import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import axios from 'axios';
import {
  AI3DProvider,
  AI3DGenerateResult,
  AI3DGenerateOptions,
} from './ai-3d-provider.interface';
import { TencentCloudSigner } from '../utils/tencent-cloud-sign';

/**
 * 腾讯混元 3D Provider
 * 文档：https://cloud.tencent.com/document/api/1804/123447
 * API概览：https://cloud.tencent.com/document/product/1804/120838
 *
 * 重要说明：
 * - 默认提供3个并发任务，最多同时处理3个任务
 * - 每个任务会消耗一定积分（根据资源包计费）
 * - 如果遇到"资源不足"错误，可能是：并发数达到上限、积分不足、或服务暂时不可用
 */
@Injectable()
export class HunyuanAI3DProvider implements AI3DProvider {
  private readonly logger = new Logger(HunyuanAI3DProvider.name);
  private readonly apiHost = 'ai3d.tencentcloudapi.com';
  private readonly apiVersion = '2025-05-13'; // 使用正确的API版本
  private readonly secretId: string;
  private readonly secretKey: string;
  private readonly region: string;

  constructor(private configService: ConfigService) {
    this.secretId = this.configService.get<string>('TENCENT_SECRET_ID');
    this.secretKey = this.configService.get<string>('TENCENT_SECRET_KEY');
    this.region =
      this.configService.get<string>('TENCENT_REGION') || 'ap-guangzhou';

    if (!this.secretId || !this.secretKey) {
      this.logger.warn(
        '未配置腾讯云密钥，请设置 TENCENT_SECRET_ID 和 TENCENT_SECRET_KEY 环境变量',
      );
    }
  }

  /**
   * 提交生成任务
   */
  async submitTask(
    inputType: 'text' | 'image',
    inputContent: string,
    options?: AI3DGenerateOptions,
  ): Promise<string> {
    try {
      // 构造请求参数
      const payload: any = {};

      if (inputType === 'text') {
        // 文生3D：使用 Prompt
        payload.Prompt = inputContent;

        // 文生3D支持额外参数
        if (options?.generateType) {
          payload.GenerateType = options.generateType;
        }
        if (options?.faceCount) {
          payload.FaceCount = options.faceCount;
        }

        this.logger.log(
          `提交文生3D任务: ${inputContent.substring(0, 50)}... ` +
            `[类型: ${options?.generateType || 'Normal'}, 面数: ${options?.faceCount || 500000}]`,
        );
      } else {
        // 图生3D：使用 ImageUrl 或 ImageBase64
        if (
          inputContent.startsWith('http://') ||
          inputContent.startsWith('https://')
        ) {
          payload.ImageUrl = inputContent;
        } else {
          // 假设是 Base64 编码的图片
          payload.ImageBase64 = inputContent;
        }

        // 图生3D也支持模型类型
        if (options?.generateType) {
          payload.GenerateType = options.generateType;
        }

        // 多视图图片支持
        if (options?.multiViewImages && options.multiViewImages.length > 0) {
          // 检查是否包含扩展视角（需要 v3.1）
          const extendedViewTypes = ['top', 'bottom', 'left_front', 'right_front'];
          const hasExtendedViews = options.multiViewImages.some(
            (img) => extendedViewTypes.includes(img.viewType)
          );

          // 如果有扩展视角，使用模型版本 3.1
          if (hasExtendedViews) {
            payload.ModelVersion = '3.1';
          }

          payload.MultiViewImages = options.multiViewImages.map((img) => ({
            ViewType: img.viewType,
            ViewImageUrl: img.imageUrl,
          }));
          this.logger.log(
            `提交图生3D任务（多视图）: ${options.multiViewImages.length} 张图片 ` +
              `[类型: ${options?.generateType || 'Normal'}]` +
              (hasExtendedViews ? ' [模型版本: 3.1]' : ''),
          );
        } else {
          this.logger.log(
            `提交图生3D任务: ${inputContent.substring(0, 50)}... ` +
              `[类型: ${options?.generateType || 'Normal'}]`,
          );
        }
      }

      // 生成签名和请求头
      const headers = TencentCloudSigner.sign({
        secretId: this.secretId,
        secretKey: this.secretKey,
        service: 'ai3d',
        host: this.apiHost,
        region: this.region,
        action: 'SubmitHunyuanTo3DProJob',
        version: this.apiVersion,
        payload,
      });

      // 发送请求
      const response = await axios.post(`https://${this.apiHost}`, payload, {
        headers,
      });

      // 检查响应
      if (response.data.Response?.Error) {
        const error = response.data.Response.Error;
        this.logger.error(`混元3D API错误: ${error.Code} - ${error.Message}`);

        // 对特定错误提供更友好的提示
        if (error.Code === 'ResourceInsufficient') {
          const friendlyMessage =
            '资源不足。可能原因：1) 并发任务数已达到上限（默认3个），请等待其他任务完成；' +
            '2) 积分余额不足，请检查腾讯云控制台的积分余额；' +
            '3) 服务暂时不可用，请稍后重试。';
          throw new Error(`混元3D API错误: ${friendlyMessage}`);
        }

        throw new Error(`混元3D API错误: ${error.Message}`);
      }

      const jobId = response.data.Response?.JobId;
      if (!jobId) {
        this.logger.error('混元3D API未返回JobId');
        throw new Error('混元3D API未返回任务ID');
      }

      this.logger.log(`混元3D任务创建成功: ${jobId}`);
      return jobId;
    } catch (error) {
      this.logger.error(`提交混元3D任务失败: ${error.message}`, error.stack);
      throw error;
    }
  }

  /**
   * 查询任务状态
   */
  async queryTask(taskId: string): Promise<AI3DGenerateResult> {
    try {
      // 构造请求参数
      const payload = {
        JobId: taskId,
      };

      // 生成签名和请求头
      const headers = TencentCloudSigner.sign({
        secretId: this.secretId,
        secretKey: this.secretKey,
        service: 'ai3d',
        host: this.apiHost,
        region: this.region,
        action: 'QueryHunyuanTo3DProJob',
        version: this.apiVersion,
        payload,
      });

      // 发送请求
      const response = await axios.post(`https://${this.apiHost}`, payload, {
        headers,
      });

      // 检查响应
      if (response.data.Response?.Error) {
        const error = response.data.Response.Error;
        this.logger.error(`混元3D查询错误: ${error.Code} - ${error.Message}`);
        return {
          taskId,
          status: 'failed',
          errorMessage: error.Message,
        };
      }

      const result = response.data.Response;

      // 映射任务状态
      // 混元状态: WAIT（等待中）| RUN（运行中）| FAIL（失败）| DONE（完成）
      const statusMap: Record<
        string,
        'pending' | 'processing' | 'completed' | 'failed'
      > = {
        WAIT: 'processing',
        RUN: 'processing',
        FAIL: 'failed',
        DONE: 'completed',
      };

      const status = statusMap[result.Status] || 'processing';

      // 构造返回结果
      const generateResult: AI3DGenerateResult = {
        taskId,
        status,
      };

      // 如果任务完成，提取模型URL
      // 根据API文档，返回的是 ResultFile3Ds 数组
      // 注意：这里只返回原始URL，COS转存由AI3DService统一处理
      if (status === 'completed' && result.ResultFile3Ds?.length > 0) {
        const file3Ds = result.ResultFile3Ds;
        // 提取所有模型URL和预览图URL
        const urls = file3Ds.map((file: any) => file.Url).filter(Boolean);
        const previewUrls = file3Ds
          .map((file: any) => file.PreviewImageUrl)
          .filter(Boolean);

        if (urls.length > 0) {
          generateResult.resultUrl = urls[0];
          generateResult.resultUrls = urls;
        }

        if (previewUrls.length > 0) {
          generateResult.previewUrl = previewUrls[0];
          generateResult.previewUrls = previewUrls;
        }

        this.logger.log(
          `混元3D任务 ${taskId} 完成: ${urls.length} 个模型文件, ${previewUrls.length} 个预览图`,
        );
      } else if (status === 'failed') {
        // 失败原因：根据文档，错误信息在 ErrorMessage 字段
        generateResult.errorMessage =
          result.ErrorMessage || result.ErrorCode || '生成失败';
        this.logger.warn(
          `混元3D任务 ${taskId} 失败: ${generateResult.errorMessage}`,
        );
      }

      return generateResult;
    } catch (error) {
      this.logger.error(`查询混元3D任务失败: ${error.message}`, error.stack);
      return {
        taskId,
        status: 'failed',
        errorMessage: `查询任务失败: ${error.message}`,
      };
    }
  }
}
