import { useEffect, useMemo, useRef, useState } from 'react';
import { AlertTriangle, CheckCircle2, FileText, Info, ShieldCheck, UploadCloud } from 'lucide-react';
import { Avatar, Badge, Button, Card, DocumentUploadCard, formatINR, Input, SelectField } from '../';
import type { BadgeTone, DocStatus, OcrField } from '../';
import { SchemaGuard } from '../form';
import { useQuery, useZino } from '../../api/provider';
import { fieldFromSchema } from '../../api/schema';
import { ACTIVITIES } from '../../api/config';
import { OCR_FIELDS } from '../../api/forms';
import { crossCheck, type DocExtract, type DocKey } from '../../lib/kyc-match';
import type { ActivityBodyProps } from './types';

const ACT = ACTIVITIES.COLLECT_DOCUMENTS;
const F = ACT.fields;

const STATUS_TONE: Record<string, BadgeTone> = {
  pending: 'neutral',
  verified: 'success',
  mismatch: 'warning',
  incomplete: 'info',
};

const DOC_LABEL: Record<DocKey, string> = { pan: 'PAN', aadhaar: 'Aadhaar' };

function mismatchLine(f: { doc: DocKey; field: 'name' | 'dob'; captured: string; ocr: string }): string {
  const what = f.field === 'name' ? 'name' : 'DOB';
  const fmt = (v: string) => (f.field === 'name' ? `"${v || '—'}"` : v || '—');
  return `${DOC_LABEL[f.doc]} ${what} ${fmt(f.ocr)} ≠ captured ${fmt(f.captured)}`;
}

function OcrCapture({
  ocr,
  docKey,
  activityId,
  instanceId,
  onAutofill,
  onFile,
  onExtract,
}: {
  ocr: (typeof OCR_FIELDS)[keyof typeof OCR_FIELDS];
  docKey: DocKey;
  activityId: string;
  instanceId?: number | string;
  onAutofill: (targetField: string, value: unknown) => void;
  onFile: (file: File | null) => void;
  onExtract: (doc: DocKey, ex: DocExtract) => void;
}) {
  const { client } = useZino();
  const inputRef = useRef<HTMLInputElement>(null);
  const [status, setStatus] = useState<DocStatus>('empty');
  const [fileName, setFileName] = useState<string | null>(null);
  const [fields, setFields] = useState<OcrField[]>([]);
  const [error, setError] = useState<string | null>(null);

  function reset() {
    setStatus('empty');
    setFileName(null);
    setFields([]);
    setError(null);
    onFile(null);
    onExtract(docKey, { name: null, dob: null }); // clear this doc's KYC cross-check
  }

  async function handlePick(file: File) {
    setFileName(file.name);
    setStatus('processing');
    setError(null);
    onFile(file);
    try {
      const res = await client.extractOcr(file, { activityId, fieldId: ocr.id, instanceId });
      const extracted = res.extracted ?? {};
      for (const m of ocr.mappings) {
        if (Object.prototype.hasOwnProperty.call(extracted, m.extraction_key)) {
          onAutofill(m.target_field, extracted[m.extraction_key]);
        }
      }
      const asStr = (v: unknown) => (v == null ? null : String(v));
      onExtract(docKey, { name: asStr(extracted.full_name), dob: asStr(extracted.date_of_birth) });
      setFields(
        Object.entries(extracted)
          .filter(([, v]) => v !== null && v !== undefined && v !== '')
          .map(([k, v]) => ({ label: k.replace(/_/g, ' ').replace(/\b\w/g, (c) => c.toUpperCase()), value: String(v), mono: /number|pan|aadhaar/i.test(k) })),
      );
      setStatus('extracted');
      if (res.parse_error) setError(res.parse_error);
    } catch (e) {
      setStatus('empty');
      setError(e instanceof Error ? e.message : ((e as { message?: string })?.message ?? 'OCR failed'));
      onFile(null);
    }
  }

  return (
    <div className="h-full">
      <input
        ref={inputRef}
        type="file"
        accept=".pdf,.png,.jpg,.jpeg"
        className="hidden"
        onChange={(e) => {
          const f = e.target.files?.[0];
          if (f) handlePick(f);
          e.target.value = '';
        }}
      />
      <DocumentUploadCard
        docType={ocr.docLabel}
        status={status}
        fields={fields}
        fileName={fileName}
        onUpload={() => inputRef.current?.click()}
        onConfirm={() => setStatus('verified')}
        onReplace={() => inputRef.current?.click()}
        onRemove={reset}
      />
      {error && <div className="text-2xs text-amber-700 mt-1.5">{error}</div>}
    </div>
  );
}

export function DocumentsBody({ instanceId, record, onSuccess }: ActivityBodyProps) {
  const { client } = useZino();

  const schemaQ = useQuery(() => client.formSchema(ACT.uid, instanceId), [instanceId]);
  const docStatusOptions = useMemo(() => fieldFromSchema(schemaQ.data, F.docStatus)?.options ?? [], [schemaQ.data]);

  const [pan, setPan] = useState('');
  const [aadhaar, setAadhaar] = useState('');
  const [verifiedIncome, setVerifiedIncome] = useState(0);
  const [docStatus, setDocStatus] = useState('verified');
  const [files, setFiles] = useState<Record<string, File | null>>({});
  const [ocrExtracts, setOcrExtracts] = useState<Partial<Record<DocKey, DocExtract>>>({});
  const statusTouched = useRef(false);

  useEffect(() => {
    if (!record) return;
    setPan(record.pan_number || '');
    setAadhaar(record.aadhaar_number || '');
    setVerifiedIncome((record.verified_income as number) || record.annual_income || 0);
    setDocStatus(record.doc_status || 'verified');
    setFiles({});
    setOcrExtracts({});
    statusTouched.current = false;
  }, [record]);

  const setFile = (fieldId: string) => (f: File | null) => setFiles((p) => ({ ...p, [fieldId]: f }));
  const applyExtract = (doc: DocKey, ex: DocExtract) => setOcrExtracts((p) => ({ ...p, [doc]: ex }));

  const kyc = useMemo(
    () => crossCheck({ name: record?.lead_name, dob: record?.date_of_birth }, ocrExtracts),
    [record, ocrExtracts],
  );

  useEffect(() => {
    if (kyc.hasMismatch && !statusTouched.current) setDocStatus('mismatch');
  }, [kyc.hasMismatch]);

  const applyAutofill = (target: string, value: unknown) => {
    const v = value == null ? '' : String(value);
    if (target === F.panNumber) setPan(v.toUpperCase());
    else if (target === F.aadhaarNumber) setAadhaar(v.replace(/\s/g, ''));
  };

  const [submitting, setSubmitting] = useState(false);
  const [result, setResult] = useState<{ ok: boolean; msg: string } | null>(null);

  async function submit() {
    setSubmitting(true);
    setResult(null);
    const activityId = ACT.uid;
    try {
      const fileData: Record<string, unknown> = {};
      for (const [fieldId, file] of Object.entries(files)) {
        if (!file) continue;
        const meta = await client.uploadFile(file, { activityId, fieldId, instanceId });
        fileData[fieldId] = [meta];
      }
      const res = await client.performActivity(instanceId, activityId, {
        [F.panNumber]: pan,
        [F.aadhaarNumber]: aadhaar,
        [F.verifiedIncome]: verifiedIncome,
        [F.docStatus]: docStatus,
        ...fileData,
      });
      setResult({ ok: true, msg: 'Documents submitted — lead advanced to Documents Collected.' });
      onSuccess?.(res);
    } catch (e) {
      setResult({ ok: false, msg: e instanceof Error ? e.message : ((e as { message?: string })?.message ?? 'Submit failed') });
    } finally {
      setSubmitting(false);
    }
  }

  const checklist = [
    { doc: 'PAN number', done: !!pan },
    { doc: 'Aadhaar number', done: !!aadhaar },
    { doc: 'Verified income', done: verifiedIncome > 0 },
    { doc: 'Status confirmed', done: docStatus === 'verified' },
  ];
  const completion = Math.round((checklist.filter((c) => c.done).length / checklist.length) * 100);

  return (
    <SchemaGuard
      loading={schemaQ.loading}
      error={schemaQ.error}
      action="collect documents for this lead"
    >
    <div className="grid gap-[18px] items-start grid-cols-1 lg:grid-cols-[1fr_320px]">
      <div className="flex flex-col gap-[18px] min-w-0">
        <div className="flex items-center gap-3 bg-card border border-border-subtle rounded-lg px-[18px] py-3.5 shadow-sm">
          {record ? (
            <>
              <Avatar name={record.lead_name ?? `Lead ${record.instance_id}`} size={40} />
              <div className="flex-1">
                <div className="text-base font-bold text-strong">
                  KYC for {record.lead_name ?? `Lead ${record.instance_id}`} · #{record.instance_id}
                </div>
                <div className="text-xs text-faint">Collected by Aria Eligibility · {record.current_state_name}</div>
              </div>
            </>
          ) : (
            <div className="flex-1 text-sm text-faint">No lead record provided.</div>
          )}
        </div>

        {result && (
          <div
            className={
              result.ok
                ? 'flex items-center gap-2 text-sm text-emerald-700 bg-emerald-100 border border-emerald-300 rounded-md px-4 py-3'
                : 'text-sm text-amber-700 bg-escalated-soft border border-amber-300 rounded-md px-4 py-3'
            }
          >
            {result.ok && <CheckCircle2 size={16} />}
            {result.msg}
          </div>
        )}

        {kyc.hasMismatch ? (
          <div className="flex items-start gap-2.5 text-sm text-amber-800 bg-escalated-soft border border-amber-300 rounded-md px-4 py-3">
            <AlertTriangle size={16} className="text-amber-600 shrink-0 mt-0.5" />
            <div className="flex-1">
              <div className="font-semibold">Identity mismatch — review before advancing</div>
              <ul className="mt-1.5 list-disc pl-4 space-y-0.5">
                {kyc.fields
                  .filter((f) => f.status === 'mismatch')
                  .map((f) => (
                    <li key={`${f.doc}-${f.field}`} className="font-numeric">
                      {mismatchLine(f)}
                    </li>
                  ))}
              </ul>
              <div className="mt-1.5 text-xs text-amber-700">
                Document status set to "Mismatch". Override only once you've confirmed the documents belong to this lead.
              </div>
            </div>
          </div>
        ) : kyc.anyChecked ? (
          <div className="flex items-center gap-2 text-sm text-emerald-700 bg-emerald-100 border border-emerald-300 rounded-md px-4 py-3">
            <ShieldCheck size={16} />
            OCR identity matches the captured lead (name + DOB).
          </div>
        ) : null}

        <div className="grid grid-cols-2 gap-[18px]">
          <OcrCapture
            ocr={OCR_FIELDS.pan}
            docKey="pan"
            activityId={ACT.uid}
            instanceId={instanceId}
            onAutofill={applyAutofill}
            onFile={setFile(OCR_FIELDS.pan.id)}
            onExtract={applyExtract}
          />
          <OcrCapture
            ocr={OCR_FIELDS.aadhaar}
            docKey="aadhaar"
            activityId={ACT.uid}
            instanceId={instanceId}
            onAutofill={applyAutofill}
            onFile={setFile(OCR_FIELDS.aadhaar.id)}
            onExtract={applyExtract}
          />
        </div>

        <Card title="KYC details">
          <div className="grid grid-cols-2 gap-4">
            <Input label="PAN number" value={pan} onChange={(e) => setPan(e.target.value.toUpperCase())} placeholder="ABCDE1234F" />
            <Input label="Aadhaar number" value={aadhaar} onChange={(e) => setAadhaar(e.target.value)} placeholder="XXXX XXXX XXXX" />
            <Input
              label="Verified income"
              prefix="₹"
              type="number"
              value={verifiedIncome}
              onChange={(e) => setVerifiedIncome(Number(e.target.value) || 0)}
            />
            <SelectField
              label="Document status"
              required
              options={docStatusOptions}
              value={docStatus}
              onChange={(v) => {
                statusTouched.current = true;
                setDocStatus(v as DocStatus);
              }}
            />
          </div>

          <div className="mt-4">
            <SalarySlipUpload value={files[F.salarySlip] ?? null} onChange={setFile(F.salarySlip)} />
          </div>

          <div className="flex items-start gap-3 bg-info-soft rounded-md px-3.5 py-3 mt-4">
            <Info size={16} className="text-sky-600 shrink-0 mt-0.5" />
            <div className="text-xs text-muted leading-normal">
              Upload PAN / Aadhaar to auto-extract the numbers via OCR, then confirm the values and the verification
              status before advancing. Files upload on submit.
            </div>
          </div>
          <div className="flex gap-2.5 mt-5">
            <Button variant="primary" disabled={submitting} onClick={submit}>
              {submitting ? 'Submitting…' : 'Submit documents'}
            </Button>
          </div>
        </Card>
      </div>

      <div className="flex flex-col gap-4">
        <section className="bg-card rounded-lg border border-border-subtle shadow-sm p-5">
          <h3 className="mt-0 mb-3.5 text-sm font-semibold text-strong">Document checklist</h3>
          <div className="flex flex-col gap-2.5">
            {checklist.map((c) => (
              <div key={c.doc} className="flex items-center justify-between">
                <span className="text-sm text-body">{c.doc}</span>
                <Badge tone={c.done ? 'success' : 'neutral'} dot={c.done}>
                  {c.done ? 'Done' : 'Pending'}
                </Badge>
              </div>
            ))}
          </div>

          <div className="h-px bg-border-subtle my-4" />

          <div className="flex items-center justify-between mb-3">
            <span className="text-sm text-body">Identity check</span>
            <Badge tone={kyc.hasMismatch ? 'warning' : kyc.anyChecked ? 'success' : 'neutral'} dot>
              {kyc.hasMismatch ? 'Mismatch' : kyc.anyChecked ? 'Verified' : 'Awaiting OCR'}
            </Badge>
          </div>

          <div className="flex items-center justify-between mb-1">
            <span className="text-sm text-muted">Current status</span>
            <Badge tone={STATUS_TONE[docStatus] ?? 'neutral'} dot>
              {docStatusOptions.find((o) => o.value === docStatus)?.label ?? docStatus}
            </Badge>
          </div>

          <div className="flex items-center justify-between mb-3.5 mt-3">
            <span className="text-sm text-muted">KYC completion</span>
            <span className="font-numeric font-extrabold text-xl text-sunrise-600">{completion}%</span>
          </div>
          <div className="h-2 bg-slate-100 rounded-pill overflow-hidden mb-[18px]">
            <div className="h-full bg-sunrise transition-[width] duration-500" style={{ width: `${completion}%` }} />
          </div>
        </section>

        {record?.annual_income ? (
          <div className="bg-info-soft rounded-md px-3.5 py-3 text-xs text-muted">
            Stated annual income on file: ₹{formatINR(record.annual_income)}.
          </div>
        ) : null}
      </div>
    </div>
    </SchemaGuard>
  );
}

function SalarySlipUpload({ value, onChange }: { value: File | null; onChange: (f: File | null) => void }) {
  const ref = useRef<HTMLInputElement>(null);
  return (
    <div>
      <span className="text-sm font-medium text-muted">Salary slip</span>
      <input
        ref={ref}
        type="file"
        accept=".pdf,.png,.jpg,.jpeg"
        className="hidden"
        onChange={(e) => {
          onChange(e.target.files?.[0] ?? null);
          e.target.value = '';
        }}
      />
      <button
        type="button"
        onClick={() => ref.current?.click()}
        className="mt-1.5 w-full flex items-center gap-2.5 border border-dashed border-border-default rounded-md bg-slate-50 px-3.5 py-3 cursor-pointer text-left"
      >
        {value ? <FileText size={18} className="text-sunrise-600 shrink-0" /> : <UploadCloud size={18} className="text-sunrise-500 shrink-0" />}
        <span className="text-sm text-body truncate flex-1">{value ? value.name : 'Upload salary slip (PDF / image)'}</span>
        {value && (
          <span
            onClick={(e) => {
              e.stopPropagation();
              onChange(null);
            }}
            className="text-2xs font-semibold text-link"
          >
            Remove
          </span>
        )}
      </button>
    </div>
  );
}
