'use client';

import { useEffect, useState } from 'react';
import { useAuth } from '@/lib/auth-context';
import { adminApiFetch, adminApiOpenPdf } from '@/lib/api';
import { useToast } from '@/lib/toast';
import { TableSkeleton } from '@/components/Skeletons';
import Modal from '@/components/Modal';
import LineItemBuilder, { LineItem, ProductLookup, computeTotals, toProductsJson } from '@/components/LineItemBuilder';

type InvoiceRow = {
  id: number; invoiceNo: string; client: { name: string; poBox: string | null };
  quote: { id: number; quoteNo: string } | null; order: { id: number; orderNo: string } | null;
  totalTzs: string; vatTzs: string; status: string; paymentRef: string | null;
};
type ClientLookup = { id: number; name: string; company: string | null; phone: string };
type QuoteOption = { id: number; quoteNo: string; status: string; totalTzs: string; subtotalTzs: string; vatTzs: string; client: { id: number; name: string } };
type OrderOption = { id: number; orderNo: string; status: string; totalTzs: string; subtotalTzs: string; vatTzs: string; client: { id: number; name: string } };

type Mode = 'QUOTE' | 'ORDER' | 'MANUAL';

export default function InvoicesPage() {
  const { accessToken, appSecretProof, user } = useAuth();
  const { show } = useToast();
  const [invoices, setInvoices] = useState<InvoiceRow[]>([]);
  const [threshold, setThreshold] = useState(1_000_000);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const [showForm, setShowForm] = useState(false);
  const [mode, setMode] = useState<Mode>('QUOTE');
  const [quotes, setQuotes] = useState<QuoteOption[]>([]);
  const [orders, setOrders] = useState<OrderOption[]>([]);
  const [clients, setClients] = useState<ClientLookup[]>([]);
  const [products, setProducts] = useState<ProductLookup[]>([]);
  const [selectedQuoteId, setSelectedQuoteId] = useState('');
  const [selectedOrderId, setSelectedOrderId] = useState('');
  const [manualClientId, setManualClientId] = useState('');
  const [manualItems, setManualItems] = useState<LineItem[]>([]);
  const [dueDate, setDueDate] = useState('');
  const [saving, setSaving] = useState(false);

  async function load() {
    if (!accessToken || !appSecretProof) return;
    setLoading(true);
    try {
      const d = await adminApiFetch('/admin/invoices', accessToken, appSecretProof);
      setInvoices(d.invoices || []);
      setThreshold(d.directorApprovalThresholdTzs ?? 1_000_000);
    } catch { setError('You do not have permission to view this page.'); }
    finally { setLoading(false); }
  }
  useEffect(() => { load(); }, [accessToken, appSecretProof]); // eslint-disable-line react-hooks/exhaustive-deps

  // Quotes/orders that already have an invoice shouldn't be offered again —
  // the DB has a unique constraint on invoice.quoteId/orderId, so picking
  // an already-invoiced one would just fail; filtering here is a lot
  // friendlier than letting that surface as a raw error.
  const invoicedQuoteIds = new Set(invoices.map((i) => i.quote?.id).filter(Boolean));
  const invoicedOrderIds = new Set(invoices.map((i) => i.order?.id).filter(Boolean));

  async function openForm() {
    setShowForm(true);
    if (!accessToken || !appSecretProof) return;
    try {
      const [q, o, c, p] = await Promise.all([
        adminApiFetch('/admin/quotes', accessToken, appSecretProof),
        adminApiFetch('/admin/orders', accessToken, appSecretProof),
        adminApiFetch('/admin/billing/clients-lookup', accessToken, appSecretProof),
        adminApiFetch('/admin/billing/products-lookup', accessToken, appSecretProof),
      ]);
      setQuotes((q.quotes || []).filter((qt: QuoteOption) => qt.status === 'APPROVED'));
      setOrders((o.orders || []).filter((or: OrderOption) => or.status === 'DELIVERED'));
      setClients(c.clients || []);
      setProducts(p.products || []);
    } catch { show('error', 'Could not load quotes/orders/clients.'); }
  }

  async function submit(e: React.FormEvent) {
    e.preventDefault();
    if (!accessToken || !appSecretProof) return;
    setSaving(true);
    try {
      let body: Record<string, unknown>;
      if (mode === 'QUOTE') {
        const q = quotes.find((x) => x.id === Number(selectedQuoteId));
        if (!q) { show('error', 'Select a quote first.'); setSaving(false); return; }
        body = { clientId: q.client.id, quoteId: q.id, subtotalTzs: Number(q.subtotalTzs), vatTzs: Number(q.vatTzs), totalTzs: Number(q.totalTzs), dueDate: dueDate || undefined };
      } else if (mode === 'ORDER') {
        const o = orders.find((x) => x.id === Number(selectedOrderId));
        if (!o) { show('error', 'Select an order first.'); setSaving(false); return; }
        body = { clientId: o.client.id, orderId: o.id, subtotalTzs: Number(o.subtotalTzs), vatTzs: Number(o.vatTzs), totalTzs: Number(o.totalTzs), dueDate: dueDate || undefined };
      } else {
        if (!manualClientId || manualItems.length === 0) { show('error', 'Pick a client and at least one line item.'); setSaving(false); return; }
        const { subtotalTzs, vatTzs, totalTzs } = computeTotals(manualItems);
        body = { clientId: Number(manualClientId), subtotalTzs, vatTzs, totalTzs, dueDate: dueDate || undefined };
      }

      const d = await adminApiFetch('/admin/invoices', accessToken, appSecretProof, { method: 'POST', body: JSON.stringify(body) });
      show('success', `${d.invoice.invoiceNo} created${d.needsApproval ? ' — needs Director approval (over TZS 1M).' : '.'}`);
      setShowForm(false);
      setSelectedQuoteId(''); setSelectedOrderId(''); setManualClientId(''); setManualItems([]); setDueDate('');
      load();
    } catch { show('error', 'Could not create that invoice.'); }
    finally { setSaving(false); }
  }

  async function markPaid(id: number, invoiceNo: string) {
    if (!accessToken || !appSecretProof) return;
    try {
      await adminApiFetch(`/admin/invoices/${id}/payment`, accessToken, appSecretProof, { method: 'PATCH', body: JSON.stringify({ status: 'PAID' }) });
      setInvoices((i) => i.map((row) => row.id === id ? { ...row, status: 'PAID' } : row));
      show('success', `${invoiceNo} marked as paid.`);
    } catch { show('error', 'Could not update that invoice.'); }
  }

  async function remind(id: number, invoiceNo: string) {
    if (!accessToken || !appSecretProof) return;
    try {
      await adminApiFetch(`/admin/invoices/${id}/remind`, accessToken, appSecretProof, { method: 'POST' });
      show('info', `Reminder for ${invoiceNo} queued — wire the WhatsApp Cloud API call server-side to actually deliver it.`);
    } catch { show('error', 'Could not queue that reminder.'); }
  }

  async function approve(id: number, invoiceNo: string) {
    if (!accessToken || !appSecretProof) return;
    try {
      await adminApiFetch(`/admin/invoices/${id}/approve`, accessToken, appSecretProof, { method: 'POST' });
      show('success', `${invoiceNo} approved.`);
      load();
    } catch { show('error', 'Only the Director (SUPER_ADMIN) can approve invoices above the threshold.'); }
  }

  async function downloadPdf(id: number) {
    if (!accessToken || !appSecretProof) return;
    try { await adminApiOpenPdf(`/admin/invoices/${id}/pdf`, accessToken, appSecretProof); }
    catch { show('error', 'Could not open the invoice PDF.'); }
  }

  async function downloadReceipt(id: number) {
    if (!accessToken || !appSecretProof) return;
    try { await adminApiOpenPdf(`/admin/invoices/${id}/receipt.pdf`, accessToken, appSecretProof); }
    catch { show('error', 'Receipt is only available once the invoice is marked Paid.'); }
  }

  if (error) return <p className="text-sm text-brand-red">{error}</p>;

  return (
    <div className="space-y-4">
      <div className="flex justify-between items-center">
        <h1 className="text-xl font-bold">Invoices &bull; admin.lussavara.co.tz</h1>
        <button onClick={openForm} className="bg-brand-red text-white px-4 py-2 rounded-full text-sm transition-transform hover:scale-[1.03]">+ Create Invoice</button>
      </div>
      <p className="text-xs text-gray-500 -mt-3">Invoices over TZS {threshold.toLocaleString()} need Director approval</p>

      {loading ? <TableSkeleton rows={5} cols={6} /> : (
        <div className="bg-white rounded-xl border border-brand-border overflow-hidden">
          <table className="w-full text-xs">
            <thead className="bg-brand-bg"><tr>
              <th className="p-3 text-left">Invoice No</th><th className="p-3 text-left">Client</th>
              <th className="p-3 text-left">Source</th><th className="p-3 text-left">Total TZS</th>
              <th className="p-3 text-left">Status</th><th className="p-3 text-left">Actions</th>
            </tr></thead>
            <tbody>
              {invoices.map((inv) => (
                <tr key={inv.id} className="border-t border-brand-border transition-colors hover:bg-brand-bg">
                  <td className="p-3 font-mono font-bold">{inv.invoiceNo}</td>
                  <td className="p-3">{inv.client.name}<br /><span className="text-gray-400">{inv.client.poBox}</span></td>
                  <td className="p-3">{inv.quote?.quoteNo || inv.order?.orderNo || 'Manual'}</td>
                  <td className="p-3 font-bold">TZS {Number(inv.totalTzs).toLocaleString()}</td>
                  <td className="p-3">
                    <span className={`px-2 py-1 rounded-full text-[10px] ${
                      inv.status === 'PAID' ? 'bg-green-100 text-green-700' : inv.status === 'OVERDUE' ? 'bg-red-100 text-red-700' : 'bg-gray-100 text-gray-700'
                    }`}>{inv.status}</span>
                  </td>
                  <td className="p-3 space-x-1">
                    <button onClick={() => downloadPdf(inv.id)} className="border px-2 py-1 rounded text-[10px] transition-colors hover:bg-brand-bg">PDF</button>
                    {inv.status !== 'PAID' && <button onClick={() => markPaid(inv.id, inv.invoiceNo)} className="border px-2 py-1 rounded text-[10px] transition-colors hover:bg-brand-bg">Mark Paid</button>}
                    {inv.status === 'PAID' && <button onClick={() => downloadReceipt(inv.id)} className="border px-2 py-1 rounded text-[10px] transition-colors hover:bg-brand-bg">Receipt</button>}
                    {inv.status !== 'PAID' && <button onClick={() => remind(inv.id, inv.invoiceNo)} className="bg-red-500 text-white px-2 py-1 rounded text-[10px] transition-transform hover:scale-105">Remind WhatsApp</button>}
                    {Number(inv.totalTzs) > threshold && user?.role === 'SUPER_ADMIN' && (
                      <button onClick={() => approve(inv.id, inv.invoiceNo)} className="bg-brand-charcoal text-white px-2 py-1 rounded text-[10px] transition-transform hover:scale-105">Approve</button>
                    )}
                  </td>
                </tr>
              ))}
              {invoices.length === 0 && <tr><td colSpan={6} className="p-6 text-center text-gray-400">No invoices yet.</td></tr>}
            </tbody>
          </table>
        </div>
      )}

      {showForm && (
        <Modal title="Create Invoice" onClose={() => setShowForm(false)} wide>
          <div className="flex gap-1 mb-4">
            {(['QUOTE', 'ORDER', 'MANUAL'] as Mode[]).map((m) => (
              <button key={m} type="button" onClick={() => setMode(m)}
                className={`text-xs px-3 py-1.5 rounded-full transition-colors ${mode === m ? 'bg-brand-red text-white' : 'bg-brand-bg border border-brand-border'}`}>
                {m === 'QUOTE' ? 'From Quote' : m === 'ORDER' ? 'From Order' : 'Manual'}
              </button>
            ))}
          </div>

          <form onSubmit={submit} className="space-y-3">
            {mode === 'QUOTE' && (
              <select required value={selectedQuoteId} onChange={(e) => setSelectedQuoteId(e.target.value)}
                className="w-full border border-brand-border rounded-lg px-2 py-1.5 text-sm">
                <option value="">Select an approved quote…</option>
                {quotes.filter((q) => !invoicedQuoteIds.has(q.id)).map((q) => (
                  <option key={q.id} value={q.id}>{q.quoteNo} &bull; {q.client.name} &bull; TZS {Number(q.totalTzs).toLocaleString()}</option>
                ))}
              </select>
            )}

            {mode === 'ORDER' && (
              <select required value={selectedOrderId} onChange={(e) => setSelectedOrderId(e.target.value)}
                className="w-full border border-brand-border rounded-lg px-2 py-1.5 text-sm">
                <option value="">Select a delivered order…</option>
                {orders.filter((o) => !invoicedOrderIds.has(o.id)).map((o) => (
                  <option key={o.id} value={o.id}>{o.orderNo} &bull; {o.client.name} &bull; TZS {Number(o.totalTzs).toLocaleString()}</option>
                ))}
              </select>
            )}

            {mode === 'MANUAL' && (
              <>
                <select required value={manualClientId} onChange={(e) => setManualClientId(e.target.value)}
                  className="w-full border border-brand-border rounded-lg px-2 py-1.5 text-sm">
                  <option value="">Select client…</option>
                  {clients.map((c) => <option key={c.id} value={c.id}>{c.name} {c.company && `• ${c.company}`}</option>)}
                </select>
                <LineItemBuilder items={manualItems} onChange={setManualItems} products={products} />
              </>
            )}

            <div>
              <label className="text-xs font-medium text-gray-600">Due date (optional)</label>
              <input type="date" value={dueDate} onChange={(e) => setDueDate(e.target.value)}
                className="mt-1 w-full border border-brand-border rounded-lg px-2 py-1.5 text-sm" />
            </div>

            <button disabled={saving} className="w-full bg-brand-red text-white text-sm font-semibold py-2.5 rounded-lg disabled:opacity-60">
              {saving ? 'Creating…' : 'Create Invoice'}
            </button>
          </form>
        </Modal>
      )}
    </div>
  );
}
