import {
  Controller, Get, Post, Put, Patch, Delete, Inject,
  Param, Query, Body, UseGuards, UseInterceptors, UploadedFile, Req,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { ApiTags, ApiOperation, ApiBearerAuth, ApiConsumes } from '@nestjs/swagger';
import { JwtAuthGuard, Roles, RolesGuard, UserRole } from '@genex/common';
import { AppVersionService } from '../../../application/services/app-version.service';
import { FileStorageService } from '../../../application/services/file-storage.service';
import { PACKAGE_PARSER, IPackageParser } from '../../../domain/ports/package-parser.interface';
import { Platform } from '../../../domain/enums/platform.enum';

@ApiTags('admin-versions')
@Controller('admin/versions')
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles(UserRole.ADMIN)
@ApiBearerAuth()
export class AdminVersionController {
  constructor(
    private readonly versionService: AppVersionService,
    private readonly fileStorage: FileStorageService,
    @Inject(PACKAGE_PARSER) private readonly packageParser: IPackageParser,
  ) {}

  @Get()
  @ApiOperation({ summary: 'List app versions' })
  async listVersions(
    @Query('platform') platform?: string,
    @Query('includeDisabled') includeDisabled?: string,
  ) {
    const platformEnum = platform
      ? (platform.toUpperCase() as Platform)
      : undefined;
    const versions = await this.versionService.listVersions(
      platformEnum,
      includeDisabled === 'true',
    );
    return { code: 0, data: versions };
  }

  @Get(':id')
  @ApiOperation({ summary: 'Get version details' })
  async getVersion(@Param('id') id: string) {
    const version = await this.versionService.getVersion(id);
    return { code: 0, data: version };
  }

  @Post()
  @ApiOperation({ summary: 'Create version manually' })
  async createVersion(
    @Body() body: {
      platform: string;
      versionCode: number;
      versionName: string;
      buildNumber: string;
      downloadUrl: string;
      fileSize: string;
      fileSha256: string;
      changelog: string;
      isForceUpdate: boolean;
      minOsVersion?: string;
      releaseDate?: string;
    },
    @Req() req: any,
  ) {
    const version = await this.versionService.createVersion({
      ...body,
      platform: body.platform.toUpperCase() as Platform,
      releaseDate: body.releaseDate ? new Date(body.releaseDate) : undefined,
      createdBy: req.user?.sub,
    });
    return { code: 0, data: version };
  }

  @Post('upload')
  @UseInterceptors(FileInterceptor('file'))
  @ApiConsumes('multipart/form-data')
  @ApiOperation({ summary: 'Upload APK/IPA and create version' })
  async uploadVersion(
    @UploadedFile() file: Express.Multer.File,
    @Body() body: {
      platform: string;
      versionCode?: string;
      versionName?: string;
      buildNumber?: string;
      changelog?: string;
      isForceUpdate?: string;
      minOsVersion?: string;
      releaseDate?: string;
    },
    @Req() req: any,
  ) {
    // Parse package to extract metadata (auto-fill when not provided)
    const parsedInfo = await this.packageParser.parse(file.buffer, file.originalname);

    const platform: Platform = body.platform
      ? (body.platform.toUpperCase() as Platform)
      : (parsedInfo.platform as Platform);
    const versionCode = body.versionCode
      ? parseInt(body.versionCode, 10)
      : parsedInfo.versionCode || Date.now();
    const versionName = body.versionName || parsedInfo.versionName || '1.0.0';
    const buildNumber = body.buildNumber || versionCode.toString();

    // Upload to MinIO
    const uploadResult = await this.fileStorage.uploadFile(
      file.buffer,
      file.originalname,
      platform,
      versionName,
    );

    const version = await this.versionService.createVersion({
      platform,
      versionCode,
      versionName,
      buildNumber,
      downloadUrl: uploadResult.downloadUrl,
      fileSize: uploadResult.fileSize,
      fileSha256: uploadResult.sha256,
      changelog: body.changelog || '',
      isForceUpdate: body.isForceUpdate === 'true',
      minOsVersion: body.minOsVersion || parsedInfo.minSdkVersion,
      releaseDate: body.releaseDate ? new Date(body.releaseDate) : undefined,
      createdBy: req.user?.sub,
    });

    return { code: 0, data: version };
  }

  @Post('parse')
  @UseInterceptors(FileInterceptor('file'))
  @ApiConsumes('multipart/form-data')
  @ApiOperation({ summary: 'Parse APK/IPA without saving (preview metadata)' })
  async parsePackage(@UploadedFile() file: Express.Multer.File) {
    const info = await this.packageParser.parse(file.buffer, file.originalname);
    return { code: 0, data: info };
  }

  @Put(':id')
  @ApiOperation({ summary: 'Update version' })
  async updateVersion(
    @Param('id') id: string,
    @Body() body: any,
    @Req() req: any,
  ) {
    const version = await this.versionService.updateVersion(id, {
      ...body,
      updatedBy: req.user?.sub,
    });
    return { code: 0, data: version };
  }

  @Patch(':id/toggle')
  @ApiOperation({ summary: 'Enable/disable version' })
  async toggleVersion(
    @Param('id') id: string,
    @Body() body: { isEnabled: boolean },
  ) {
    const result = await this.versionService.toggleVersion(id, body.isEnabled);
    return { code: 0, data: result };
  }

  @Delete(':id')
  @ApiOperation({ summary: 'Delete version' })
  async deleteVersion(@Param('id') id: string) {
    const result = await this.versionService.deleteVersion(id);
    return { code: 0, data: result };
  }
}
