"use client";

import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { CustomerPicker } from "@/components/CustomerPicker";
import { createPolicy, getLookups, updatePolicy } from "@/lib/api";
import {
  PAYMENT_FREQUENCY_LABELS,
  type Currency,
  type LookupsResponse,
  type PaymentFrequency,
  type PolicyDetail,
  type PolicyInput,
} from "@/lib/types";
import {
  computeTax,
  computeTotal,
  formatRate,
  resolveTaxRate,
  surchargeApplies,
  taxableBase,
} from "@/lib/premium";

function toDateInput(v: string | null | undefined): string {
  if (!v) return "";
  const d = new Date(v);
  return isNaN(d.getTime()) ? "" : d.toISOString().slice(0, 10);
}
function numOrUndef(v: string): number | undefined {
  const t = v.trim();
  if (t === "") return undefined;
  const n = Number(t);
  return isNaN(n) ? undefined : n;
}
function s(v: string): string | undefined {
  const t = v.trim();
  return t === "" ? undefined : t;
}

type V = {
  policyNumber: string;
  policyTypeId: string;
  insuranceProviderId: string;
  agentName: string;
  policyDate: string;
  policyFrom: string;
  policyTo: string;
  netPremium: string;
  surcharge: string;
  policyFee: string;
  brokerFee: string;
  commission: string;
  /** Blank means "use the computed figure". Only ever holds a value once the
   *  operator overrides it, so a later change to prima neta keeps flowing
   *  through instead of being frozen by a value the form itself wrote. */
  tax: string;
  total: string;
  paymentFrequency: PaymentFrequency | "";
  currency: Currency;
  liquidated: boolean;
  liquidationNumber: string;
  liquidationDate: string;
  endorsement: boolean;
  observations: string;
  notes: string;
};

function initial(p?: PolicyDetail): V {
  return {
    policyNumber: p?.policyNumber ?? "",
    policyTypeId: p?.policyType?.id ?? "",
    insuranceProviderId: p?.insuranceProvider?.id ?? "",
    agentName: p?.agentName ?? "",
    policyDate: toDateInput(p?.policyDate),
    policyFrom: toDateInput(p?.policyFrom),
    policyTo: toDateInput(p?.policyTo),
    netPremium: p?.netPremium != null ? String(p.netPremium) : "",
    surcharge: p?.surcharge != null ? String(p.surcharge) : "",
    policyFee: p?.policyFee != null ? String(p.policyFee) : "",
    brokerFee: p?.brokerFee != null ? String(p.brokerFee) : "",
    commission: p?.commission != null ? String(p.commission) : "",
    tax: p?.tax != null ? String(p.tax) : "",
    total: p?.total != null ? String(p.total) : "",
    paymentFrequency: p?.paymentFrequency ?? "",
    currency: (p?.currency as Currency) ?? "MXN",
    liquidated: p?.liquidated ?? false,
    liquidationNumber: p?.liquidationNumber ?? "",
    liquidationDate: toDateInput(p?.liquidationDate),
    endorsement: p?.endorsement ?? false,
    observations: p?.observations ?? "",
    notes: p?.notes ?? "",
  };
}

export function PolicyForm({
  policy,
  fixedCustomerId,
  fixedCustomerName,
}: {
  policy?: PolicyDetail;
  fixedCustomerId?: string;
  fixedCustomerName?: string;
}) {
  const router = useRouter();
  const editing = !!policy;
  const [v, setV] = useState<V>(() => initial(policy));
  const [lookups, setLookups] = useState<LookupsResponse | null>(null);
  const [customerId, setCustomerId] = useState(
    policy?.customer.id ?? fixedCustomerId ?? "",
  );
  const [customerName, setCustomerName] = useState(
    policy?.customer.name ?? fixedCustomerName ?? "",
  );
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    getLookups().then(setLookups).catch(() => setLookups(null));
  }, []);

  function set<K extends keyof V>(k: K, val: V[K]) {
    setV((p) => ({ ...p, [k]: val }));
  }

  // IVA and Total are the only two figures the form derives. Everything else,
  // the recargo included, is keyed by hand — the carrier quotes the financing
  // charge, we do not compute it.
  const selectedType = lookups?.types.find((t) => t.id === v.policyTypeId);
  const taxRate = resolveTaxRate(policy?.taxRate, selectedType?.taxRate);
  const parts = {
    netPremium: v.netPremium,
    // A recargo on an annual policy is a data-entry mistake, so it is dropped
    // from the arithmetic as well as disabled in the UI. Otherwise switching
    // ANNUAL after typing one would leave it silently inflating the IVA.
    surcharge: surchargeApplies(v.paymentFrequency || null) ? v.surcharge : "",
    policyFee: v.policyFee,
  };
  const computedTax = computeTax(parts, taxRate);
  const computedTotal = computeTotal(parts, taxRate);
  // Blank field = take the computed figure. A typed one wins, so staff can key
  // the carrier's rounding verbatim when it disagrees with ours by a centavo.
  const effectiveTax = v.tax.trim() === "" ? computedTax : Number(v.tax);
  const effectiveTotal = v.total.trim() === "" ? computedTotal : Number(v.total);
  const showSurcharge = surchargeApplies(v.paymentFrequency || null);

  async function submit(e: React.FormEvent) {
    e.preventDefault();
    if (!customerId) {
      setError("Seleccione un cliente.");
      return;
    }
    setSaving(true);
    setError(null);
    const base = {
      policyNumber: v.policyNumber.trim(),
      policyTypeId: s(v.policyTypeId),
      insuranceProviderId: s(v.insuranceProviderId),
      agentName: s(v.agentName),
      policyDate: s(v.policyDate),
      policyFrom: s(v.policyFrom),
      policyTo: s(v.policyTo),
      netPremium: numOrUndef(v.netPremium),
      surcharge: showSurcharge ? numOrUndef(v.surcharge) : undefined,
      policyFee: numOrUndef(v.policyFee),
      brokerFee: numOrUndef(v.brokerFee),
      commission: numOrUndef(v.commission),
      // The derived figures are persisted, not recomputed on read: the printed
      // policy is the record of truth and a later rate change must not silently
      // restate what was issued. `taxRate` rides along for the same reason.
      tax: Number.isFinite(effectiveTax) ? effectiveTax : undefined,
      taxRate,
      total: Number.isFinite(effectiveTotal) ? effectiveTotal : undefined,
      paymentFrequency: v.paymentFrequency || undefined,
      currency: v.currency,
      liquidated: v.liquidated,
      liquidationNumber: s(v.liquidationNumber),
      liquidationDate: s(v.liquidationDate),
      endorsement: v.endorsement,
      observations: s(v.observations),
      notes: s(v.notes),
    };
    try {
      if (editing) {
        const saved = await updatePolicy(policy!.id, base);
        router.push(`/polizas/${saved.id}`);
      } else {
        const payload: PolicyInput = { ...base, customerId };
        const saved = await createPolicy(payload);
        router.push(`/polizas/${saved.id}`);
      }
    } catch (e2) {
      setError((e2 as Error)?.message ?? "No se pudo guardar la póliza.");
      setSaving(false);
    }
  }

  return (
    <form onSubmit={submit}>
      {error && <div className="state-box state-error">{error}</div>}

      <div className="card" style={{ padding: 20, marginBottom: 16 }}>
        <h2 className="section-title" style={{ marginBottom: 14 }}>Datos de la póliza</h2>
        <div className="form-grid">
          <label className="field">
            <span className="field-label">Cliente *</span>
            {editing ? (
              <input className="input" value={customerName} disabled />
            ) : (
              <CustomerPicker
                value={customerId}
                valueName={customerName}
                onPick={(id, name) => {
                  setCustomerId(id);
                  setCustomerName(name);
                }}
              />
            )}
          </label>
          <label className="field">
            <span className="field-label">Número de póliza *</span>
            <input className="input" required value={v.policyNumber}
              onChange={(e) => set("policyNumber", e.target.value)} />
          </label>
          <label className="field">
            <span className="field-label">Tipo</span>
            <select className="select" value={v.policyTypeId}
              onChange={(e) => set("policyTypeId", e.target.value)}>
              <option value="">—</option>
              {lookups?.types.map((t) => (
                <option key={t.id} value={t.id}>{t.name}</option>
              ))}
            </select>
          </label>
          <label className="field">
            <span className="field-label">Aseguradora</span>
            <select className="select" value={v.insuranceProviderId}
              onChange={(e) => set("insuranceProviderId", e.target.value)}>
              <option value="">—</option>
              {lookups?.providers.map((p) => (
                <option key={p.id} value={p.id}>{p.name}</option>
              ))}
            </select>
          </label>
          <label className="field">
            <span className="field-label">Agente</span>
            <input className="input" value={v.agentName}
              onChange={(e) => set("agentName", e.target.value)} />
          </label>
          <label className="field">
            <span className="field-label">Moneda</span>
            <select className="select" value={v.currency}
              onChange={(e) => set("currency", e.target.value as Currency)}>
              <option value="MXN">MXN</option>
              <option value="USD">USD</option>
            </select>
          </label>
        </div>
      </div>

      <div className="card" style={{ padding: 20, marginBottom: 16 }}>
        <h2 className="section-title" style={{ marginBottom: 14 }}>Vigencia</h2>
        <div className="form-grid">
          <label className="field">
            <span className="field-label">Emisión</span>
            <input className="input" type="date" value={v.policyDate}
              onChange={(e) => set("policyDate", e.target.value)} />
          </label>
          <label className="field">
            <span className="field-label">Desde</span>
            <input className="input" type="date" value={v.policyFrom}
              onChange={(e) => set("policyFrom", e.target.value)} />
          </label>
          <label className="field">
            <span className="field-label">Hasta</span>
            <input className="input" type="date" value={v.policyTo}
              onChange={(e) => set("policyTo", e.target.value)} />
          </label>
          <label className="field">
            <span className="field-label">Forma de pago</span>
            <select className="select" value={v.paymentFrequency}
              onChange={(e) =>
                set("paymentFrequency", e.target.value as PaymentFrequency | "")
              }>
              <option value="">—</option>
              {(
                Object.keys(PAYMENT_FREQUENCY_LABELS) as PaymentFrequency[]
              ).map((f) => (
                <option key={f} value={f}>{PAYMENT_FREQUENCY_LABELS[f]}</option>
              ))}
            </select>
          </label>
        </div>
      </div>

      <div className="card" style={{ padding: 20, marginBottom: 16 }}>
        <h2 className="section-title" style={{ marginBottom: 4 }}>Primas</h2>
        <p className="muted" style={{ fontSize: 12, marginBottom: 14 }}>
          IVA y prima total se calculan solos sobre (prima neta + recargo +
          derecho de póliza). Puede sobrescribirlos si la póliza impresa
          redondea distinto.
        </p>
        <div className="form-grid">
          <label className="field">
            <span className="field-label">Prima neta</span>
            <input className="input" type="number" step="0.01" value={v.netPremium}
              onChange={(e) => set("netPremium", e.target.value)} />
          </label>
          <label className="field">
            <span className="field-label">Recargo</span>
            <input className="input" type="number" step="0.01" value={v.surcharge}
              disabled={!showSurcharge}
              onChange={(e) => set("surcharge", e.target.value)} />
            <span className="field-hint">
              {showSurcharge
                ? "Lo cotiza la aseguradora — se captura a mano."
                : "No aplica en pago anual ni de contado."}
            </span>
          </label>
          <label className="field">
            <span className="field-label">Derecho de póliza</span>
            <input className="input" type="number" step="0.01" value={v.policyFee}
              onChange={(e) => set("policyFee", e.target.value)} />
          </label>
          <label className="field">
            <span className="field-label">IVA ({formatRate(taxRate)})</span>
            <input className="input" type="number" step="0.01"
              placeholder={computedTax.toFixed(2)} value={v.tax}
              onChange={(e) => set("tax", e.target.value)} />
            <span className="field-hint">
              Calculado: {computedTax.toFixed(2)} sobre base{" "}
              {taxableBase(parts).toFixed(2)}
              {selectedType?.taxRate == null &&
                policy?.taxRate == null &&
                " · tasa por omisión, configúrela en Catálogos"}
            </span>
          </label>
          <label className="field">
            <span className="field-label">Prima total</span>
            <input className="input" type="number" step="0.01"
              placeholder={computedTotal.toFixed(2)} value={v.total}
              onChange={(e) => set("total", e.target.value)} />
            <span className="field-hint">
              Calculado: {computedTotal.toFixed(2)}
            </span>
          </label>
          <label className="field">
            <span className="field-label">Comisión</span>
            <input className="input" type="number" step="0.01" value={v.commission}
              onChange={(e) => set("commission", e.target.value)} />
          </label>
          <label className="field">
            <span className="field-label">Honorarios</span>
            <input className="input" type="number" step="0.01" value={v.brokerFee}
              onChange={(e) => set("brokerFee", e.target.value)} />
          </label>
        </div>
      </div>

      <div className="card" style={{ padding: 20, marginBottom: 16 }}>
        <h2 className="section-title" style={{ marginBottom: 14 }}>Liquidación</h2>
        <div className="form-grid">
          <label className="field">
            <span className="field-label">Liquidada</span>
            <input type="checkbox" checked={v.liquidated}
              onChange={(e) => set("liquidated", e.target.checked)} />
          </label>
          <label className="field">
            <span className="field-label">Endoso</span>
            <input type="checkbox" checked={v.endorsement}
              onChange={(e) => set("endorsement", e.target.checked)} />
          </label>
          <label className="field">
            <span className="field-label">No. liquidación</span>
            <input className="input" value={v.liquidationNumber}
              onChange={(e) => set("liquidationNumber", e.target.value)} />
          </label>
          <label className="field">
            <span className="field-label">Fecha liquidación</span>
            <input className="input" type="date" value={v.liquidationDate}
              onChange={(e) => set("liquidationDate", e.target.value)} />
          </label>
        </div>
        <label className="field" style={{ marginTop: 14 }}>
          <span className="field-label">Observaciones</span>
          <textarea className="input" rows={2} value={v.observations}
            onChange={(e) => set("observations", e.target.value)} />
        </label>
        <label className="field" style={{ marginTop: 12 }}>
          <span className="field-label">Notas</span>
          <textarea className="input" rows={2} value={v.notes}
            onChange={(e) => set("notes", e.target.value)} />
        </label>
      </div>

      <div className="form-actions">
        <button type="submit" className="btn btn-primary" disabled={saving}>
          {saving ? "Guardando…" : editing ? "Guardar cambios" : "Crear póliza"}
        </button>
        <button type="button" className="btn btn-outline" onClick={() => router.back()}>
          Cancelar
        </button>
      </div>
    </form>
  );
}
