"use client";

import { useCallback, useEffect, useRef, useState, use, FormEvent } from "react";
import Link from "next/link";
import {
  PageHeader, PageLoader, Modal, Badge, TableShell,
  fmtKes2, inputCls, btnPrimary, btnGhost, Field, Spinner,
} from "@/components/ui";

interface Detail {
  invoice: {
    id: number; invoiceNo: string; clientName: string; clientEmail: string; clientPhone: string;
    clientAddress: string; issueDate: string; dueDate: string; status: string; notes: string;
    subtotal: number; taxRate: number; taxAmount: number; total: number; amountPaid: number;
  };
  items: Array<{ id: number; description: string; quantity: number; unitPrice: number; amount: number }>;
  payments: Array<{ id: number; amount: number; method: string; reference: string; paidAt: string }>;
  mpesa: Array<{ id: number; phone: string; amount: number; status: string; mpesaReceipt: string; resultDesc: string; simulated: boolean }>;
}

export default function InvoiceDetailPage({ params }: { params: Promise<{ id: string }> }) {
  const { id } = use(params);
  const [data, setData] = useState<Detail | null>(null);
  const [error, setError] = useState("");
  const [stkOpen, setStkOpen] = useState(false);
  const [payOpen, setPayOpen] = useState(false);
  const [busy, setBusy] = useState(false);
  const [stkMsg, setStkMsg] = useState("");
  const [modalErr, setModalErr] = useState("");
  const [phone, setPhone] = useState("");
  const [stkAmount, setStkAmount] = useState(0);
  const [pay, setPay] = useState({ amount: 0, method: "bank", reference: "" });
  const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);

  const load = useCallback(async () => {
    const res = await fetch(`/api/invoices/${id}`);
    const d = await res.json();
    if (!res.ok) setError(d.error || "Failed to load");
    else {
      setData(d);
      const bal = Math.max(0, d.invoice.total - d.invoice.amountPaid);
      setStkAmount((prev) => (prev > 0 ? prev : bal));
      setPay((p) => ({ ...p, amount: p.amount > 0 ? p.amount : bal }));
    }
  }, [id]);

  useEffect(() => { load(); }, [load]);
  useEffect(() => () => { if (pollRef.current) clearInterval(pollRef.current); }, []);

  const balance = data ? Math.max(0, data.invoice.total - data.invoice.amountPaid) : 0;

  const sendStk = async (e: FormEvent) => {
    e.preventDefault();
    setBusy(true);
    setModalErr("");
    setStkMsg("");
    try {
      const res = await fetch("/api/mpesa/stk", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ phone, amount: stkAmount, invoiceId: Number(id) }),
      });
      const d = await res.json();
      if (!res.ok) throw new Error(d.error || "STK push failed");
      setStkMsg(
        d.transaction.simulated
          ? "STK push sent (simulation mode — will auto-confirm in a few seconds)…"
          : "STK push sent. Ask the customer to enter their M-Pesa PIN…",
      );
      // Poll for completion
      pollRef.current = setInterval(async () => {
        const txRes = await fetch("/api/mpesa/transactions");
        const txs = await txRes.json();
        const tx = Array.isArray(txs) ? txs.find((t: { id: number }) => t.id === d.transaction.id) : null;
        if (tx && tx.status !== "pending") {
          if (pollRef.current) clearInterval(pollRef.current);
          setBusy(false);
          if (tx.status === "success") {
            setStkMsg(`✅ Payment received! Receipt: ${tx.mpesaReceipt}`);
            await load();
            setTimeout(() => setStkOpen(false), 1800);
          } else {
            setModalErr(`Payment failed: ${tx.resultDesc || "declined"}`);
          }
        }
      }, 2500);
    } catch (err) {
      setModalErr((err as Error).message);
      setBusy(false);
    }
  };

  const recordPayment = async (e: FormEvent) => {
    e.preventDefault();
    setBusy(true);
    setModalErr("");
    try {
      const res = await fetch("/api/payments", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ invoiceId: Number(id), ...pay }),
      });
      const d = await res.json();
      if (!res.ok) throw new Error(d.error || "Failed to record payment");
      await load();
      setPayOpen(false);
    } catch (err) {
      setModalErr((err as Error).message);
    } finally {
      setBusy(false);
    }
  };

  const setStatus = async (status: string) => {
    if (!data) return;
    const prev = data;
    setData({ ...data, invoice: { ...data.invoice, status } }); // optimistic
    const res = await fetch(`/api/invoices/${id}`, {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ status }),
    });
    if (!res.ok) setData(prev);
  };

  if (error) return <p className="rounded-lg bg-rose-50 p-4 text-sm text-rose-700">{error}</p>;
  if (!data) return <PageLoader label="Loading invoice…" />;
  const inv = data.invoice;

  return (
    <div>
      <PageHeader
        title={inv.invoiceNo}
        subtitle={`Billed to ${inv.clientName}`}
        action={
          <div className="flex flex-wrap items-center gap-2">
            <Badge value={inv.status} />
            {inv.status === "draft" && <button onClick={() => setStatus("sent")} className={btnGhost}>Mark sent</button>}
            <Link href="/dashboard/invoices" className={btnGhost}>← Back</Link>
            <button onClick={() => window.print()} className={btnGhost}>🖨 Print</button>
          </div>
        }
      />

      <div className="grid grid-cols-1 gap-6 xl:grid-cols-3">
        <div className="space-y-6 xl:col-span-2">
          <div className="rounded-2xl border border-slate-200 bg-white p-5 sm:p-6">
            <div className="flex flex-col gap-4 sm:flex-row sm:justify-between">
              <div>
                <p className="text-xs font-semibold uppercase tracking-wide text-slate-400">Billed to</p>
                <p className="mt-1 font-semibold text-slate-900">{inv.clientName}</p>
                <p className="text-sm text-slate-500">{inv.clientAddress}</p>
                <p className="text-sm text-slate-500">{inv.clientEmail} · {inv.clientPhone}</p>
              </div>
              <div className="sm:text-right">
                <p className="text-sm text-slate-500">Issued: <span className="font-medium text-slate-700">{inv.issueDate}</span></p>
                <p className="text-sm text-slate-500">Due: <span className="font-medium text-slate-700">{inv.dueDate}</span></p>
              </div>
            </div>

            <div className="mt-5 overflow-x-auto">
              <table className="min-w-full text-sm">
                <thead>
                  <tr className="border-b border-slate-200 text-left text-xs font-semibold uppercase text-slate-400">
                    <th className="py-2 pr-4">Description</th>
                    <th className="py-2 pr-4">Qty</th>
                    <th className="py-2 pr-4">Unit price</th>
                    <th className="py-2 text-right">Amount</th>
                  </tr>
                </thead>
                <tbody className="divide-y divide-slate-100">
                  {data.items.map((it) => (
                    <tr key={it.id}>
                      <td className="py-2.5 pr-4 text-slate-800">{it.description}</td>
                      <td className="py-2.5 pr-4 text-slate-600">{it.quantity}</td>
                      <td className="whitespace-nowrap py-2.5 pr-4 text-slate-600">{fmtKes2(it.unitPrice)}</td>
                      <td className="whitespace-nowrap py-2.5 text-right font-medium">{fmtKes2(it.amount)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>

            <div className="mt-4 flex justify-end">
              <div className="w-full max-w-xs space-y-1 text-sm">
                <div className="flex justify-between text-slate-500"><span>Subtotal</span><span>{fmtKes2(inv.subtotal)}</span></div>
                <div className="flex justify-between text-slate-500"><span>VAT ({inv.taxRate}%)</span><span>{fmtKes2(inv.taxAmount)}</span></div>
                <div className="flex justify-between border-t border-slate-200 pt-2 text-base font-bold text-slate-900"><span>Total</span><span>{fmtKes2(inv.total)}</span></div>
                <div className="flex justify-between text-emerald-700"><span>Paid</span><span>{fmtKes2(inv.amountPaid)}</span></div>
                <div className="flex justify-between font-semibold text-amber-700"><span>Balance</span><span>{fmtKes2(balance)}</span></div>
              </div>
            </div>
          </div>

          <section>
            <h2 className="mb-3 text-sm font-semibold text-slate-700">Payment history</h2>
            {data.payments.length === 0 ? (
              <p className="rounded-xl border border-dashed border-slate-300 bg-white p-6 text-center text-sm text-slate-400">
                No payments recorded yet.
              </p>
            ) : (
              <TableShell head={["Date", "Method", "Reference", "Amount"]}>
                {data.payments.map((p) => (
                  <tr key={p.id}>
                    <td className="whitespace-nowrap px-4 py-3 text-slate-500">{new Date(p.paidAt).toLocaleDateString("en-KE")}</td>
                    <td className="px-4 py-3"><Badge value={p.method} /></td>
                    <td className="px-4 py-3 font-mono text-xs text-slate-600">{p.reference}</td>
                    <td className="whitespace-nowrap px-4 py-3 font-medium text-emerald-700">{fmtKes2(p.amount)}</td>
                  </tr>
                ))}
              </TableShell>
            )}
          </section>
        </div>

        <aside className="space-y-4">
          <div className="rounded-2xl border border-emerald-200 bg-gradient-to-b from-emerald-50 to-white p-5">
            <h3 className="text-sm font-bold text-emerald-800">📱 Collect via M-Pesa</h3>
            <p className="mt-1 text-xs text-emerald-700/80">
              Send an STK push to the customer&apos;s phone — they simply enter their M-Pesa PIN.
            </p>
            <button
              onClick={() => { setModalErr(""); setStkMsg(""); setStkOpen(true); }}
              disabled={balance <= 0}
              className={`${btnPrimary} mt-4 w-full bg-emerald-600 hover:bg-emerald-700`}
            >
              {balance <= 0 ? "Fully paid ✓" : "Send STK push"}
            </button>
          </div>
          <div className="rounded-2xl border border-slate-200 bg-white p-5">
            <h3 className="text-sm font-bold text-slate-800">Record manual payment</h3>
            <p className="mt-1 text-xs text-slate-500">Bank transfer, cash or cheque received offline.</p>
            <button
              onClick={() => { setModalErr(""); setPayOpen(true); }}
              disabled={balance <= 0}
              className={`${btnGhost} mt-4 w-full`}
            >
              + Record payment
            </button>
          </div>
          {data.mpesa.length > 0 && (
            <div className="rounded-2xl border border-slate-200 bg-white p-5">
              <h3 className="mb-3 text-sm font-bold text-slate-800">M-Pesa requests</h3>
              <ul className="space-y-2">
                {data.mpesa.map((t) => (
                  <li key={t.id} className="flex items-center justify-between gap-2 text-xs">
                    <span className="truncate text-slate-500">{t.phone}{t.mpesaReceipt ? ` · ${t.mpesaReceipt}` : ""}</span>
                    <Badge value={t.status} />
                  </li>
                ))}
              </ul>
            </div>
          )}
        </aside>
      </div>

      <Modal open={stkOpen} onClose={() => { setStkOpen(false); if (pollRef.current) clearInterval(pollRef.current); setBusy(false); }} title="M-Pesa STK push">
        <form onSubmit={sendStk}>
          {modalErr && <div className="mb-4 rounded-lg bg-rose-50 px-3 py-2 text-sm text-rose-700">{modalErr}</div>}
          {stkMsg && (
            <div className="mb-4 flex items-center gap-2 rounded-lg bg-emerald-50 px-3 py-2 text-sm text-emerald-700">
              {busy && <Spinner className="h-4 w-4" />}
              {stkMsg}
            </div>
          )}
          <div className="space-y-4">
            <Field label="Customer phone (Safaricom) *">
              <input className={inputCls} required placeholder="0722123456" value={phone} onChange={(e) => setPhone(e.target.value)} />
            </Field>
            <Field label="Amount (KES) *">
              <input type="number" min={1} className={inputCls} required value={stkAmount} onChange={(e) => setStkAmount(Number(e.target.value))} />
            </Field>
          </div>
          <div className="mt-6 flex justify-end gap-2">
            <button type="button" onClick={() => setStkOpen(false)} className={btnGhost}>Close</button>
            <button type="submit" disabled={busy} className={`${btnPrimary} bg-emerald-600 hover:bg-emerald-700`}>
              {busy && <Spinner className="h-4 w-4 text-white" />}
              {busy ? "Waiting for PIN…" : "Send STK push"}
            </button>
          </div>
        </form>
      </Modal>

      <Modal open={payOpen} onClose={() => setPayOpen(false)} title="Record payment">
        <form onSubmit={recordPayment}>
          {modalErr && <div className="mb-4 rounded-lg bg-rose-50 px-3 py-2 text-sm text-rose-700">{modalErr}</div>}
          <div className="space-y-4">
            <Field label="Amount (KES) *">
              <input type="number" min={1} step="any" className={inputCls} required value={pay.amount} onChange={(e) => setPay({ ...pay, amount: Number(e.target.value) })} />
            </Field>
            <Field label="Method">
              <select className={inputCls} value={pay.method} onChange={(e) => setPay({ ...pay, method: e.target.value })}>
                <option value="bank">Bank transfer</option>
                <option value="cash">Cash</option>
                <option value="cheque">Cheque</option>
                <option value="mpesa">M-Pesa (manual)</option>
              </select>
            </Field>
            <Field label="Reference">
              <input className={inputCls} placeholder="Transaction reference" value={pay.reference} onChange={(e) => setPay({ ...pay, reference: e.target.value })} />
            </Field>
          </div>
          <div className="mt-6 flex justify-end gap-2">
            <button type="button" onClick={() => setPayOpen(false)} className={btnGhost}>Cancel</button>
            <button type="submit" disabled={busy} className={btnPrimary}>
              {busy && <Spinner className="h-4 w-4 text-white" />}
              {busy ? "Saving…" : "Record payment"}
            </button>
          </div>
        </form>
      </Modal>
    </div>
  );
}
