import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Patch,
  Body,
  Param,
  Query,
  HttpCode,
  HttpStatus,
  UseInterceptors,
  UploadedFile,
  ParseFilePipe,
  MaxFileSizeValidator,
  FileTypeValidator,
  BadRequestException,
} from '@nestjs/common'
import { FileInterceptor } from '@nestjs/platform-express'
import { ApiTags, ApiOperation, ApiBearerAuth, ApiResponse, ApiQuery, ApiConsumes, ApiBody } from '@nestjs/swagger'
import { CheckUpdateDto } from '../dto/request/check-update.dto'
import { CreateVersionDto } from '../dto/request/create-version.dto'
import { UpdateVersionDto } from '../dto/request/update-version.dto'
import { ToggleVersionDto } from '../dto/request/toggle-version.dto'
import { UploadVersionDto } from '../dto/request/upload-version.dto'
import { UpdateCheckResultDto, VersionDto } from '../dto/response/version.dto'
import { CheckUpdateHandler } from '@/application/queries/check-update/check-update.handler'
import { CheckUpdateQuery } from '@/application/queries/check-update/check-update.query'
import { ListVersionsHandler } from '@/application/queries/list-versions/list-versions.handler'
import { ListVersionsQuery } from '@/application/queries/list-versions/list-versions.query'
import { GetVersionHandler } from '@/application/queries/get-version/get-version.handler'
import { GetVersionQuery } from '@/application/queries/get-version/get-version.query'
import { CreateVersionHandler } from '@/application/commands/create-version/create-version.handler'
import { CreateVersionCommand } from '@/application/commands/create-version/create-version.command'
import { UpdateVersionHandler } from '@/application/commands/update-version/update-version.handler'
import { UpdateVersionCommand } from '@/application/commands/update-version/update-version.command'
import { DeleteVersionHandler } from '@/application/commands/delete-version/delete-version.handler'
import { DeleteVersionCommand } from '@/application/commands/delete-version/delete-version.command'
import { ToggleVersionHandler } from '@/application/commands/toggle-version/toggle-version.handler'
import { ToggleVersionCommand } from '@/application/commands/toggle-version/toggle-version.command'
import { UploadVersionHandler } from '@/application/commands/upload-version/upload-version.handler'
import { UploadVersionCommand } from '@/application/commands/upload-version/upload-version.command'
import { Platform } from '@/domain/enums/platform.enum'
import { AppVersion } from '@/domain/entities/app-version.entity'
import { PackageParserService } from '@/infrastructure/parsers/package-parser.service'

// Maximum file size: 500MB
const MAX_FILE_SIZE = 500 * 1024 * 1024

@ApiTags('Version Management')
@Controller('versions')
export class VersionController {
  constructor(
    private readonly checkUpdateHandler: CheckUpdateHandler,
    private readonly listVersionsHandler: ListVersionsHandler,
    private readonly getVersionHandler: GetVersionHandler,
    private readonly createVersionHandler: CreateVersionHandler,
    private readonly updateVersionHandler: UpdateVersionHandler,
    private readonly deleteVersionHandler: DeleteVersionHandler,
    private readonly toggleVersionHandler: ToggleVersionHandler,
    private readonly uploadVersionHandler: UploadVersionHandler,
    private readonly packageParserService: PackageParserService,
  ) {}

  private toVersionDto(version: AppVersion): VersionDto {
    return {
      id: version.id,
      platform: version.platform,
      versionCode: version.versionCode.value,
      versionName: version.versionName.value,
      buildNumber: version.buildNumber.value,
      downloadUrl: version.downloadUrl.value,
      fileSize: version.fileSize.bytes.toString(),
      fileSha256: version.fileSha256.value,
      changelog: version.changelog.value,
      isForceUpdate: version.isForceUpdate,
      isEnabled: version.isEnabled,
      minOsVersion: version.minOsVersion?.value ?? null,
      releaseDate: version.releaseDate,
      createdAt: version.createdAt,
      updatedAt: version.updatedAt,
    }
  }

  @Get('check-update')
  @ApiOperation({ summary: '检查更新 (供移动端调用)' })
  @ApiResponse({ status: 200, type: UpdateCheckResultDto })
  async checkUpdate(@Query() dto: CheckUpdateDto): Promise<UpdateCheckResultDto> {
    const query = new CheckUpdateQuery(dto.platform, dto.currentVersionCode)
    const result = await this.checkUpdateHandler.execute(query)

    return {
      hasUpdate: result.hasUpdate,
      isForceUpdate: result.isForceUpdate,
      latestVersion: result.latestVersion
        ? {
            ...result.latestVersion,
            fileSize: result.latestVersion.fileSize.toString(),
          }
        : null,
    }
  }

  @Get()
  @ApiOperation({ summary: '获取版本列表 (管理员)' })
  @ApiBearerAuth()
  @ApiQuery({ name: 'platform', required: false, enum: ['android', 'ios', 'ANDROID', 'IOS'], description: '筛选平台' })
  @ApiQuery({ name: 'includeDisabled', required: false, type: Boolean, description: '是否包含已禁用版本' })
  @ApiResponse({ status: 200, type: [VersionDto] })
  async listVersions(
    @Query('platform') platform?: string,
    @Query('includeDisabled') includeDisabled?: string,
  ): Promise<VersionDto[]> {
    // Convert platform to uppercase enum value
    const platformEnum = platform ? (platform.toUpperCase() as Platform) : undefined
    const query = new ListVersionsQuery(platformEnum, includeDisabled === 'true')
    const versions = await this.listVersionsHandler.execute(query)
    return versions.map((v) => this.toVersionDto(v))
  }

  @Get(':id')
  @ApiOperation({ summary: '获取版本详情 (管理员)' })
  @ApiBearerAuth()
  @ApiResponse({ status: 200, type: VersionDto })
  @ApiResponse({ status: 404, description: '版本不存在' })
  async getVersion(@Param('id') id: string): Promise<VersionDto> {
    const query = new GetVersionQuery(id)
    const version = await this.getVersionHandler.execute(query)
    return this.toVersionDto(version)
  }

  @Post()
  @ApiOperation({ summary: '创建新版本 (管理员)' })
  @ApiBearerAuth()
  @ApiResponse({ status: 201, type: VersionDto })
  async createVersion(@Body() dto: CreateVersionDto): Promise<VersionDto> {
    const command = new CreateVersionCommand(
      dto.platform,
      dto.versionCode,
      dto.versionName,
      dto.buildNumber,
      dto.downloadUrl,
      BigInt(dto.fileSize),
      dto.fileSha256,
      dto.changelog,
      dto.isForceUpdate,
      dto.minOsVersion ?? null,
      dto.releaseDate ? new Date(dto.releaseDate) : null,
      'admin', // TODO: Get from JWT token
    )

    const version = await this.createVersionHandler.execute(command)
    return this.toVersionDto(version)
  }

  @Put(':id')
  @ApiOperation({ summary: '更新版本 (管理员)' })
  @ApiBearerAuth()
  @ApiResponse({ status: 200, type: VersionDto })
  @ApiResponse({ status: 404, description: '版本不存在' })
  async updateVersion(@Param('id') id: string, @Body() dto: UpdateVersionDto): Promise<VersionDto> {
    const command = new UpdateVersionCommand(
      id,
      dto.downloadUrl,
      dto.fileSize ? BigInt(dto.fileSize) : undefined,
      dto.fileSha256,
      dto.changelog,
      dto.isForceUpdate,
      dto.minOsVersion,
      dto.releaseDate ? new Date(dto.releaseDate) : dto.releaseDate === null ? null : undefined,
      'admin', // TODO: Get from JWT token
    )

    const version = await this.updateVersionHandler.execute(command)
    return this.toVersionDto(version)
  }

  @Delete(':id')
  @HttpCode(HttpStatus.NO_CONTENT)
  @ApiOperation({ summary: '删除版本 (管理员)' })
  @ApiBearerAuth()
  @ApiResponse({ status: 204, description: '删除成功' })
  @ApiResponse({ status: 404, description: '版本不存在' })
  async deleteVersion(@Param('id') id: string): Promise<void> {
    const command = new DeleteVersionCommand(id)
    await this.deleteVersionHandler.execute(command)
  }

  @Patch(':id/toggle')
  @ApiOperation({ summary: '启用/禁用版本 (管理员)' })
  @ApiBearerAuth()
  @ApiResponse({ status: 200, description: '操作成功' })
  @ApiResponse({ status: 404, description: '版本不存在' })
  async toggleVersion(@Param('id') id: string, @Body() dto: ToggleVersionDto): Promise<{ success: boolean }> {
    const command = new ToggleVersionCommand(id, dto.isEnabled)
    await this.toggleVersionHandler.execute(command)
    return { success: true }
  }

  @Post('parse')
  @UseInterceptors(FileInterceptor('file'))
  @ApiOperation({ summary: '解析APK/IPA包信息 (不保存)' })
  @ApiBearerAuth()
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      required: ['file', 'platform'],
      properties: {
        file: {
          type: 'string',
          format: 'binary',
          description: 'APK或IPA安装包文件',
        },
        platform: {
          type: 'string',
          enum: ['android', 'ios'],
          description: '平台',
        },
      },
    },
  })
  @ApiResponse({
    status: 200,
    description: '解析成功',
    schema: {
      type: 'object',
      properties: {
        packageName: { type: 'string', description: '包名' },
        versionCode: { type: 'number', description: '版本号' },
        versionName: { type: 'string', description: '版本名称' },
        minSdkVersion: { type: 'string', description: '最低SDK版本' },
        targetSdkVersion: { type: 'string', description: '目标SDK版本' },
      },
    },
  })
  @ApiResponse({ status: 400, description: '解析失败' })
  async parsePackage(
    @UploadedFile(
      new ParseFilePipe({
        validators: [new MaxFileSizeValidator({ maxSize: MAX_FILE_SIZE })],
        fileIsRequired: true,
      }),
    )
    file: Express.Multer.File,
    @Body('platform') platform: Platform,
  ): Promise<{
    packageName: string
    versionCode: number
    versionName: string
    minSdkVersion?: string
    targetSdkVersion?: string
  }> {
    // Validate file extension
    const ext = file.originalname.toLowerCase().split('.').pop()
    if (platform === Platform.ANDROID && ext !== 'apk') {
      throw new BadRequestException('Android平台只能上传APK文件')
    }
    if (platform === Platform.IOS && ext !== 'ipa') {
      throw new BadRequestException('iOS平台只能上传IPA文件')
    }

    const parsed = await this.packageParserService.parsePackage(file.buffer, platform)
    if (!parsed) {
      throw new BadRequestException('无法解析安装包信息，请确认文件格式正确')
    }

    return parsed
  }

  @Post('upload')
  @UseInterceptors(FileInterceptor('file'))
  @ApiOperation({ summary: '上传APK/IPA并创建版本 (管理员)' })
  @ApiBearerAuth()
  @ApiConsumes('multipart/form-data')
  @ApiBody({
    schema: {
      type: 'object',
      required: ['file', 'platform', 'changelog'],
      properties: {
        file: {
          type: 'string',
          format: 'binary',
          description: 'APK或IPA安装包文件',
        },
        platform: {
          type: 'string',
          enum: ['android', 'ios'],
          description: '平台',
        },
        versionCode: {
          type: 'integer',
          description: '版本号 (可选，可从APK/IPA自动检测)',
          minimum: 1,
        },
        versionName: {
          type: 'string',
          description: '版本名称 (可选，可从APK/IPA自动检测，格式: x.y.z)',
        },
        buildNumber: {
          type: 'string',
          description: '构建号 (可选，可从APK/IPA自动检测)',
        },
        changelog: {
          type: 'string',
          description: '更新日志',
        },
        isForceUpdate: {
          type: 'boolean',
          description: '是否强制更新',
          default: false,
        },
        minOsVersion: {
          type: 'string',
          description: '最低操作系统版本 (可选，可从APK/IPA自动检测)',
        },
        releaseDate: {
          type: 'string',
          format: 'date-time',
          description: '发布日期',
        },
      },
    },
  })
  @ApiResponse({ status: 201, type: VersionDto })
  @ApiResponse({ status: 400, description: '无效的文件或参数' })
  async uploadVersion(
    @UploadedFile(
      new ParseFilePipe({
        validators: [new MaxFileSizeValidator({ maxSize: MAX_FILE_SIZE })],
        fileIsRequired: true,
      }),
    )
    file: Express.Multer.File,
    @Body() dto: UploadVersionDto,
  ): Promise<VersionDto> {
    // Debug: log isForceUpdate value
    console.log('[VersionController] uploadVersion - dto.isForceUpdate:', dto.isForceUpdate, 'type:', typeof dto.isForceUpdate)

    // Validate file extension
    const ext = file.originalname.toLowerCase().split('.').pop()
    if (dto.platform === Platform.ANDROID && ext !== 'apk') {
      throw new BadRequestException('Android平台只能上传APK文件')
    }
    if (dto.platform === Platform.IOS && ext !== 'ipa') {
      throw new BadRequestException('iOS平台只能上传IPA文件')
    }

    const command = new UploadVersionCommand(
      dto.platform,
      file.buffer,
      file.originalname,
      dto.changelog ?? '',
      dto.isForceUpdate ?? false,
      'admin', // TODO: Get from JWT token
      dto.versionCode,
      dto.versionName,
      dto.buildNumber,
      dto.minOsVersion,
      dto.releaseDate ? new Date(dto.releaseDate) : null,
    )

    const version = await this.uploadVersionHandler.execute(command)
    return this.toVersionDto(version)
  }
}
