/**
 * VNLH-VND SDK — KYC Engine (ISO 20022 auth.012/013)
 * Xử lý KYC, eKYC và ODC (Optical Document Capture) phía TypeScript gateway.
 *
 * Chuẩn ISO 20022:
 *   auth.012.001.02 — MoneyLaunderingRiskReport (KYC Request từ NHTM)
 *   auth.013.001.02 — InvestigationRequestResponse (KYC Response từ NHNN)
 *
 * Tích hợp với:
 *   - Gov-Chain: neo hash hồ sơ KYC sau khi APPROVED
 *   - AML Engine: dùng kết quả KYC để nâng cao độ chính xác screening
 *   - SWIFT gpi Tracker: gắn kycId vào giao dịch pacs.008/pacs.009
 *
 * Pháp lý:
 *   Luật PCRT 2022 | TT09/2023/TT-NHNN | FATF R.10 | FATF R.12
 */

import { createHash } from 'crypto';
import { AML_THRESHOLD } from './constants';
import type { InstitutionRole, AmlRiskLevel, AmlFlag } from './types';

// ─── KYC Domain Types ─────────────────────────────────────────────────────────

export type KycSubjectType   = 'INDIVIDUAL' | 'LEGAL_ENTITY' | 'SOLE_PROPRIETOR';
export type KycStatus        = 'PENDING' | 'IN_REVIEW' | 'APPROVED' | 'REJECTED' | 'EXPIRED' | 'SUSPENDED';
export type OdcDocType =
  | 'NATIONAL_ID'
  | 'PASSPORT'
  | 'DRIVING_LIC'
  | 'BUSINESS_REG'
  | 'CONTRACT'
  | 'LEGAL_DOC'
  | 'FINANCIAL_STMT'
  | 'OTHER';

export type OdcVerifyStatus = 'PENDING' | 'VALID' | 'INVALID' | 'TAMPERED' | 'EXPIRED';

// ─── ODC Scanned Document ─────────────────────────────────────────────────────

export interface OdcScanResult {
  docType:        OdcDocType;
  docHash:        string;
  fileName:       string;
  mimeType:       string;
  ocrConfidence:  number;          // 0–100
  ocrFields:      Record<string, unknown>;
  verifyStatus:   OdcVerifyStatus;
  expiryDays?:    number | null;   // null nếu không có expiry
  contractRisk?:  OdcContractRisk;
  scannedAt:      string;
}

export interface OdcContractRisk {
  riskLevel:     'LOW' | 'MEDIUM' | 'HIGH';
  riskClauses:   string[];
  governingLaw:  string;
  parties:       string[];
  legalCompliant: boolean;
}

// ─── KYC Record ───────────────────────────────────────────────────────────────

export interface KycRecord {
  kycId:          string;
  subjectType:    KycSubjectType;
  fullName:       string;
  idNumber:       string;
  idType:         string;
  nationality:    string;
  requesterBic:   string;
  documents:      OdcScanResult[];
  riskAssessment: KycRiskAssessment;
  status:         KycStatus;
  recordHash:     string;
  govChainAnchored: boolean;
  govChainBlockHash?: string | null;
  iso20022MsgId:  string;
  createdAt:      string;
  expiryDate:     string;
}

export interface KycRiskAssessment {
  riskScore:    number;            // 0–100
  riskLevel:    AmlRiskLevel;
  isPep:        boolean;
  isSanctioned: boolean;
  flags:        string[];
  requiresEdd:  boolean;
  assessedAt:   string;
}

// ─── KYC Submit Input ─────────────────────────────────────────────────────────

export interface KycSubmitInput {
  subjectType?:  KycSubjectType;
  fullName:      string;
  idNumber:      string;
  idType?:       string;
  dateOfBirth?:  string;
  nationality?:  string;
  address?:      string;
  email?:        string;
  phone?:        string;
  requesterBic:  string;
  linkedUetr?:   string;
  /** Tài liệu đính kèm — text content từ OCR/PDF parse */
  documents?:    Array<{
    docType:    OdcDocType;
    content:    string;
    fileName?:  string;
    mimeType?:  string;
    fileSize?:  number;
  }>;
}

export interface KycSubmitResult {
  kycId:        string;
  status:       KycStatus;
  riskLevel:    AmlRiskLevel;
  riskScore:    number;
  requiresEdd:  boolean;
  flags:        string[];
  docCount:     number;
  docStatuses:  { docType: OdcDocType; verifyStatus: OdcVerifyStatus; ocrConfidence: number }[];
  recordHash:   string;
  auth012Xml:   string;
  auth013Xml:   string;
  submittedAt:  string;
  legalRefs:    string[];
}

// ─── FATF High-Risk Countries (ISO 3166-1 alpha-2) ───────────────────────────

const FATF_BLACK_LIST = new Set(['KP','IR','SY']);
const FATF_GREY_LIST  = new Set(['MM','YE','SD','AF','PK','NG']);

const PEP_KEYWORDS = [
  'bộ trưởng','thứ trưởng','chủ tịch','phó chủ tịch',
  'minister','secretary','chairman','senator',
];

// ─── ODC Scanner (TypeScript side) ───────────────────────────────────────────

/**
 * Trích xuất trường dữ liệu từ CMND/CCCD (phía TS gateway).
 */
export function extractNationalIdFields(text: string): Record<string, unknown> {
  const fields: Record<string, unknown> = {};

  const idMatch = text.match(/\b(\d{12}|\d{9})\b/);
  if (idMatch) fields.idNumber = idMatch[1];

  const dates = text.match(/\d{2}\/\d{2}\/\d{4}/g) || [];
  if (dates[0]) fields.dateOfBirth = dates[0];
  if (dates[1]) fields.issueDate   = dates[1];
  if (dates[2]) fields.expiryDate  = dates[2];

  if (/^([A-ZÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚÝ\s]{5,40})$/m.test(text)) {
    const nameMatch = text.match(/^([A-ZÀÁÂÃÈÉÊÌÍÒÓÔÕÙÚÝ\s]{5,40})$/m);
    if (nameMatch) fields.fullName = nameMatch[1].trim();
  }

  if (/\bNam\b/i.test(text)) fields.gender = 'MALE';
  else if (/\bN[ữu]\b/i.test(text)) fields.gender = 'FEMALE';

  return fields;
}

/**
 * Quét và phân tích tài liệu (TypeScript sandbox implementation).
 */
export function scanOdcDocument(params: {
  docType:    OdcDocType;
  content:    string;
  fileName?:  string;
  mimeType?:  string;
  fileSize?:  number;
}): OdcScanResult {
  const { docType, content, fileName, mimeType, fileSize } = params;

  const docHash = createHash('sha256')
    .update(content || '')
    .digest('hex');

  // OCR fields
  let ocrFields: Record<string, unknown> = {};
  let ocrConfidence = 50;

  if (docType === 'NATIONAL_ID') {
    ocrFields     = extractNationalIdFields(content);
    const required = ['idNumber','dateOfBirth','issueDate'];
    const found    = required.filter(f => ocrFields[f]).length;
    ocrConfidence  = Math.round((found / required.length) * 100);
  } else if (docType === 'CONTRACT' || docType === 'LEGAL_DOC') {
    ocrFields      = extractContractFields(content);
    ocrConfidence  = ocrFields.contractNo ? 80 : 40;
  } else {
    ocrConfidence  = content.length > 100 ? 60 : 30;
  }

  // Verify status
  const verifyStatus: OdcVerifyStatus =
    fileSize !== undefined && fileSize < 50_000 ? 'INVALID' :
    ocrConfidence >= 60                         ? 'VALID'   : 'PENDING';

  // Expiry
  let expiryDays: number | null = null;
  if (docType === 'NATIONAL_ID' || docType === 'PASSPORT') {
    const expiryStr = ocrFields.expiryDate as string | undefined;
    if (expiryStr) {
      const [d, m, y] = expiryStr.split('/');
      if (d && m && y) {
        const exp = new Date(`${y}-${m}-${d}`);
        expiryDays = Math.floor((exp.getTime() - Date.now()) / 86_400_000);
      }
    }
  }

  // Contract analysis
  let contractRisk: OdcContractRisk | undefined;
  if (docType === 'CONTRACT' || docType === 'LEGAL_DOC') {
    contractRisk = analyzeContractRisk(content);
  }

  return {
    docType,
    docHash,
    fileName:      fileName || 'document',
    mimeType:      mimeType || 'application/pdf',
    ocrConfidence,
    ocrFields,
    verifyStatus,
    expiryDays,
    contractRisk,
    scannedAt:     new Date().toISOString(),
  };
}

function extractContractFields(text: string): Record<string, unknown> {
  const fields: Record<string, unknown> = {};

  const cNoMatch = text.match(/(?:Hợp đồng số|Contract No\.?)[:\s]+([A-Z0-9\-\/]{4,30})/i);
  if (cNoMatch) fields.contractNo = cNoMatch[1].trim();

  const valueMatch = text.match(/([0-9,\.]+)\s*(?:VND|đồng|USD)/i);
  if (valueMatch) {
    fields.value    = parseFloat(valueMatch[1].replace(/,/g,''));
    fields.currency = /USD/i.test(valueMatch[0]) ? 'USD' : 'VND';
  }

  const dates = text.match(/\d{2}\/\d{2}\/\d{4}/g) || [];
  if (dates[0]) fields.effectiveDate = dates[0];
  if (dates[1]) fields.expiryDate    = dates[1];

  return fields;
}

function analyzeContractRisk(text: string): OdcContractRisk {
  const riskClauses: string[] = [];

  if (/lãi suất phạt.*?\d+\s*%/i.test(text))         riskClauses.push('PENALTY_RATE');
  if (/vô hiệu|void ab initio/i.test(text))           riskClauses.push('VOID_CLAUSE');
  if (/ủy quyền không hủy ngang|irrevocable/i.test(text)) riskClauses.push('IRREVOCABLE_POA');
  if (/xử lý tài sản.*?không qua tòa/i.test(text))   riskClauses.push('EXTRAJUDICIAL');

  const parties: string[] = [];
  const partyMatch = text.match(/(?:Bên [AB]|Ngân hàng|Khách hàng)[:\s]+(.{5,60})/gi) || [];
  partyMatch.slice(0, 4).forEach(m => {
    const v = m.split(/[:\s]+/).slice(1).join(' ').trim();
    if (v) parties.push(v);
  });

  const governingLaw = /Luật Việt Nam|pháp luật Việt Nam/i.test(text) ? 'VN' :
                       /English law/i.test(text)  ? 'UK' : 'UNKNOWN';

  const dangerous = ['VOID_CLAUSE','IRREVOCABLE_POA','EXTRAJUDICIAL'];
  const riskLevel: 'LOW' | 'MEDIUM' | 'HIGH' =
    riskClauses.some(r => dangerous.includes(r)) ? 'HIGH' :
    riskClauses.length > 1                        ? 'MEDIUM' : 'LOW';

  return {
    riskLevel,
    riskClauses,
    governingLaw,
    parties,
    legalCompliant: !riskClauses.some(r => dangerous.includes(r)),
  };
}

// ─── KYC Risk Scoring ─────────────────────────────────────────────────────────

export function computeKycRisk(params: {
  fullName:    string;
  idNumber:    string;
  nationality: string;
  subjectType: KycSubjectType;
  documents:   OdcScanResult[];
}): KycRiskAssessment {
  const { fullName, idNumber, nationality, subjectType, documents } = params;
  let score = 0;
  const flags: string[] = [];

  // Rule 1: FATF high-risk country
  const ctry = (nationality || '').toUpperCase();
  if (FATF_BLACK_LIST.has(ctry)) { score += 50; flags.push('FATF_BLACK_LIST'); }
  else if (FATF_GREY_LIST.has(ctry)) { score += 25; flags.push('FATF_GREY_LIST'); }

  // Rule 2: PEP screening
  const nameLow = fullName.toLowerCase();
  const isPep   = PEP_KEYWORDS.some(k => nameLow.includes(k));
  if (isPep) { score += 25; flags.push('PEP_SUSPECTED'); }

  // Rule 3: Missing required documents
  const docTypes = documents.map(d => d.docType);
  const hasIdDoc = docTypes.includes('NATIONAL_ID') || docTypes.includes('PASSPORT')
                || docTypes.includes('BUSINESS_REG');
  if (!hasIdDoc) { score += 20; flags.push('MISSING_ID_DOCUMENT'); }

  // Rule 4: Invalid/expired/tampered documents
  const invalid  = documents.filter(d => d.verifyStatus === 'INVALID' || d.verifyStatus === 'EXPIRED').length;
  const tampered = documents.filter(d => d.verifyStatus === 'TAMPERED').length;
  if (invalid  > 0) { score += invalid  * 10; flags.push('INVALID_DOCUMENTS'); }
  if (tampered > 0) { score += 60;            flags.push('TAMPERED_DOCUMENT'); }

  // Rule 5: Legal entity extra scrutiny
  if (subjectType === 'LEGAL_ENTITY') score += 5;

  score = Math.min(score, 100);
  const riskLevel: AmlRiskLevel =
    score < 30 ? 'LOW' : score < 60 ? 'MEDIUM' : score < 80 ? 'HIGH' : 'CRITICAL';

  return {
    riskScore:    score,
    riskLevel,
    isPep,
    isSanctioned: false,   // Production: kiểm tra OFAC/UN/EU real-time
    flags,
    requiresEdd:  riskLevel === 'HIGH' || riskLevel === 'CRITICAL',
    assessedAt:   new Date().toISOString(),
  };
}

// ─── ISO 20022 auth.012 / auth.013 Builder ────────────────────────────────────

function escXml(s: string): string {
  return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
          .replace(/"/g,'&quot;').replace(/'/g,'&apos;');
}

export function buildAuth012Xml(params: {
  kycId:        string;
  requesterBic: string;
  requesterName: string;
  fullName:     string;
  idNumber:     string;
  idType:       string;
  nationality:  string;
  riskScore:    number;
  riskLevel:    string;
  isPep:        boolean;
  isSanctioned: boolean;
}): string {
  const msgId    = `AUTH012-${params.kycId}-${Date.now().toString(36).toUpperCase()}`;
  const creDtTm  = new Date().toISOString();
  return `<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:auth.012.001.02">
  <MnyLndrgRskRpt>
    <GrpHdr>
      <MsgId>${escXml(msgId)}</MsgId>
      <CreDtTm>${creDtTm}</CreDtTm>
      <RptgPty>
        <BICFI>${escXml(params.requesterBic)}</BICFI>
        <Nm>${escXml(params.requesterName)}</Nm>
      </RptgPty>
    </GrpHdr>
    <Rpt>
      <RptId>${escXml(params.kycId)}</RptId>
      <Cstmr>
        <Id>
          <Prvt>
            <Othr>
              <Id>${escXml(params.idNumber)}</Id>
              <SchmeNm><Cd>${escXml(params.idType)}</Cd></SchmeNm>
            </Othr>
          </Prvt>
        </Id>
        <Nm>${escXml(params.fullName)}</Nm>
        <CtryOfRes>${escXml(params.nationality)}</CtryOfRes>
      </Cstmr>
      <RskAssssmt>
        <RskScr>${params.riskScore}</RskScr>
        <RskLvl>${escXml(params.riskLevel)}</RskLvl>
        <PEP>${params.isPep}</PEP>
        <Snctnd>${params.isSanctioned}</Snctnd>
      </RskAssssmt>
    </Rpt>
  </MnyLndrgRskRpt>
</Document>`;
}

export function buildAuth013Xml(params: {
  kycId:        string;
  status:       KycStatus;
  docCount:     number;
  validDocCount: number;
  rejectReason?: string;
}): string {
  const msgId   = `AUTH013-${params.kycId}-${Date.now().toString(36).toUpperCase()}`;
  const creDtTm = new Date().toISOString();
  const isoSts  = { APPROVED: 'ACCP', REJECTED: 'RJCT', IN_REVIEW: 'PDNG', PENDING: 'RCVD', EXPIRED: 'CANC', SUSPENDED: 'HOLD' };
  const sts     = isoSts[params.status] || 'RCVD';
  return `<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:iso:std:iso:20022:tech:xsd:auth.013.001.02">
  <InvstgtnRqstRspn>
    <GrpHdr>
      <MsgId>${escXml(msgId)}</MsgId>
      <CreDtTm>${creDtTm}</CreDtTm>
    </GrpHdr>
    <Rspn>
      <OrgnlKycId>${escXml(params.kycId)}</OrgnlKycId>
      <RspnSts>${sts}</RspnSts>
      <RspnDtTm>${creDtTm}</RspnDtTm>
      ${params.rejectReason ? `<RjctRsn>${escXml(params.rejectReason)}</RjctRsn>` : ''}
      <DocVerif>
        <TtlDocs>${params.docCount}</TtlDocs>
        <VrfdDocs>${params.validDocCount}</VrfdDocs>
      </DocVerif>
    </Rspn>
  </InvstgtnRqstRspn>
</Document>`;
}

// ─── Main KYC Processing ──────────────────────────────────────────────────────

/**
 * Xử lý KYC submission (phía TypeScript gateway).
 * Dùng nội bộ bởi vnlh-router endpoint /vnlh/kyc/*.
 */
export function processKycSubmit(input: KycSubmitInput): KycSubmitResult {
  const {
    subjectType = 'INDIVIDUAL',
    fullName, idNumber, idType = 'NATIONAL_ID',
    nationality = 'VN', requesterBic,
    documents = [], linkedUetr,
  } = input;

  if (!fullName || !idNumber || !requesterBic) {
    throw new Error('Thiếu trường bắt buộc: fullName, idNumber, requesterBic');
  }

  // 1. ODC Scan tài liệu
  const scannedDocs: OdcScanResult[] = documents.map(doc =>
    scanOdcDocument({
      docType:  doc.docType,
      content:  doc.content,
      fileName: doc.fileName,
      mimeType: doc.mimeType,
      fileSize: doc.fileSize,
    })
  );

  // 2. Risk assessment
  const riskAssessment = computeKycRisk({
    fullName, idNumber, nationality,
    subjectType, documents: scannedDocs,
  });

  // 3. Auto status
  let status: KycStatus = 'PENDING';
  if (riskAssessment.riskLevel === 'CRITICAL' || riskAssessment.isSanctioned) {
    status = 'REJECTED';
  } else if (riskAssessment.requiresEdd) {
    status = 'IN_REVIEW';
  } else if (riskAssessment.riskLevel === 'LOW' && scannedDocs.every(d => d.verifyStatus === 'VALID')) {
    status = 'APPROVED';
  }

  // 4. KYC ID & record hash
  const kycId = `KYC-${new Date().toISOString().slice(0,10).replace(/-/g,'')}` +
                `-${createHash('sha256').update(fullName + idNumber + Date.now()).digest('hex').slice(0,8).toUpperCase()}`;

  const recordHash = createHash('sha256').update(JSON.stringify({
    kycId, fullName, idNumber, idType, requesterBic,
    docHashes: scannedDocs.map(d => d.docHash),
  })).digest('hex');

  // 5. Build ISO 20022 messages
  const auth012Xml = buildAuth012Xml({
    kycId, requesterBic, requesterName: '',
    fullName, idNumber, idType, nationality,
    riskScore:    riskAssessment.riskScore,
    riskLevel:    riskAssessment.riskLevel,
    isPep:        riskAssessment.isPep,
    isSanctioned: riskAssessment.isSanctioned,
  });

  const auth013Xml = buildAuth013Xml({
    kycId, status,
    docCount:      scannedDocs.length,
    validDocCount: scannedDocs.filter(d => d.verifyStatus === 'VALID').length,
  });

  const submittedAt = new Date().toISOString();

  return {
    kycId,
    status,
    riskLevel:   riskAssessment.riskLevel,
    riskScore:   riskAssessment.riskScore,
    requiresEdd: riskAssessment.requiresEdd,
    flags:       riskAssessment.flags,
    docCount:    scannedDocs.length,
    docStatuses: scannedDocs.map(d => ({
      docType:       d.docType,
      verifyStatus:  d.verifyStatus,
      ocrConfidence: d.ocrConfidence,
    })),
    recordHash,
    auth012Xml,
    auth013Xml,
    submittedAt,
    legalRefs: [
      'auth.012.001.02 — MoneyLaunderingRiskReport',
      'auth.013.001.02 — InvestigationRequestResponse',
      'FATF Recommendation 10 — Customer Due Diligence',
      'Thông tư 09/2023/TT-NHNN — eKYC điện tử',
      'Luật Phòng, chống rửa tiền 2022 — Điều 11',
    ],
  };
}
