import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as crypto from 'crypto';

/**
 * 二要素验证结果
 */
export interface IdCardVerificationResult {
  success: boolean;
  errorMessage?: string;
  rawResponse?: Record<string, unknown>;
}

/**
 * 人脸活体认证初始化结果
 */
export interface FaceVerifyInitResult {
  success: boolean;
  certifyId?: string;  // 认证ID，用于客户端SDK
  certifyUrl?: string; // H5认证链接（可选）
  errorMessage?: string;
  rawResponse?: Record<string, unknown>;
}

/**
 * 人脸活体认证查询结果
 */
export interface FaceVerifyQueryResult {
  success: boolean;
  passed: boolean;      // 是否通过认证
  status: 'PENDING' | 'PASSED' | 'FAILED' | 'EXPIRED';
  errorMessage?: string;
  rawResponse?: Record<string, unknown>;
}

/**
 * OCR识别结果
 */
export interface IdCardOcrResult {
  success: boolean;
  name?: string;
  idNumber?: string;
  address?: string;
  ethnicity?: string;
  birthDate?: string;
  sex?: string;
  issueAuthority?: string;  // 签发机关
  validPeriod?: string;     // 有效期限
  errorMessage?: string;
  rawResponse?: Record<string, unknown>;
}

/**
 * 阿里云实人认证服务 - 支持三层认证
 *
 * 层级1: 实名认证 - 二要素验证（姓名+身份证号）
 *        备用：三要素验证（姓名+身份证号+手机号）- verifyIdCardThreeFactor
 * 层级2: 实人认证 - 人脸活体检测
 * 层级3: KYC - 证件照OCR识别验证
 *
 * 文档: https://help.aliyun.com/product/60032.html
 */
@Injectable()
export class AliyunKycProvider {
  private readonly logger = new Logger(AliyunKycProvider.name);

  private readonly accessKeyId: string;
  private readonly accessKeySecret: string;
  private readonly enabled: boolean;
  private readonly endpoint: string;
  private readonly sceneId: string;

  constructor(private readonly configService: ConfigService) {
    this.accessKeyId = this.configService.get<string>('ALIYUN_ACCESS_KEY_ID', '');
    this.accessKeySecret = this.configService.get<string>('ALIYUN_ACCESS_KEY_SECRET', '');
    this.enabled = this.configService.get<boolean>('ALIYUN_KYC_ENABLED', false);
    this.endpoint = this.configService.get<string>('ALIYUN_KYC_ENDPOINT', 'cloudauth.aliyuncs.com');
    this.sceneId = this.configService.get<string>('ALIYUN_KYC_SCENE_ID', '');

    if (this.enabled && (!this.accessKeyId || !this.accessKeySecret)) {
      this.logger.warn('[AliyunKYC] KYC is enabled but credentials are not configured');
    }
  }

  /**
   * ========================================
   * 层级1: 实名认证 - 二要素验证（默认）
   * ========================================
   * 验证姓名和身份证号是否匹配
   * 使用阿里云 Id2MetaStandardVerify API (身份证二要素标准版核验)
   * 文档: https://help.aliyun.com/zh/id-verification/api-cloudauth-2019-03-07-id2metastandardverify-infor-verify
   */
  async verifyIdCard(
    realName: string,
    idCardNumber: string,
    phoneNumber: string,  // 保留参数以兼容调用方，但二要素验证不使用
    requestId: string,
  ): Promise<IdCardVerificationResult> {
    // 使用二要素验证（姓名 + 身份证号）
    return this.verifyIdCardTwoFactor(realName, idCardNumber, requestId);
  }

  /**
   * 二要素验证：姓名 + 身份证号
   * 使用阿里云 Id2MetaVerify API (身份证二要素核验)
   * 文档: https://help.aliyun.com/zh/id-verification/developer-reference/api-cloudauth-2019-03-07-id2metaverify
   */
  async verifyIdCardTwoFactor(
    realName: string,
    idCardNumber: string,
    requestId: string,
  ): Promise<IdCardVerificationResult> {
    this.logger.log(`[AliyunKYC] [Level1] Starting 2-factor verification, requestId: ${requestId}`);

    // 二要素验证直接调用真实API，不使用mock
    if (!this.accessKeyId || !this.accessKeySecret) {
      this.logger.error('[AliyunKYC] KYC credentials not configured');
      return {
        success: false,
        errorMessage: '实名认证服务未配置',
        rawResponse: { error: 'credentials_not_configured' },
      };
    }

    try {
      // 调用阿里云身份二要素核验 API (Id2MetaVerify)
      // 文档: https://help.aliyun.com/zh/id-verification/developer-reference/api-cloudauth-2019-03-07-id2metaverify
      // 参数说明:
      // - ParamType: 加密方式 (normal=明文, md5=MD5加密, sm2=SM2加密)
      // - UserName: 姓名
      // - IdentifyNum: 身份证号
      const params = {
        Action: 'Id2MetaVerify',
        Version: '2019-03-07',
        Format: 'JSON',
        ParamType: 'normal',
        UserName: realName,
        IdentifyNum: idCardNumber,
      };

      const response = await this.callAliyunApi(params);

      this.logger.log(`[AliyunKYC] [Level1] 2-factor API Response: ${JSON.stringify(response, null, 2)}`);

      // Id2MetaStandardVerify 返回结果:
      // - Code: 200 表示请求成功
      // - ResultObject.BizCode: 核验结果 (数字类型)
      //   - 1: 核验一致 (成功)
      //   - 2: 核验不一致 (失败)
      //   - 3: 查无记录 (失败)
      if (response.Code === 'OK' || response.Code === '200' || response.Code === 200) {
        const bizCode = response.ResultObject?.BizCode;
        // BizCode 可能是数字或字符串，都要兼容
        const isMatch = bizCode === 1 || bizCode === '1';

        this.logger.log(`[AliyunKYC] [Level1] 2-factor ResultObject: BizCode=${bizCode}`);

        if (isMatch) {
          this.logger.log(`[AliyunKYC] [Level1] 2-factor Verification SUCCESS for requestId: ${requestId}`);
          return {
            success: true,
            rawResponse: response,
          };
        } else {
          this.logger.warn(`[AliyunKYC] [Level1] 2-factor Verification FAILED (BizCode: ${bizCode})`);
          return {
            success: false,
            errorMessage: '身份信息验证失败',
            rawResponse: response,
          };
        }
      } else {
        this.logger.warn(`[AliyunKYC] [Level1] 2-factor API call FAILED - Code: ${response.Code}, Message: ${response.Message}`);
        return {
          success: false,
          errorMessage: '身份信息验证失败',
          rawResponse: response,
        };
      }
    } catch (error) {
      this.logger.error(`[AliyunKYC] [Level1] 2-factor API call failed: ${error.message}`, error.stack);
      return {
        success: false,
        errorMessage: '实名认证服务暂时不可用',
        rawResponse: { error: error.message },
      };
    }
  }

  /**
   * ========================================
   * 层级1: 实名认证 - 手机号三要素验证（备用）
   * ========================================
   * 验证姓名、身份证号和手机号是否匹配
   * 使用阿里云 Mobile3MetaDetailVerify API (手机号三要素核验详版)
   * 文档: https://help.aliyun.com/zh/id-verification/information-verification/developer-reference/esf1ff158mxowkk6
   */
  async verifyIdCardThreeFactor(
    realName: string,
    idCardNumber: string,
    phoneNumber: string,
    requestId: string,
  ): Promise<IdCardVerificationResult> {
    this.logger.log(`[AliyunKYC] [Level1] Starting mobile 3-factor verification (detail), requestId: ${requestId}`);

    // 开发/测试环境：模拟验证
    if (!this.enabled) {
      this.logger.warn('[AliyunKYC] KYC is disabled, using mock verification');
      return this.mockIdCardVerification(realName, idCardNumber, phoneNumber);
    }

    try {
      // 调用阿里云手机号三要素核验详版 API (Mobile3MetaDetailVerify)
      // 参数说明:
      // - ParamType: 加密方式 (normal=明文, md5=MD5加密, sm2=SM2加密)
      // - UserName: 姓名
      // - IdentifyNum: 身份证号
      // - Mobile: 手机号
      const params = {
        Action: 'Mobile3MetaDetailVerify',
        Version: '2019-03-07',
        Format: 'JSON',
        ParamType: 'normal',  // 使用明文传输
        UserName: realName,
        IdentifyNum: idCardNumber,
        Mobile: phoneNumber,
      };

      const response = await this.callAliyunApi(params);

      // 打印完整的阿里云返回信息（脱敏后）
      this.logger.log(`[AliyunKYC] [Level1] Aliyun API Response: ${JSON.stringify(response, null, 2)}`);

      // Mobile3MetaDetailVerify 返回结果:
      // - Code: OK 表示请求成功
      // - ResultObject.BizCode: 核验结果
      //   - 1: 校验一致 (成功)
      //   - 2: 校验不一致 (失败)
      //   - 3: 查无记录 (失败)
      // - ResultObject.SubCode: 详细错误码（仅在失败时有意义）
      //   - 101: 验证通过，三要素校验一致
      //   - 201: 手机号与姓名、证件号对比均不一致
      //   - 202: 手机号与姓名一致，但与证件号不一致
      //   - 203: 手机号与姓名不一致，但与证件号一致
      //   - 204: 其他不一致
      //   - 301: 查无记录
      if (response.Code === 'OK' || response.Code === '200' || response.Code === 200) {
        const bizCode = response.ResultObject?.BizCode;
        const subCode = response.ResultObject?.SubCode;
        const isConsistent = response.ResultObject?.IsConsistent;
        // BizCode 可能是数字或字符串，都要兼容
        const isMatch = bizCode === 1 || bizCode === '1';

        this.logger.log(`[AliyunKYC] [Level1] ResultObject: BizCode=${bizCode}, SubCode=${subCode}, IsConsistent=${isConsistent}`);

        if (isMatch) {
          this.logger.log(`[AliyunKYC] [Level1] Verification SUCCESS for requestId: ${requestId}`);
          return {
            success: true,
            rawResponse: response,
          };
        } else {
          // 使用 SubCode 获取详细错误原因
          const errorMsg = this.mapMobile3MetaDetailSubCode(subCode, bizCode);
          this.logger.warn(`[AliyunKYC] [Level1] Verification FAILED: ${errorMsg} (BizCode: ${bizCode}, SubCode: ${subCode})`);
          return {
            success: false,
            errorMessage: errorMsg,
            rawResponse: response,
          };
        }
      } else {
        this.logger.warn(`[AliyunKYC] [Level1] API call FAILED - Code: ${response.Code}, Message: ${response.Message}, RequestId: ${response.RequestId}`);
        return {
          success: false,
          errorMessage: this.mapErrorMessage(response.Code, response.Message),
          rawResponse: response,
        };
      }
    } catch (error) {
      this.logger.error(`[AliyunKYC] [Level1] API call failed: ${error.message}`, error.stack);
      return {
        success: false,
        errorMessage: '实名认证服务暂时不可用',
        rawResponse: { error: error.message },
      };
    }
  }

  /**
   * 映射手机号三要素核验详版错误码 (SubCode)
   * 阿里云 Mobile3MetaDetailVerify 返回的 SubCode:
   * - 101: 验证通过，三要素校验一致
   * - 201: 手机号与姓名、证件号对比均不一致
   * - 202: 手机号与姓名一致，但与证件号不一致
   * - 203: 手机号与姓名不一致，但与证件号一致
   * - 204: 其他不一致
   * - 301: 查无记录
   */
  private mapMobile3MetaDetailSubCode(subCode: string, bizCode: string): string {
    const subCodeMap: Record<string, string> = {
      '101': '验证通过',
      '201': '手机号与姓名、身份证号均不匹配',
      '202': '手机号与身份证号不匹配',
      '203': '手机号与姓名不匹配',
      '204': '信息校验不一致',
      '301': '查无记录，请确认信息是否正确',
    };

    if (subCode && subCodeMap[subCode]) {
      return subCodeMap[subCode];
    }

    // 如果没有 SubCode，回退到 BizCode 映射
    const bizCodeMap: Record<string, string> = {
      '2': '三要素信息校验不一致',
      '3': '查无记录，请确认信息是否正确',
    };
    return bizCodeMap[bizCode] || `验证失败 (错误码: ${bizCode})`;
  }

  /**
   * ========================================
   * 层级2: 实人认证 - 初始化人脸活体检测
   * ========================================
   * 返回认证ID供客户端SDK使用
   */
  async initFaceVerify(
    userId: string,
    realName: string,
    idCardNumber: string,
    returnUrl?: string,
  ): Promise<FaceVerifyInitResult> {
    this.logger.log(`[AliyunKYC] [Level2] Initializing face verify for user: ${userId}`);

    if (!this.enabled) {
      this.logger.warn('[AliyunKYC] KYC is disabled, using mock face verify init');
      return this.mockFaceVerifyInit(userId);
    }

    try {
      const outerOrderNo = `FACE_${userId}_${Date.now()}`;

      // 调用阿里云金融级实人认证初始化 API
      const params = {
        Action: 'InitFaceVerify',
        Version: '2019-03-07',
        Format: 'JSON',
        SceneId: this.sceneId,
        OuterOrderNo: outerOrderNo,
        ProductCode: 'ID_PLUS',  // 金融级实人认证
        CertType: 'IDENTITY_CARD',
        CertName: realName,
        CertNo: idCardNumber,
        ReturnUrl: returnUrl || '',
        MetaInfo: JSON.stringify({
          zimVer: '3.0.0',
          appVersion: '1.0.0',
          bioMetaInfo: 'mock',
        }),
      };

      const response = await this.callAliyunApi(params);

      if (response.Code === 'OK' || response.Code === '200') {
        const resultObject = response.ResultObject || {};
        this.logger.log(`[AliyunKYC] [Level2] Init SUCCESS, certifyId: ${resultObject.CertifyId}`);
        return {
          success: true,
          certifyId: resultObject.CertifyId,
          certifyUrl: resultObject.CertifyUrl,
          rawResponse: response,
        };
      } else {
        this.logger.warn(`[AliyunKYC] [Level2] Init FAILED: ${response.Message}`);
        return {
          success: false,
          errorMessage: this.mapErrorMessage(response.Code, response.Message),
          rawResponse: response,
        };
      }
    } catch (error) {
      this.logger.error(`[AliyunKYC] [Level2] Init failed: ${error.message}`, error.stack);
      return {
        success: false,
        errorMessage: '实人认证服务暂时不可用',
        rawResponse: { error: error.message },
      };
    }
  }

  /**
   * ========================================
   * 层级2: 实人认证 - 查询认证结果
   * ========================================
   */
  async queryFaceVerify(certifyId: string): Promise<FaceVerifyQueryResult> {
    this.logger.log(`[AliyunKYC] [Level2] Querying face verify result, certifyId: ${certifyId}`);

    if (!this.enabled) {
      this.logger.warn('[AliyunKYC] KYC is disabled, using mock face verify query');
      return this.mockFaceVerifyQuery(certifyId);
    }

    try {
      const params = {
        Action: 'DescribeFaceVerify',
        Version: '2019-03-07',
        Format: 'JSON',
        SceneId: this.sceneId,
        CertifyId: certifyId,
      };

      const response = await this.callAliyunApi(params);

      if (response.Code === 'OK' || response.Code === '200') {
        const resultObject = response.ResultObject || {};
        const passed = resultObject.Passed === 'T' || resultObject.Passed === true;

        this.logger.log(`[AliyunKYC] [Level2] Query result: passed=${passed}`);
        return {
          success: true,
          passed,
          status: passed ? 'PASSED' : 'FAILED',
          rawResponse: response,
        };
      } else {
        return {
          success: false,
          passed: false,
          status: 'FAILED',
          errorMessage: this.mapErrorMessage(response.Code, response.Message),
          rawResponse: response,
        };
      }
    } catch (error) {
      this.logger.error(`[AliyunKYC] [Level2] Query failed: ${error.message}`, error.stack);
      return {
        success: false,
        passed: false,
        status: 'FAILED',
        errorMessage: '查询认证结果失败',
        rawResponse: { error: error.message },
      };
    }
  }

  /**
   * ========================================
   * 层级3: KYC - 证件照OCR识别
   * ========================================
   */
  async ocrIdCard(
    imageUrl: string,
    side: 'front' | 'back',
  ): Promise<IdCardOcrResult> {
    this.logger.log(`[AliyunKYC] [Level3] Starting ID card OCR, side: ${side}`);

    if (!this.enabled) {
      this.logger.warn('[AliyunKYC] KYC is disabled, using mock OCR');
      return this.mockIdCardOcr(side);
    }

    try {
      const params = {
        Action: 'RecognizeIdCard',
        Version: '2019-03-07',
        Format: 'JSON',
        Side: side === 'front' ? 'face' : 'back',
        ImageUrl: imageUrl,
      };

      const response = await this.callAliyunApi(params);

      if (response.Code === 'OK' || response.Code === '200') {
        const data = response.Data || {};
        this.logger.log(`[AliyunKYC] [Level3] OCR SUCCESS`);

        if (side === 'front') {
          return {
            success: true,
            name: data.Name,
            idNumber: data.IdNumber,
            address: data.Address,
            ethnicity: data.Ethnicity,
            birthDate: data.BirthDate,
            sex: data.Sex,
            rawResponse: response,
          };
        } else {
          return {
            success: true,
            issueAuthority: data.Issue,
            validPeriod: data.ValidPeriod || `${data.StartDate}-${data.EndDate}`,
            rawResponse: response,
          };
        }
      } else {
        return {
          success: false,
          errorMessage: this.mapErrorMessage(response.Code, response.Message),
          rawResponse: response,
        };
      }
    } catch (error) {
      this.logger.error(`[AliyunKYC] [Level3] OCR failed: ${error.message}`, error.stack);
      return {
        success: false,
        errorMessage: '证件识别服务暂时不可用',
        rawResponse: { error: error.message },
      };
    }
  }

  // ============ 私有方法 ============

  /**
   * 调用阿里云 API (签名方式)
   */
  private async callAliyunApi(params: Record<string, string>): Promise<any> {
    const timestamp = new Date().toISOString().replace(/\.\d{3}/, '');
    const nonce = crypto.randomUUID();

    const commonParams: Record<string, string> = {
      AccessKeyId: this.accessKeyId,
      Timestamp: timestamp,
      SignatureMethod: 'HMAC-SHA1',
      SignatureVersion: '1.0',
      SignatureNonce: nonce,
      ...params,
    };

    // 计算签名
    const signature = this.calculateSignature(commonParams);
    commonParams['Signature'] = signature;

    // 发起请求
    const queryString = Object.entries(commonParams)
      .map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`)
      .join('&');

    const url = `https://${this.endpoint}/?${queryString}`;

    const response = await fetch(url, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
      },
    });

    return response.json();
  }

  /**
   * 计算阿里云 API 签名
   */
  private calculateSignature(params: Record<string, string>): string {
    const sortedKeys = Object.keys(params).sort();
    const canonicalizedQueryString = sortedKeys
      .map((k) => `${this.percentEncode(k)}=${this.percentEncode(params[k])}`)
      .join('&');

    const stringToSign = `GET&${this.percentEncode('/')}&${this.percentEncode(canonicalizedQueryString)}`;

    const hmac = crypto.createHmac('sha1', `${this.accessKeySecret}&`);
    hmac.update(stringToSign);
    return hmac.digest('base64');
  }

  private percentEncode(str: string): string {
    return encodeURIComponent(str)
      .replace(/\+/g, '%20')
      .replace(/\*/g, '%2A')
      .replace(/~/g, '%7E');
  }

  /**
   * 映射错误消息
   */
  private mapErrorMessage(code: string, message: string): string {
    const errorMap: Record<string, string> = {
      'InvalidParameter': '参数格式错误',
      'IdCardNotMatch': '姓名与身份证号不匹配',
      'IdCardNotExist': '身份证号不存在',
      'IdCardExpired': '身份证已过期',
      'FaceNotMatch': '人脸比对不通过',
      'LivenessCheckFail': '活体检测失败',
      'SystemError': '系统错误，请稍后重试',
    };
    return errorMap[code] || message || '认证失败';
  }

  // ============ Mock 方法 (开发/测试环境) ============

  private mockIdCardTwoFactorVerification(realName: string, idCardNumber: string): IdCardVerificationResult {
    this.logger.log('[AliyunKYC] Using mock ID card verification (2-factor)');

    // 基本格式验证
    if (!realName || realName.length < 2) {
      return {
        success: false,
        errorMessage: '身份信息验证失败',
        rawResponse: { mock: true, reason: 'invalid_name' },
      };
    }

    // 身份证号格式验证
    const idCardRegex = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
    if (!idCardRegex.test(idCardNumber)) {
      return {
        success: false,
        errorMessage: '身份信息验证失败',
        rawResponse: { mock: true, reason: 'invalid_id_card_format' },
      };
    }

    // 校验码验证
    if (!this.validateIdCardChecksum(idCardNumber)) {
      return {
        success: false,
        errorMessage: '身份信息验证失败',
        rawResponse: { mock: true, reason: 'invalid_checksum' },
      };
    }

    return {
      success: true,
      rawResponse: { mock: true, verifyTime: new Date().toISOString(), verifyType: '2-factor' },
    };
  }

  private mockIdCardVerification(realName: string, idCardNumber: string, phoneNumber: string): IdCardVerificationResult {
    this.logger.log('[AliyunKYC] Using mock ID card verification (3-factor)');

    // 基本格式验证
    if (!realName || realName.length < 2) {
      return {
        success: false,
        errorMessage: '姓名格式不正确',
        rawResponse: { mock: true, reason: 'invalid_name' },
      };
    }

    // 身份证号格式验证
    const idCardRegex = /^[1-9]\d{5}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
    if (!idCardRegex.test(idCardNumber)) {
      return {
        success: false,
        errorMessage: '身份证号格式不正确',
        rawResponse: { mock: true, reason: 'invalid_id_card_format' },
      };
    }

    // 校验码验证
    if (!this.validateIdCardChecksum(idCardNumber)) {
      return {
        success: false,
        errorMessage: '身份证号校验码不正确',
        rawResponse: { mock: true, reason: 'invalid_checksum' },
      };
    }

    // 手机号格式验证
    const phoneRegex = /^1[3-9]\d{9}$/;
    if (!phoneNumber || !phoneRegex.test(phoneNumber)) {
      return {
        success: false,
        errorMessage: '手机号格式不正确',
        rawResponse: { mock: true, reason: 'invalid_phone' },
      };
    }

    return {
      success: true,
      rawResponse: { mock: true, verifyTime: new Date().toISOString(), verifyType: '3-factor' },
    };
  }

  private mockFaceVerifyInit(userId: string): FaceVerifyInitResult {
    this.logger.log('[AliyunKYC] Using mock face verify init');
    const mockCertifyId = `MOCK_CERTIFY_${userId}_${Date.now()}`;
    return {
      success: true,
      certifyId: mockCertifyId,
      certifyUrl: `https://mock.aliyun.com/face-verify?certifyId=${mockCertifyId}`,
      rawResponse: { mock: true },
    };
  }

  private mockFaceVerifyQuery(certifyId: string): FaceVerifyQueryResult {
    this.logger.log('[AliyunKYC] Using mock face verify query');
    // 模拟环境中，假设所有以 MOCK_ 开头的认证都通过
    const passed = certifyId.startsWith('MOCK_');
    return {
      success: true,
      passed,
      status: passed ? 'PASSED' : 'PENDING',
      rawResponse: { mock: true },
    };
  }

  private mockIdCardOcr(side: 'front' | 'back'): IdCardOcrResult {
    this.logger.log('[AliyunKYC] Using mock ID card OCR');
    if (side === 'front') {
      return {
        success: true,
        name: '测试用户',
        idNumber: '110101199001011234',
        address: '北京市东城区测试街道1号',
        ethnicity: '汉',
        birthDate: '1990-01-01',
        sex: '男',
        rawResponse: { mock: true },
      };
    } else {
      return {
        success: true,
        issueAuthority: '北京市公安局东城分局',
        validPeriod: '2020.01.01-2040.01.01',
        rawResponse: { mock: true },
      };
    }
  }

  private validateIdCardChecksum(idCard: string): boolean {
    if (idCard.length !== 18) return false;

    const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
    const checksumChars = '10X98765432';

    let sum = 0;
    for (let i = 0; i < 17; i++) {
      sum += parseInt(idCard[i], 10) * weights[i];
    }

    const expectedChecksum = checksumChars[sum % 11];
    const actualChecksum = idCard[17].toUpperCase();

    return expectedChecksum === actualChecksum;
  }
}
