import {
  Controller,
  Get,
  Post,
  Put,
  Delete,
  Patch,
  Body,
  Param,
  Query,
  HttpCode,
  HttpStatus,
  UseInterceptors,
  UploadedFile,
  ParseFilePipe,
  MaxFileSizeValidator,
  BadRequestException,
} from '@nestjs/common'
import { FileInterceptor } from '@nestjs/platform-express'
import {
  ApiTags,
  ApiOperation,
  ApiBearerAuth,
  ApiResponse,
  ApiQuery,
  ApiConsumes,
  ApiBody,
} from '@nestjs/swagger'
import { VersionService } from '../../application/services/version.service'
import { Platform, AppVersion } from '../../domain/version-management'
import {
  CreateVersionDto,
  UploadVersionDto,
  UpdateVersionDto,
  ToggleVersionDto,
  VersionResponseDto,
} from '../dto/version'

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

@ApiTags('Version Management')
@Controller('versions')
export class VersionController {
  constructor(private readonly versionService: VersionService) {}

  private toVersionDto(version: AppVersion): VersionResponseDto {
    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()
  @ApiOperation({ summary: '获取版本列表' })
  @ApiBearerAuth()
  @ApiQuery({ name: 'platform', required: false, enum: ['ANDROID', 'IOS', 'android', 'ios'] })
  @ApiQuery({ name: 'includeDisabled', required: false, type: Boolean })
  @ApiResponse({ status: 200, type: [VersionResponseDto] })
  async listVersions(
    @Query('platform') platform?: string,
    @Query('includeDisabled') includeDisabled?: string,
  ): Promise<VersionResponseDto[]> {
    const platformEnum = platform ? (platform.toUpperCase() as Platform) : undefined
    const versions = await this.versionService.findAll(platformEnum, includeDisabled === 'true')
    return versions.map((v) => this.toVersionDto(v))
  }

  @Get(':id')
  @ApiOperation({ summary: '获取版本详情' })
  @ApiBearerAuth()
  @ApiResponse({ status: 200, type: VersionResponseDto })
  @ApiResponse({ status: 404, description: '版本不存在' })
  async getVersion(@Param('id') id: string): Promise<VersionResponseDto> {
    const version = await this.versionService.findById(id)
    return this.toVersionDto(version)
  }

  @Post()
  @ApiOperation({ summary: '创建新版本' })
  @ApiBearerAuth()
  @ApiResponse({ status: 201, type: VersionResponseDto })
  async createVersion(@Body() dto: CreateVersionDto): Promise<VersionResponseDto> {
    const version = await this.versionService.create({
      ...dto,
      releaseDate: dto.releaseDate ? new Date(dto.releaseDate) : undefined,
      createdBy: 'admin', // TODO: Get from JWT token
    })
    return this.toVersionDto(version)
  }

  @Put(':id')
  @ApiOperation({ summary: '更新版本' })
  @ApiBearerAuth()
  @ApiResponse({ status: 200, type: VersionResponseDto })
  @ApiResponse({ status: 404, description: '版本不存在' })
  async updateVersion(
    @Param('id') id: string,
    @Body() dto: UpdateVersionDto,
  ): Promise<VersionResponseDto> {
    const version = await this.versionService.update(id, {
      ...dto,
      releaseDate: dto.releaseDate ? new Date(dto.releaseDate) : dto.releaseDate === null ? null : undefined,
      updatedBy: 'admin', // TODO: Get from JWT token
    })
    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> {
    await this.versionService.delete(id)
  }

  @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 }> {
    await this.versionService.toggleEnabled(id, dto.isEnabled, 'admin')
    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', 'ANDROID', 'IOS'],
          description: '平台',
        },
      },
    },
  })
  @ApiResponse({ status: 200, description: '解析成功' })
  @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: string,
  ): Promise<{
    packageName: string
    versionCode: number
    versionName: string
    minSdkVersion?: string
    targetSdkVersion?: string
  }> {
    const platformEnum = platform.toUpperCase() as Platform

    // 验证文件扩展名
    const ext = file.originalname.toLowerCase().split('.').pop()
    if (platformEnum === Platform.ANDROID && ext !== 'apk') {
      throw new BadRequestException('Android平台只能上传APK文件')
    }
    if (platformEnum === Platform.IOS && ext !== 'ipa') {
      throw new BadRequestException('iOS平台只能上传IPA文件')
    }

    const parsed = await this.versionService.parsePackage(file.buffer, platformEnum)
    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', 'ANDROID', 'IOS'],
          description: '平台',
        },
        versionCode: {
          type: 'integer',
          description: '版本号 (可选，可从APK/IPA自动检测)',
        },
        versionName: {
          type: 'string',
          description: '版本名称 (可选，可从APK/IPA自动检测)',
        },
        buildNumber: {
          type: 'string',
          description: '构建号 (可选)',
        },
        changelog: {
          type: 'string',
          description: '更新日志',
        },
        isForceUpdate: {
          type: 'boolean',
          description: '是否强制更新',
          default: false,
        },
        minOsVersion: {
          type: 'string',
          description: '最低操作系统版本 (可选)',
        },
        releaseDate: {
          type: 'string',
          format: 'date-time',
          description: '发布日期',
        },
      },
    },
  })
  @ApiResponse({ status: 201, type: VersionResponseDto })
  @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<VersionResponseDto> {
    // 验证文件扩展名
    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 version = await this.versionService.upload({
      platform: dto.platform,
      fileBuffer: file.buffer,
      originalFilename: file.originalname,
      changelog: dto.changelog ?? '',
      isForceUpdate: dto.isForceUpdate ?? false,
      createdBy: 'admin', // TODO: Get from JWT token
      versionCode: dto.versionCode,
      versionName: dto.versionName,
      buildNumber: dto.buildNumber,
      minOsVersion: dto.minOsVersion,
      releaseDate: dto.releaseDate ? new Date(dto.releaseDate) : undefined,
    })

    return this.toVersionDto(version)
  }
}
