import { Injectable, Logger } from '@nestjs/common';
import { SmsVerificationType } from '../../domain/entities/sms-verification.entity';
import { ISmsProvider, SmsDeliveryResult } from './sms-provider.interface';

/**
 * 阿里云 SMS Provider
 *
 * 环境变量:
 * - ALIYUN_ACCESS_KEY_ID / ALIYUN_ACCESS_KEY_SECRET
 * - ALIYUN_SMS_SIGN_NAME (签名名称)
 * - ALIYUN_SMS_TEMPLATE_CODE (通用 fallback 模板)
 * - ALIYUN_SMS_TPL_REGISTER       注册验证码
 * - ALIYUN_SMS_TPL_LOGIN           登录验证码
 * - ALIYUN_SMS_TPL_RESET_PASSWORD  重置密码
 * - ALIYUN_SMS_TPL_CHANGE_PHONE    换绑手机（复用身份验证模板）
 * - ALIYUN_SMS_TPL_IDENTITY_VERIFY 身份验证
 * - ALIYUN_SMS_TPL_TRANSACTION     交易确认
 * - ALIYUN_SMS_TPL_PAYMENT         支付验证
 * - ALIYUN_SMS_ENDPOINT (默认 dysmsapi.aliyuncs.com)
 */
@Injectable()
export class AliyunSmsProvider implements ISmsProvider {
  private readonly logger = new Logger('AliyunSmsProvider');
  private client: any; // Dysmsapi20170525 client (lazy init)

  /** 类型 → 环境变量名 映射 */
  private static readonly TEMPLATE_ENV_MAP: Record<SmsVerificationType, string> = {
    [SmsVerificationType.REGISTER]: 'ALIYUN_SMS_TPL_REGISTER',
    [SmsVerificationType.LOGIN]: 'ALIYUN_SMS_TPL_LOGIN',
    [SmsVerificationType.RESET_PASSWORD]: 'ALIYUN_SMS_TPL_RESET_PASSWORD',
    [SmsVerificationType.CHANGE_PHONE]: 'ALIYUN_SMS_TPL_CHANGE_PHONE',
    [SmsVerificationType.IDENTITY_VERIFY]: 'ALIYUN_SMS_TPL_IDENTITY_VERIFY',
    [SmsVerificationType.TRANSACTION_CONFIRM]: 'ALIYUN_SMS_TPL_TRANSACTION',
    [SmsVerificationType.PAYMENT_VERIFY]: 'ALIYUN_SMS_TPL_PAYMENT',
  };

  async send(
    phone: string,
    code: string,
    type: SmsVerificationType,
  ): Promise<SmsDeliveryResult> {
    try {
      const client = await this.getClient();

      // 去掉 +86 前缀 (阿里云要求纯数字)
      const phoneNumber = phone.startsWith('+86') ? phone.slice(3) : phone;

      const templateParam = JSON.stringify({ code });
      const signName = process.env.ALIYUN_SMS_SIGN_NAME || '券金融';
      const templateCode = this.getTemplateCode(type);

      if (!templateCode) {
        this.logger.error(`No SMS template configured for type: ${type}`);
        return { success: false, errorMsg: `No template for type: ${type}` };
      }

      // eslint-disable-next-line @typescript-eslint/no-var-requires
      const Dysmsapi = require('@alicloud/dysmsapi20170525');
      // eslint-disable-next-line @typescript-eslint/no-var-requires
      const $Util = require('@alicloud/tea-util');

      const sendSmsRequest = new Dysmsapi.SendSmsRequest({
        phoneNumbers: phoneNumber,
        signName,
        templateCode,
        templateParam,
      });

      const runtime = new $Util.RuntimeOptions({
        connectTimeout: 15000,
        readTimeout: 15000,
      });

      const response = await client.sendSmsWithOptions(sendSmsRequest, runtime);

      if (response.body?.code === 'OK') {
        this.logger.log(
          `SMS sent [${type}]: phone=${phone.slice(0, 3)}****${phone.slice(-4)} tpl=${templateCode} bizId=${response.body.bizId}`,
        );
        return {
          success: true,
          providerId: response.body.bizId,
        };
      }

      this.logger.error(
        `Aliyun SMS failed: ${response.body?.code} - ${response.body?.message}`,
      );
      return {
        success: false,
        errorMsg: `${response.body?.code}: ${response.body?.message}`,
      };
    } catch (error: any) {
      this.logger.error(`Aliyun SMS error: ${error.message}`);
      return { success: false, errorMsg: error.message };
    }
  }

  private getTemplateCode(type: SmsVerificationType): string {
    const envKey = AliyunSmsProvider.TEMPLATE_ENV_MAP[type];
    const specific = envKey ? process.env[envKey] : undefined;
    return specific || process.env.ALIYUN_SMS_TEMPLATE_CODE || '';
  }

  private async getClient() {
    if (this.client) return this.client;

    // eslint-disable-next-line @typescript-eslint/no-var-requires
    const Dysmsapi20170525 = require('@alicloud/dysmsapi20170525').default;
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    const { Config } = require('@alicloud/openapi-client');

    const config = new Config({
      accessKeyId: process.env.ALIYUN_ACCESS_KEY_ID,
      accessKeySecret: process.env.ALIYUN_ACCESS_KEY_SECRET,
      endpoint: process.env.ALIYUN_SMS_ENDPOINT || 'dysmsapi.aliyuncs.com',
    });

    this.client = new Dysmsapi20170525(config);
    this.logger.log('Aliyun SMS client initialized');
    return this.client;
  }
}
