import {
  Controller,
  Get,
  Param,
  Res,
  Req,
  NotFoundException,
  Logger,
} from '@nestjs/common'
import { ApiTags, ApiOperation, ApiResponse, ApiParam } from '@nestjs/swagger'
import { Request, Response } from 'express'
import { ConfigService } from '@nestjs/config'
import * as fs from 'fs'
import * as path from 'path'

@ApiTags('Downloads')
@Controller('downloads')
export class DownloadController {
  private readonly logger = new Logger(DownloadController.name)
  private readonly uploadDir: string

  constructor(private readonly configService: ConfigService) {
    this.uploadDir = this.configService.get<string>('UPLOAD_DIR') || './uploads'
  }

  @Get(':filename')
  @ApiOperation({ summary: '下载文件 (支持断点续传)' })
  @ApiParam({ name: 'filename', description: '文件名' })
  @ApiResponse({ status: 200, description: '文件内容' })
  @ApiResponse({ status: 206, description: '部分内容 (断点续传)' })
  @ApiResponse({ status: 404, description: '文件不存在' })
  @ApiResponse({ status: 416, description: 'Range 不满足' })
  async downloadFile(
    @Param('filename') filename: string,
    @Req() req: Request,
    @Res() res: Response,
  ): Promise<void> {
    // 安全检查：防止路径遍历攻击
    const sanitizedFilename = path.basename(filename)
    const filePath = path.join(this.uploadDir, sanitizedFilename)

    // 检查文件是否存在
    if (!fs.existsSync(filePath)) {
      throw new NotFoundException('文件不存在')
    }

    const stat = fs.statSync(filePath)
    const fileSize = stat.size
    const range = req.headers.range

    // 设置通用响应头
    const ext = path.extname(filename).toLowerCase()
    const mimeTypes: Record<string, string> = {
      '.apk': 'application/vnd.android.package-archive',
      '.ipa': 'application/octet-stream',
    }
    const contentType = mimeTypes[ext] || 'application/octet-stream'

    // 设置缓存和下载头
    res.setHeader('Accept-Ranges', 'bytes')
    res.setHeader('Content-Type', contentType)
    res.setHeader(
      'Content-Disposition',
      `attachment; filename="${encodeURIComponent(sanitizedFilename)}"`,
    )
    res.setHeader('Cache-Control', 'public, max-age=86400') // 缓存1天
    res.setHeader('ETag', `"${stat.mtime.getTime()}-${fileSize}"`)
    res.setHeader('Last-Modified', stat.mtime.toUTCString())

    if (range) {
      // 断点续传请求
      const parts = range.replace(/bytes=/, '').split('-')
      const start = parseInt(parts[0], 10)
      const end = parts[1] ? parseInt(parts[1], 10) : fileSize - 1

      // 验证 Range 有效性
      if (start >= fileSize || end >= fileSize || start > end) {
        res.status(416)
        res.setHeader('Content-Range', `bytes */${fileSize}`)
        res.end()
        return
      }

      const chunkSize = end - start + 1

      this.logger.log(
        `Range request: ${filename}, bytes ${start}-${end}/${fileSize}`,
      )

      res.status(206)
      res.setHeader('Content-Range', `bytes ${start}-${end}/${fileSize}`)
      res.setHeader('Content-Length', chunkSize)

      const stream = fs.createReadStream(filePath, { start, end })
      stream.pipe(res)
    } else {
      // 完整文件请求
      this.logger.log(`Full download: ${filename}, size: ${fileSize}`)

      res.setHeader('Content-Length', fileSize)

      const stream = fs.createReadStream(filePath)
      stream.pipe(res)
    }
  }
}
