import { Injectable, Logger, Inject } from '@nestjs/common';
import {
  UserAccountRepository,
  USER_ACCOUNT_REPOSITORY,
} from '@/domain/repositories/user-account.repository.interface';
import { PrismaService } from '@/infrastructure/persistence/prisma/prisma.service';
import { RedisService } from '@/infrastructure/redis/redis.service';
import { SmsService } from '@/infrastructure/external/sms/sms.service';
import { StorageService } from '@/infrastructure/external/storage/storage.service';
import { AliyunKycProvider } from '@/infrastructure/external/kyc/aliyun-kyc.provider';
import { ApplicationError } from '@/shared/exceptions/domain.exception';
import { EventPublisherService } from '@/infrastructure/kafka/event-publisher.service';
import { KYCVerifiedEvent } from '@/domain/events';

// KYC 综合状态枚举
export enum KycStatus {
  NOT_STARTED = 'NOT_STARTED',           // 未开始
  REAL_NAME_VERIFIED = 'REAL_NAME_VERIFIED', // 层级1完成: 实名认证通过
  FACE_VERIFIED = 'FACE_VERIFIED',       // 层级2完成: 实人认证通过
  KYC_VERIFIED = 'KYC_VERIFIED',         // 层级3完成: KYC认证通过
  COMPLETED = 'COMPLETED',               // 所有层级完成
  REJECTED = 'REJECTED',                 // 被拒绝
}

// KYC 配置键
export const KYC_CONFIG_KEYS = {
  LEVEL1_ENABLED: 'kyc.level1.enabled',  // 实名认证开关
  LEVEL2_ENABLED: 'kyc.level2.enabled',  // 实人认证开关
  LEVEL3_ENABLED: 'kyc.level3.enabled',  // KYC证件照开关
};

@Injectable()
export class KycApplicationService {
  private readonly logger = new Logger(KycApplicationService.name);

  constructor(
    @Inject(USER_ACCOUNT_REPOSITORY)
    private readonly userRepository: UserAccountRepository,
    private readonly prisma: PrismaService,
    private readonly redisService: RedisService,
    private readonly smsService: SmsService,
    private readonly storageService: StorageService,
    private readonly aliyunKycProvider: AliyunKycProvider,
    private readonly eventPublisher: EventPublisherService,
  ) {}

  /**
   * 获取 KYC 配置（哪些层级开启）
   */
  async getKycConfig() {
    const configs = await this.prisma.kycConfig.findMany({
      where: {
        configKey: {
          in: Object.values(KYC_CONFIG_KEYS),
        },
      },
    });

    const configMap = new Map(configs.map((c) => [c.configKey, c.configValue]));

    return {
      level1Enabled: configMap.get(KYC_CONFIG_KEYS.LEVEL1_ENABLED) !== 'false',
      level2Enabled: configMap.get(KYC_CONFIG_KEYS.LEVEL2_ENABLED) !== 'false',
      level3Enabled: configMap.get(KYC_CONFIG_KEYS.LEVEL3_ENABLED) !== 'false',
    };
  }

  /**
   * 更新 KYC 配置（管理后台使用）
   */
  async updateKycConfig(
    level1Enabled?: boolean,
    level2Enabled?: boolean,
    level3Enabled?: boolean,
    updatedBy?: string,
  ) {
    const updates: { key: string; value: string; description: string }[] = [];

    if (level1Enabled !== undefined) {
      updates.push({
        key: KYC_CONFIG_KEYS.LEVEL1_ENABLED,
        value: String(level1Enabled),
        description: '层级1: 实名认证(二要素)开关',
      });
    }
    if (level2Enabled !== undefined) {
      updates.push({
        key: KYC_CONFIG_KEYS.LEVEL2_ENABLED,
        value: String(level2Enabled),
        description: '层级2: 实人认证(人脸活体)开关',
      });
    }
    if (level3Enabled !== undefined) {
      updates.push({
        key: KYC_CONFIG_KEYS.LEVEL3_ENABLED,
        value: String(level3Enabled),
        description: '层级3: KYC(证件照)开关',
      });
    }

    for (const update of updates) {
      await this.prisma.kycConfig.upsert({
        where: { configKey: update.key },
        create: {
          configKey: update.key,
          configValue: update.value,
          description: update.description,
          updatedBy,
        },
        update: {
          configValue: update.value,
          updatedBy,
        },
      });
    }

    return this.getKycConfig();
  }

  /**
   * 获取用户的 KYC 状态（包含三层认证详情）
   */
  async getKycStatus(userId: string) {
    this.logger.log(`[KYC] Getting KYC status for user: ${userId}`);

    const [user, config] = await Promise.all([
      this.prisma.userAccount.findUnique({
        where: { userId: BigInt(userId) },
        select: {
          phoneNumber: true,
          phoneVerified: true,
          realNameVerified: true,
          realNameVerifiedAt: true,
          realName: true,
          idCardNumber: true,
          faceVerified: true,
          faceVerifiedAt: true,
          faceCertifyId: true,
          kycVerified: true,
          kycVerifiedAt: true,
          idCardFrontUrl: true,
          idCardBackUrl: true,
          kycStatus: true,
          kycRejectedReason: true,
        },
      }),
      this.getKycConfig(),
    ]);

    if (!user) {
      throw new ApplicationError('用户不存在');
    }

    // 计算需要完成的步骤
    const requiredSteps: string[] = [];
    if (config.level1Enabled) requiredSteps.push('REAL_NAME');
    if (config.level2Enabled) requiredSteps.push('FACE');
    if (config.level3Enabled) requiredSteps.push('KYC');

    // 计算已完成的步骤
    const completedSteps: string[] = [];
    if (user.realNameVerified) completedSteps.push('REAL_NAME');
    if (user.faceVerified) completedSteps.push('FACE');
    if (user.kycVerified) completedSteps.push('KYC');

    // 判断是否全部完成
    const isCompleted = requiredSteps.every((s) => completedSteps.includes(s));

    return {
      // 配置信息
      config,
      requiredSteps,

      // 层级1: 实名认证
      level1: {
        enabled: config.level1Enabled,
        verified: user.realNameVerified,
        verifiedAt: user.realNameVerifiedAt,
        realName: user.realName ? this.maskName(user.realName) : undefined,
        idCardNumber: user.idCardNumber ? this.maskIdCard(user.idCardNumber) : undefined,
      },

      // 层级2: 实人认证
      level2: {
        enabled: config.level2Enabled,
        verified: user.faceVerified,
        verifiedAt: user.faceVerifiedAt,
        // 只有层级1完成才能进行层级2
        canStart: config.level2Enabled && (!config.level1Enabled || user.realNameVerified),
      },

      // 层级3: KYC
      level3: {
        enabled: config.level3Enabled,
        verified: user.kycVerified,
        verifiedAt: user.kycVerifiedAt,
        hasIdCardFront: !!user.idCardFrontUrl,
        hasIdCardBack: !!user.idCardBackUrl,
        // 只有层级2完成（或层级2未开启且层级1完成）才能进行层级3
        canStart: config.level3Enabled && (
          (!config.level2Enabled && (!config.level1Enabled || user.realNameVerified)) ||
          (config.level2Enabled && user.faceVerified)
        ),
      },

      // 综合状态
      kycStatus: user.kycStatus,
      isCompleted,
      rejectedReason: user.kycRejectedReason,
      phoneNumber: user.phoneNumber ? this.maskPhoneNumber(user.phoneNumber) : undefined,
      phoneVerified: user.phoneVerified,
    };
  }

  /**
   * ========================================
   * 层级1: 实名认证 - 提交二要素验证
   * ========================================
   * 验证姓名+身份证号
   * 注：保留手机号参数以兼容调用方，三要素验证功能保留备用
   */
  async submitRealNameVerification(
    userId: string,
    realName: string,
    idCardNumber: string,
  ) {
    this.logger.log(`[KYC] [Level1] Submitting real name verification (2-factor) for user: ${userId}`);

    const config = await this.getKycConfig();
    if (!config.level1Enabled) {
      throw new ApplicationError('实名认证功能暂未开启');
    }

    const user = await this.prisma.userAccount.findUnique({
      where: { userId: BigInt(userId) },
      select: {
        realNameVerified: true,
        kycStatus: true,
        phoneNumber: true,
        accountSequence: true,
      },
    });

    if (!user) {
      throw new ApplicationError('用户不存在');
    }

    if (user.realNameVerified) {
      throw new ApplicationError('实名认证已完成，无需重复提交');
    }

    if (!user.phoneNumber) {
      throw new ApplicationError('未绑定手机号，无法进行实名认证');
    }

    // 生成请求 ID
    const requestId = `REAL_NAME_${userId}_${Date.now()}`;

    // 记录验证尝试
    const attempt = await this.prisma.kycVerificationAttempt.create({
      data: {
        userId: BigInt(userId),
        verificationType: 'ID_CARD_TWO',  // 二要素验证（姓名+身份证号）
        provider: 'ALIYUN',
        requestId,
        inputData: {
          realName: this.maskName(realName),
          idCardNumber: this.maskIdCard(idCardNumber),
        },
        status: 'PENDING',
      },
    });

    try {
      // 调用阿里云二要素验证（姓名+身份证号）
      const result = await this.aliyunKycProvider.verifyIdCard(
        realName,
        idCardNumber,
        user.phoneNumber,
        requestId,
      );

      if (result.success) {
        // 验证成功
        await this.prisma.$transaction([
          this.prisma.kycVerificationAttempt.update({
            where: { id: attempt.id },
            data: {
              status: 'SUCCESS',
              responseData: result.rawResponse as object ?? null,
              completedAt: new Date(),
            },
          }),
          this.prisma.userAccount.update({
            where: { userId: BigInt(userId) },
            data: {
              realName,
              idCardNumber,
              realNameVerified: true,
              realNameVerifiedAt: new Date(),
              kycStatus: KycStatus.REAL_NAME_VERIFIED,
              kycProvider: 'ALIYUN',
              kycRequestId: requestId,
            },
          }),
        ]);

        this.logger.log(`[KYC] [Level1] Verification SUCCESS for user: ${userId}`);

        // 发布 KYCVerified 事件，通知其他服务（如 planting-service）
        try {
          const verifiedAt = new Date();
          const event = new KYCVerifiedEvent({
            userId,
            accountSequence: user.accountSequence,
            verifiedAt,
          });
          await this.eventPublisher.publish(event);
          this.logger.log(`[KYC] [Level1] Published KYCVerified event for user: ${userId}, accountSequence: ${user.accountSequence}`);
        } catch (eventError) {
          // 事件发布失败不影响 KYC 结果，只记录日志
          this.logger.error(`[KYC] [Level1] Failed to publish KYCVerified event for user: ${userId}`, eventError);
        }

        return {
          success: true,
          level: 1,
          status: KycStatus.REAL_NAME_VERIFIED,
          message: '实名认证成功',
        };
      } else {
        // 验证失败
        await this.prisma.kycVerificationAttempt.update({
          where: { id: attempt.id },
          data: {
            status: 'FAILED',
            failureReason: result.errorMessage,
            responseData: result.rawResponse as object ?? null,
            completedAt: new Date(),
          },
        });

        this.logger.warn(`[KYC] [Level1] Verification FAILED for user: ${userId}, reason: ${result.errorMessage}`);

        return {
          success: false,
          level: 1,
          errorMessage: result.errorMessage,
        };
      }
    } catch (error) {
      await this.prisma.kycVerificationAttempt.update({
        where: { id: attempt.id },
        data: {
          status: 'FAILED',
          failureReason: `系统错误: ${error.message}`,
          completedAt: new Date(),
        },
      });

      this.logger.error(`[KYC] [Level1] Verification ERROR for user: ${userId}`, error);
      throw new ApplicationError('实名认证服务暂时不可用，请稍后重试');
    }
  }

  /**
   * ========================================
   * 层级2: 实人认证 - 初始化人脸活体检测
   * ========================================
   */
  async initFaceVerification(userId: string, metaInfo?: string) {
    this.logger.log(`[KYC] [Level2] Initializing face verification for user: ${userId}`);

    const config = await this.getKycConfig();
    if (!config.level2Enabled) {
      throw new ApplicationError('实人认证功能暂未开启');
    }

    const user = await this.prisma.userAccount.findUnique({
      where: { userId: BigInt(userId) },
      select: {
        realNameVerified: true,
        realName: true,
        idCardNumber: true,
        faceVerified: true,
      },
    });

    if (!user) {
      throw new ApplicationError('用户不存在');
    }

    // 层级2需要先完成层级1
    if (config.level1Enabled && !user.realNameVerified) {
      throw new ApplicationError('请先完成实名认证');
    }

    if (user.faceVerified) {
      throw new ApplicationError('实人认证已完成，无需重复提交');
    }

    if (!user.realName || !user.idCardNumber) {
      throw new ApplicationError('缺少实名信息，请先完成实名认证');
    }

    // 调用阿里云初始化人脸认证
    const result = await this.aliyunKycProvider.initFaceVerify(
      userId,
      user.realName,
      user.idCardNumber,
    );

    if (result.success && result.certifyId) {
      // 记录验证尝试
      await this.prisma.kycVerificationAttempt.create({
        data: {
          userId: BigInt(userId),
          verificationType: 'FACE',
          provider: 'ALIYUN',
          requestId: result.certifyId,
          status: 'PENDING',
        },
      });

      // 保存 certifyId 到用户记录
      await this.prisma.userAccount.update({
        where: { userId: BigInt(userId) },
        data: {
          faceCertifyId: result.certifyId,
        },
      });

      return {
        success: true,
        certifyId: result.certifyId,
        certifyUrl: result.certifyUrl,
      };
    } else {
      throw new ApplicationError(result.errorMessage || '初始化实人认证失败');
    }
  }

  /**
   * ========================================
   * 层级2: 实人认证 - 查询认证结果
   * ========================================
   */
  async queryFaceVerification(userId: string, certifyId: string) {
    this.logger.log(`[KYC] [Level2] Querying face verification for user: ${userId}, certifyId: ${certifyId}`);

    const user = await this.prisma.userAccount.findUnique({
      where: { userId: BigInt(userId) },
      select: {
        faceCertifyId: true,
        faceVerified: true,
      },
    });

    if (!user) {
      throw new ApplicationError('用户不存在');
    }

    if (user.faceVerified) {
      return {
        success: true,
        passed: true,
        status: 'PASSED',
        message: '实人认证已通过',
      };
    }

    if (user.faceCertifyId !== certifyId) {
      throw new ApplicationError('认证ID不匹配');
    }

    // 查询阿里云认证结果
    const result = await this.aliyunKycProvider.queryFaceVerify(certifyId);

    if (result.passed) {
      // 更新用户状态
      await this.prisma.$transaction([
        this.prisma.kycVerificationAttempt.updateMany({
          where: { requestId: certifyId },
          data: {
            status: 'SUCCESS',
            responseData: result.rawResponse as object ?? null,
            completedAt: new Date(),
          },
        }),
        this.prisma.userAccount.update({
          where: { userId: BigInt(userId) },
          data: {
            faceVerified: true,
            faceVerifiedAt: new Date(),
            kycStatus: KycStatus.FACE_VERIFIED,
          },
        }),
      ]);

      this.logger.log(`[KYC] [Level2] Face verification PASSED for user: ${userId}`);
    }

    return {
      success: result.success,
      passed: result.passed,
      status: result.status,
      errorMessage: result.errorMessage,
    };
  }

  /**
   * ========================================
   * 层级3: KYC - 上传证件照
   * ========================================
   */
  async uploadIdCardPhoto(
    userId: string,
    side: 'front' | 'back',
    file: Express.Multer.File,
  ) {
    this.logger.log(`[KYC] [Level3] Uploading ID card photo for user: ${userId}, side: ${side}`);

    const config = await this.getKycConfig();
    if (!config.level3Enabled) {
      throw new ApplicationError('KYC证件上传功能暂未开启');
    }

    const user = await this.prisma.userAccount.findUnique({
      where: { userId: BigInt(userId) },
      select: {
        realNameVerified: true,
        faceVerified: true,
        kycVerified: true,
      },
    });

    if (!user) {
      throw new ApplicationError('用户不存在');
    }

    // 检查前置条件
    if (config.level1Enabled && !user.realNameVerified) {
      throw new ApplicationError('请先完成实名认证');
    }
    if (config.level2Enabled && !user.faceVerified) {
      throw new ApplicationError('请先完成实人认证');
    }
    if (user.kycVerified) {
      throw new ApplicationError('KYC认证已完成，无需重复上传');
    }

    // 上传到 MinIO
    const uploadResult = await this.storageService.uploadImage(
      userId.toString(),
      `kyc/id_card_${side}`,
      file.buffer,
      file.mimetype,
    );
    const imageUrl = uploadResult.url;

    // 更新用户记录
    const updateData = side === 'front'
      ? { idCardFrontUrl: imageUrl }
      : { idCardBackUrl: imageUrl };

    await this.prisma.userAccount.update({
      where: { userId: BigInt(userId) },
      data: updateData,
    });

    // OCR 识别（可选）
    let ocrResult = null;
    try {
      ocrResult = await this.aliyunKycProvider.ocrIdCard(imageUrl, side);
    } catch (error) {
      this.logger.warn(`[KYC] [Level3] OCR failed: ${error.message}`);
    }

    return {
      success: true,
      side,
      imageUrl,
      ocrResult: ocrResult?.success ? {
        name: ocrResult.name,
        idNumber: ocrResult.idNumber,
        address: ocrResult.address,
        issueAuthority: ocrResult.issueAuthority,
        validPeriod: ocrResult.validPeriod,
      } : null,
    };
  }

  /**
   * ========================================
   * 层级3: KYC - 确认提交
   * ========================================
   */
  async confirmKycSubmission(userId: string) {
    this.logger.log(`[KYC] [Level3] Confirming KYC submission for user: ${userId}`);

    const user = await this.prisma.userAccount.findUnique({
      where: { userId: BigInt(userId) },
      select: {
        realNameVerified: true,
        faceVerified: true,
        kycVerified: true,
        idCardFrontUrl: true,
        idCardBackUrl: true,
        realName: true,
        idCardNumber: true,
      },
    });

    if (!user) {
      throw new ApplicationError('用户不存在');
    }

    const config = await this.getKycConfig();

    // 检查前置条件
    if (config.level1Enabled && !user.realNameVerified) {
      throw new ApplicationError('请先完成实名认证');
    }
    if (config.level2Enabled && !user.faceVerified) {
      throw new ApplicationError('请先完成实人认证');
    }
    if (!user.idCardFrontUrl || !user.idCardBackUrl) {
      throw new ApplicationError('请上传身份证正反面照片');
    }
    if (user.kycVerified) {
      throw new ApplicationError('KYC认证已完成');
    }

    // 记录验证尝试
    const requestId = `KYC_${userId}_${Date.now()}`;
    await this.prisma.kycVerificationAttempt.create({
      data: {
        userId: BigInt(userId),
        verificationType: 'ID_PHOTO',
        provider: 'ALIYUN',
        requestId,
        inputData: {
          frontUrl: user.idCardFrontUrl,
          backUrl: user.idCardBackUrl,
        },
        status: 'SUCCESS', // 证件照上传后直接成功（OCR已在上传时完成）
        completedAt: new Date(),
      },
    });

    // 更新用户状态
    await this.prisma.userAccount.update({
      where: { userId: BigInt(userId) },
      data: {
        kycVerified: true,
        kycVerifiedAt: new Date(),
        kycStatus: KycStatus.COMPLETED,
        kycRequestId: requestId,
      },
    });

    this.logger.log(`[KYC] [Level3] KYC verification COMPLETED for user: ${userId}`);

    return {
      success: true,
      level: 3,
      status: KycStatus.COMPLETED,
      message: 'KYC认证完成',
    };
  }

  // ============ Helper Methods ============

  private generateSmsCode(): string {
    return Math.floor(100000 + Math.random() * 900000).toString();
  }

  private maskPhoneNumber(phone: string): string {
    if (phone.length < 7) return phone;
    return `${phone.substring(0, 3)}****${phone.substring(phone.length - 4)}`;
  }

  private maskName(name: string): string {
    if (name.length <= 1) return name;
    if (name.length === 2) return `${name[0]}*`;
    return `${name[0]}${'*'.repeat(name.length - 2)}${name[name.length - 1]}`;
  }

  private maskIdCard(idCard: string): string {
    if (idCard.length < 10) return idCard;
    return `${idCard.substring(0, 4)}**********${idCard.substring(idCard.length - 4)}`;
  }
}
