/**
 * 合同管理内部 API 控制器
 * [2026-02-05] 新增：用于管理后台合同管理功能
 * 回滚方式：删除此文件并从 api.module.ts 中移除引用
 */

import {
  Controller,
  Get,
  Param,
  Query,
  Logger,
  Res,
  StreamableFile,
  NotFoundException,
} from '@nestjs/common';
import { Response } from 'express';
import { ApiTags, ApiOperation, ApiQuery, ApiResponse, ApiParam } from '@nestjs/swagger';
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';
import { MinioStorageService } from '../../infrastructure/storage/minio-storage.service';
import { ContractSigningStatus } from '../../domain/value-objects/contract-signing-status.enum';

/**
 * 合同查询 DTO
 */
interface ContractDto {
  orderNo: string;
  contractNo: string;
  userId: string;
  accountSequence: string;
  userRealName: string | null;
  userPhoneNumber: string | null;
  treeCount: number;
  totalAmount: number;
  provinceCode: string;
  provinceName: string;
  cityCode: string;
  cityName: string;
  status: string;
  signedAt: string | null;
  signedPdfUrl: string | null;
  createdAt: string;
}

/**
 * 合同列表响应
 */
interface ContractsListResponse {
  items: ContractDto[];
  total: number;
  page: number;
  pageSize: number;
  totalPages: number;
}

/**
 * 合同统计响应
 */
interface ContractStatisticsResponse {
  totalContracts: number;
  signedContracts: number;
  pendingContracts: number;
  expiredContracts: number;
}

/**
 * 合同管理内部 API 控制器
 * 用于服务间通信，不需要 JWT 认证
 */
@ApiTags('Internal - Contract Admin')
@Controller('planting/internal/contracts')
export class ContractAdminController {
  private readonly logger = new Logger(ContractAdminController.name);

  constructor(
    private readonly prisma: PrismaService,
    private readonly minioStorage: MinioStorageService,
  ) {}

  /**
   * 查询已签署合同列表
   */
  @Get()
  @ApiOperation({ summary: '查询合同列表（内部接口）' })
  @ApiQuery({ name: 'accountSequences', required: false, description: '账户序列号列表（逗号分隔）' })
  @ApiQuery({ name: 'signedAfter', required: false, description: '签署时间起始（ISO格式）' })
  @ApiQuery({ name: 'signedBefore', required: false, description: '签署时间结束（ISO格式）' })
  @ApiQuery({ name: 'provinceCode', required: false, description: '省份代码' })
  @ApiQuery({ name: 'cityCode', required: false, description: '城市代码' })
  @ApiQuery({ name: 'status', required: false, description: '合同状态' })
  @ApiQuery({ name: 'page', required: false, description: '页码，默认1' })
  @ApiQuery({ name: 'pageSize', required: false, description: '每页条数，默认50' })
  @ApiQuery({ name: 'orderBy', required: false, description: '排序字段：signedAt/createdAt，默认signedAt' })
  @ApiQuery({ name: 'orderDir', required: false, description: '排序方向：asc/desc，默认desc' })
  @ApiResponse({ status: 200, description: '合同列表' })
  async getContracts(
    @Query('accountSequences') accountSequences?: string,
    @Query('signedAfter') signedAfter?: string,
    @Query('signedBefore') signedBefore?: string,
    @Query('provinceCode') provinceCode?: string,
    @Query('cityCode') cityCode?: string,
    @Query('status') status?: string,
    @Query('page') page?: string,
    @Query('pageSize') pageSize?: string,
    @Query('orderBy') orderBy?: string,
    @Query('orderDir') orderDir?: string,
  ): Promise<ContractsListResponse> {
    this.logger.log(`========== internal/contracts 查询请求 ==========`);

    const pageNum = page ? parseInt(page, 10) : 1;
    const pageSizeNum = pageSize ? parseInt(pageSize, 10) : 50;
    const skip = (pageNum - 1) * pageSizeNum;

    // 构建查询条件
    const where: Record<string, unknown> = {};

    // 账户序列号过滤
    if (accountSequences) {
      const sequences = accountSequences.split(',').map(s => s.trim());
      where.accountSequence = { in: sequences };
    }

    // 签署时间过滤
    if (signedAfter || signedBefore) {
      where.signedAt = {};
      if (signedAfter) {
        (where.signedAt as Record<string, Date>).gte = new Date(signedAfter);
      }
      if (signedBefore) {
        (where.signedAt as Record<string, Date>).lte = new Date(signedBefore);
      }
    }

    // 省份过滤
    if (provinceCode) {
      where.provinceCode = provinceCode;
    }

    // 城市过滤
    if (cityCode) {
      where.cityCode = cityCode;
    }

    // 状态过滤
    if (status) {
      where.status = status;
    } else {
      // 默认只查询已签署的合同
      where.status = ContractSigningStatus.SIGNED;
    }

    // 排序
    const sortField = orderBy === 'createdAt' ? 'createdAt' : 'signedAt';
    const sortDir = orderDir === 'asc' ? 'asc' : 'desc';

    this.logger.log(`查询条件: ${JSON.stringify(where)}`);

    // 查询总数
    const total = await this.prisma.contractSigningTask.count({ where });

    // 查询列表
    const tasks = await this.prisma.contractSigningTask.findMany({
      where,
      skip,
      take: pageSizeNum,
      orderBy: { [sortField]: sortDir },
      select: {
        orderNo: true,
        contractNo: true,
        userId: true,
        accountSequence: true,
        userRealName: true,
        userPhoneNumber: true,
        treeCount: true,
        totalAmount: true,
        provinceCode: true,
        provinceName: true,
        cityCode: true,
        cityName: true,
        status: true,
        signedAt: true,
        signedPdfUrl: true,
        createdAt: true,
      },
    });

    const items: ContractDto[] = tasks.map(task => ({
      orderNo: task.orderNo,
      contractNo: task.contractNo,
      userId: task.userId.toString(),
      accountSequence: task.accountSequence,
      userRealName: task.userRealName,
      userPhoneNumber: task.userPhoneNumber,
      treeCount: task.treeCount,
      totalAmount: Number(task.totalAmount),
      provinceCode: task.provinceCode,
      provinceName: task.provinceName,
      cityCode: task.cityCode,
      cityName: task.cityName,
      status: task.status,
      signedAt: task.signedAt?.toISOString() ?? null,
      signedPdfUrl: task.signedPdfUrl,
      createdAt: task.createdAt.toISOString(),
    }));

    this.logger.log(`查询结果: total=${total}, page=${pageNum}, pageSize=${pageSizeNum}`);

    return {
      items,
      total,
      page: pageNum,
      pageSize: pageSizeNum,
      totalPages: Math.ceil(total / pageSizeNum),
    };
  }

  /**
   * 获取合同统计信息
   */
  @Get('statistics')
  @ApiOperation({ summary: '获取合同统计信息（内部接口）' })
  @ApiQuery({ name: 'provinceCode', required: false, description: '省份代码' })
  @ApiQuery({ name: 'cityCode', required: false, description: '城市代码' })
  @ApiResponse({ status: 200, description: '合同统计' })
  async getStatistics(
    @Query('provinceCode') provinceCode?: string,
    @Query('cityCode') cityCode?: string,
  ): Promise<ContractStatisticsResponse> {
    this.logger.log(`========== internal/contracts/statistics 请求 ==========`);

    const where: Record<string, unknown> = {};
    if (provinceCode) where.provinceCode = provinceCode;
    if (cityCode) where.cityCode = cityCode;

    // 并行查询各状态数量
    const [totalContracts, signedContracts, pendingContracts, expiredContracts] = await Promise.all([
      this.prisma.contractSigningTask.count({ where }),
      this.prisma.contractSigningTask.count({ where: { ...where, status: ContractSigningStatus.SIGNED } }),
      this.prisma.contractSigningTask.count({
        where: {
          ...where,
          status: { in: [ContractSigningStatus.PENDING, ContractSigningStatus.SCROLLED, ContractSigningStatus.ACKNOWLEDGED] },
        },
      }),
      this.prisma.contractSigningTask.count({ where: { ...where, status: ContractSigningStatus.UNSIGNED_TIMEOUT } }),
    ]);

    return {
      totalContracts,
      signedContracts,
      pendingContracts,
      expiredContracts,
    };
  }

  /**
   * 获取单个合同详情
   */
  @Get(':orderNo')
  @ApiOperation({ summary: '获取合同详情（内部接口）' })
  @ApiParam({ name: 'orderNo', description: '订单号' })
  @ApiResponse({ status: 200, description: '合同详情' })
  @ApiResponse({ status: 404, description: '合同不存在' })
  async getContract(@Param('orderNo') orderNo: string): Promise<ContractDto> {
    this.logger.log(`========== internal/contracts/${orderNo} 请求 ==========`);

    const task = await this.prisma.contractSigningTask.findUnique({
      where: { orderNo },
      select: {
        orderNo: true,
        contractNo: true,
        userId: true,
        accountSequence: true,
        userRealName: true,
        userPhoneNumber: true,
        treeCount: true,
        totalAmount: true,
        provinceCode: true,
        provinceName: true,
        cityCode: true,
        cityName: true,
        status: true,
        signedAt: true,
        signedPdfUrl: true,
        createdAt: true,
      },
    });

    if (!task) {
      throw new NotFoundException(`合同不存在: ${orderNo}`);
    }

    return {
      orderNo: task.orderNo,
      contractNo: task.contractNo,
      userId: task.userId.toString(),
      accountSequence: task.accountSequence,
      userRealName: task.userRealName,
      userPhoneNumber: task.userPhoneNumber,
      treeCount: task.treeCount,
      totalAmount: Number(task.totalAmount),
      provinceCode: task.provinceCode,
      provinceName: task.provinceName,
      cityCode: task.cityCode,
      cityName: task.cityName,
      status: task.status,
      signedAt: task.signedAt?.toISOString() ?? null,
      signedPdfUrl: task.signedPdfUrl,
      createdAt: task.createdAt.toISOString(),
    };
  }

  /**
   * 下载合同 PDF
   */
  @Get(':orderNo/pdf')
  @ApiOperation({ summary: '下载合同 PDF（内部接口）' })
  @ApiParam({ name: 'orderNo', description: '订单号' })
  @ApiResponse({ status: 200, description: 'PDF 文件流' })
  @ApiResponse({ status: 404, description: '合同或PDF不存在' })
  async downloadPdf(
    @Param('orderNo') orderNo: string,
    @Res({ passthrough: true }) res: Response,
  ): Promise<StreamableFile> {
    this.logger.log(`========== internal/contracts/${orderNo}/pdf 下载请求 ==========`);

    // 查询合同任务
    const task = await this.prisma.contractSigningTask.findUnique({
      where: { orderNo },
      select: {
        contractNo: true,
        userRealName: true,
        treeCount: true,
        provinceName: true,
        cityName: true,
        signedPdfUrl: true,
        status: true,
      },
    });

    if (!task) {
      throw new NotFoundException(`合同不存在: ${orderNo}`);
    }

    if (!task.signedPdfUrl) {
      throw new NotFoundException(`合同PDF不存在: ${orderNo}，状态: ${task.status}`);
    }

    // 从 MinIO 下载 PDF
    const pdfBuffer = await this.minioStorage.downloadSignedPdf(task.signedPdfUrl);

    // 生成文件名
    const safeRealName = task.userRealName?.replace(/[\/\\:*?"<>|]/g, '_') || '未知';
    const fileName = `${task.contractNo}_${safeRealName}_${task.treeCount}棵_${task.provinceName}${task.cityName}.pdf`;
    const encodedFileName = encodeURIComponent(fileName);

    // 设置响应头
    res.set({
      'Content-Type': 'application/pdf',
      'Content-Disposition': `attachment; filename*=UTF-8''${encodedFileName}`,
      'Content-Length': pdfBuffer.length,
      'Accept-Ranges': 'bytes',
    });

    this.logger.log(`下载合同 PDF: ${fileName}, size=${pdfBuffer.length}`);

    return new StreamableFile(pdfBuffer);
  }
}
