import { Injectable, Logger, HttpException, HttpStatus } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { PrismaService } from '../../infrastructure/persistence/prisma/prisma.service';

/**
 * Excel 中的单行数据
 */
export interface BatchMiningItem {
  accountSequence: string;    // 注册ID (用户账号序列号)
  treeCount: number;          // 认种量（棵）
  miningStartDate: string;    // 挖矿开始时间
  batch: number;              // 批次号
  preMineDays: number;        // 授权提前挖的天数（该批次比后续批次提前的天数）
  totalMiningDays: number;    // 总挖矿天数（从挖矿开始日期到今天）
  remark?: string;            // 备注
}

/**
 * 批量补发请求
 */
export interface BatchMiningRequest {
  items: BatchMiningItem[];
  operatorId: string;
  operatorName: string;
  reason: string;
}

/**
 * 批量补发挖矿服务 - 管理后台层
 * 负责调用 mining-service 的内部 API
 */
@Injectable()
export class BatchMiningService {
  private readonly logger = new Logger(BatchMiningService.name);
  private readonly miningServiceUrl: string;

  constructor(
    private readonly prisma: PrismaService,
    private readonly configService: ConfigService,
  ) {
    this.miningServiceUrl = this.configService.get<string>(
      'MINING_SERVICE_URL',
      'http://localhost:3021',
    );
  }

  /**
   * 获取批量补发状态
   */
  async getStatus(): Promise<any> {
    const url = `${this.miningServiceUrl}/api/v2/mining/admin/batch-mining/status`;
    this.logger.log(`[getStatus] 开始获取批量补发状态, URL: ${url}`);

    try {
      this.logger.log(`[getStatus] 发送 GET 请求...`);
      const response = await fetch(url, {
        method: 'GET',
        headers: { 'Content-Type': 'application/json' },
      });

      this.logger.log(`[getStatus] 响应状态码: ${response.status}`);
      const result = await response.json();
      this.logger.log(`[getStatus] 响应数据: ${JSON.stringify(result)}`);

      if (!response.ok) {
        this.logger.error(`[getStatus] 请求失败: ${result.message || '未知错误'}`);
        throw new HttpException(
          result.message || '获取状态失败',
          response.status,
        );
      }

      // mining-service 使用 TransformInterceptor 包装响应为 { success, data, timestamp }
      const data = result.data || result;
      this.logger.log(`[getStatus] 成功获取状态: hasExecuted=${data.hasExecuted}`);
      return data;
    } catch (error) {
      if (error instanceof HttpException) {
        throw error;
      }
      this.logger.error(`[getStatus] 调用 mining-service 失败:`, error);
      throw new HttpException(
        `调用 mining-service 失败: ${error instanceof Error ? error.message : error}`,
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 预览批量补发（计算但不执行）
   */
  async preview(items: BatchMiningItem[]): Promise<any> {
    const url = `${this.miningServiceUrl}/api/v2/mining/admin/batch-mining/preview`;
    this.logger.log(`[preview] 开始预览批量补发, URL: ${url}`);
    this.logger.log(`[preview] 数据条数: ${items.length}`);
    this.logger.log(`[preview] 前3条数据: ${JSON.stringify(items.slice(0, 3))}`);

    try {
      this.logger.log(`[preview] 发送 POST 请求...`);
      const response = await fetch(url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ items }),
      });

      this.logger.log(`[preview] 响应状态码: ${response.status}`);
      const result = await response.json();

      if (!response.ok) {
        this.logger.error(`[preview] 请求失败: ${result.message || '未知错误'}`);
        throw new HttpException(
          result.message || '预览失败',
          response.status,
        );
      }

      // mining-service 使用 TransformInterceptor 包装响应为 { success, data, timestamp }
      const data = result.data || result;
      this.logger.log(`[preview] 响应数据概要: totalBatches=${data.totalBatches}, totalUsers=${data.totalUsers}, grandTotalAmount=${data.grandTotalAmount}`);
      this.logger.log(`[preview] 预览成功`);
      return data;
    } catch (error) {
      if (error instanceof HttpException) {
        throw error;
      }
      this.logger.error(`[preview] 调用 mining-service 失败:`, error);
      throw new HttpException(
        `调用 mining-service 失败: ${error instanceof Error ? error.message : error}`,
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 执行批量补发
   */
  async execute(
    request: BatchMiningRequest,
    adminId: string,
    ipAddress?: string,
    userAgent?: string,
  ): Promise<any> {
    const url = `${this.miningServiceUrl}/api/v2/mining/admin/batch-mining/execute`;
    this.logger.log(`[execute] 开始执行批量补发, URL: ${url}`);
    this.logger.log(`[execute] 操作人: ${request.operatorName} (${request.operatorId})`);
    this.logger.log(`[execute] 原因: ${request.reason}`);
    this.logger.log(`[execute] 数据条数: ${request.items.length}`);

    try {
      this.logger.log(`[execute] 发送 POST 请求...`);
      const response = await fetch(url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(request),
      });

      this.logger.log(`[execute] 响应状态码: ${response.status}`);
      const result = await response.json();
      this.logger.log(`[execute] 响应数据: ${JSON.stringify(result)}`);

      if (!response.ok) {
        this.logger.error(`[execute] 请求失败: ${result.message || '未知错误'}`);
        throw new HttpException(
          result.message || '执行失败',
          response.status,
        );
      }

      // mining-service 使用 TransformInterceptor 包装响应为 { success, data, timestamp }
      const data = result.data || result;

      // 记录审计日志（失败不影响返回结果，因为实际操作已完成）
      this.logger.log(`[execute] 记录审计日志...`);
      try {
        await this.prisma.auditLog.create({
          data: {
            adminId,
            action: 'CREATE',
            resource: 'BATCH_MINING',
            resourceId: data.batchId,
            newValue: {
              totalUsers: data.totalUsers,
              successCount: data.successCount,
              failedCount: data.failedCount,
              totalAmount: data.totalAmount,
              reason: request.reason,
            },
            ipAddress,
            userAgent,
          },
        });
        this.logger.log(`[execute] 审计日志记录成功`);
      } catch (auditError) {
        // 审计日志失败不应该影响返回结果，因为批量补发已经成功执行
        this.logger.error(`[execute] 审计日志记录失败（不影响返回结果）:`, auditError);
      }

      this.logger.log(
        `[execute] 批量补发执行成功: admin=${adminId}, total=${data.totalUsers}, success=${data.successCount}, amount=${data.totalAmount}`,
      );

      return data;
    } catch (error) {
      if (error instanceof HttpException) {
        throw error;
      }
      this.logger.error(`[execute] 调用 mining-service 失败:`, error);
      throw new HttpException(
        `调用 mining-service 失败: ${error instanceof Error ? error.message : error}`,
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 获取执行记录
   */
  async getExecution(): Promise<any> {
    const url = `${this.miningServiceUrl}/api/v2/mining/admin/batch-mining/execution`;
    this.logger.log(`[getExecution] 开始获取执行记录, URL: ${url}`);

    try {
      this.logger.log(`[getExecution] 发送 GET 请求...`);
      const response = await fetch(url, {
        method: 'GET',
        headers: { 'Content-Type': 'application/json' },
      });

      this.logger.log(`[getExecution] 响应状态码: ${response.status}`);

      if (response.status === 404) {
        this.logger.log(`[getExecution] 未找到执行记录 (404)`);
        return null;
      }

      const result = await response.json();

      if (!response.ok) {
        this.logger.error(`[getExecution] 请求失败: ${result.message || '未知错误'}`);
        throw new HttpException(
          result.message || '获取记录失败',
          response.status,
        );
      }

      // mining-service 使用 TransformInterceptor 包装响应为 { success, data, timestamp }
      const data = result.data || result;
      this.logger.log(`[getExecution] 响应数据概要: id=${data.id}, totalUsers=${data.totalUsers}`);
      this.logger.log(`[getExecution] 成功获取执行记录`);
      return data;
    } catch (error) {
      if (error instanceof HttpException) {
        throw error;
      }
      this.logger.error(`[getExecution] 调用 mining-service 失败:`, error);
      throw new HttpException(
        `调用 mining-service 失败: ${error instanceof Error ? error.message : error}`,
        HttpStatus.INTERNAL_SERVER_ERROR,
      );
    }
  }

  /**
   * 解析 Excel 文件数据
   * Excel 格式:
   * 用户ID | 认种数量 | 认种时间 | 挖矿开始时间 | 批次 | 授权提前挖的天数 | 备注
   */
  parseExcelData(rows: any[]): BatchMiningItem[] {
    this.logger.log(`[parseExcelData] 开始解析 Excel 数据, 总行数: ${rows.length}`);
    const items: BatchMiningItem[] = [];
    const today = new Date();
    today.setHours(0, 0, 0, 0);

    // 打印前5行原始数据用于调试
    this.logger.log(`[parseExcelData] 前5行原始数据:`);
    for (let i = 0; i < Math.min(5, rows.length); i++) {
      this.logger.log(`[parseExcelData] 行${i}: ${JSON.stringify(rows[i])}`);
    }

    for (let i = 0; i < rows.length; i++) {
      const row = rows[i];

      // 跳过空行
      if (!row || !row[0]) {
        this.logger.debug(`[parseExcelData] 跳过行 ${i + 1}: 空行`);
        continue;
      }

      // 跳过标题行
      const firstCell = String(row[0]).trim();
      if (firstCell === '用户ID' || firstCell === '注册ID' || firstCell === '序号') {
        this.logger.debug(`[parseExcelData] 跳过行 ${i + 1}: 标题行`);
        continue;
      }

      // Excel 格式：序号 | 注册ID | 认种量（棵）| 挖矿开始时间 | 批次 | 授权提前挖的天数 | 备注
      // 索引：      0      1         2              3          4           5            6

      // 获取用户ID (第二列，索引1)
      let accountSequence = String(row[1]).trim();
      if (!accountSequence.startsWith('D')) {
        accountSequence = 'D' + accountSequence;
      }

      // 获取认种量 (第三列，索引2)
      const treeCount = parseInt(row[2], 10);
      if (isNaN(treeCount) || treeCount <= 0) {
        this.logger.debug(`[parseExcelData] 跳过行 ${i + 1}: 认种量无效 (${row[2]})`);
        continue;
      }

      // 获取挖矿开始时间 (第四列，索引3)
      const miningStartDateStr = String(row[3] || '').trim();

      // 解析挖矿开始时间，计算总挖矿天数
      const miningStartDate = this.parseDate(miningStartDateStr);
      let totalMiningDays = 0;
      if (miningStartDate) {
        const diffTime = today.getTime() - miningStartDate.getTime();
        totalMiningDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
      }

      // 获取批次 (第五列，索引4)
      const batch = parseInt(row[4], 10);
      if (isNaN(batch) || batch <= 0) {
        this.logger.warn(`[parseExcelData] 跳过行 ${i + 1}: 批次无效 (${row[4]})`);
        continue;
      }

      // 获取授权提前挖的天数 (第六列，索引5)
      const preMineDays = parseInt(row[5], 10);
      if (isNaN(preMineDays) || preMineDays <= 0) {
        this.logger.warn(`[parseExcelData] 跳过行 ${i + 1}: 授权提前挖的天数无效 (${row[5]})`);
        continue;
      }

      // 获取备注 (第七列，索引6)
      const remark = row[6] ? String(row[6]).trim() : undefined;

      items.push({
        accountSequence,
        treeCount,
        miningStartDate: miningStartDateStr,
        batch,
        preMineDays,
        totalMiningDays,
        remark,
      });
    }

    this.logger.log(`[parseExcelData] 解析完成, 有效数据: ${items.length} 条`);
    if (items.length > 0) {
      this.logger.log(`[parseExcelData] 第一条数据: ${JSON.stringify(items[0])}`);
      this.logger.log(`[parseExcelData] 最后一条数据: ${JSON.stringify(items[items.length - 1])}`);
    }

    return items;
  }

  /**
   * 解析日期字符串
   * 支持格式: 2025.11.8, 2025-11-08, 2025/11/8
   */
  private parseDate(dateStr: string): Date | null {
    if (!dateStr) return null;

    const formats = [
      /^(\d{4})\.(\d{1,2})\.(\d{1,2})$/,  // 2025.11.8
      /^(\d{4})-(\d{1,2})-(\d{1,2})$/,    // 2025-11-08
      /^(\d{4})\/(\d{1,2})\/(\d{1,2})$/,  // 2025/11/8
    ];

    for (const format of formats) {
      const match = dateStr.match(format);
      if (match) {
        const year = parseInt(match[1], 10);
        const month = parseInt(match[2], 10) - 1;
        const day = parseInt(match[3], 10);
        const date = new Date(year, month, day);
        date.setHours(0, 0, 0, 0);
        return date;
      }
    }

    return null;
  }
}
