import { createMemo, createResource, createSignal, onMount, Show, For } from 'solid-js';
import {
  api,
  AdminInvoiceSummary,
  AdminInvoiceDetail,
  InvoiceStatus,
  listAdminInvoices,
  getAdminInvoice,
  voidAdminInvoice,
  markAdminInvoicePaid,
  adminInvoiceHtmlUrl,
} from '~/lib/api';

type FilterStatus = 'all' | InvoiceStatus;

export default function InvoicePage() {
  const [invoices, { refetch }] = createResource<AdminInvoiceSummary[]>(
    () => listAdminInvoices().then((r) => r.data?.invoices ?? []),
  );
  const [search, setSearch] = createSignal('');
  const [statusFilter, setStatusFilter] = createSignal<FilterStatus>('all');
  const [sortBy, setSortBy] = createSignal<'newest' | 'oldest' | 'total_desc' | 'total_asc'>(
    'newest',
  );
  const [selectedInvoice, setSelectedInvoice] = createSignal<AdminInvoiceDetail | null>(null);
  const [detailLoading, setDetailLoading] = createSignal(false);
  const [voidModalInvoice, setVoidModalInvoice] = createSignal<AdminInvoiceSummary | null>(null);
  const [voidReason, setVoidReason] = createSignal('');
  const [actionError, setActionError] = createSignal('');
  const [actionBusy, setActionBusy] = createSignal('');

  const filteredInvoices = createMemo(() => {
    const data = invoices() ?? [];
    const q = search().toLowerCase().trim();
    let filtered = data;
    if (q) {
      filtered = filtered.filter(
        (inv) =>
          (inv.invoice_number ?? '').toLowerCase().includes(q) ||
          (inv.user_email ?? '').toLowerCase().includes(q) ||
          (inv.user_id ?? '').toLowerCase().includes(q) ||
          (inv.customer_name ?? '').toLowerCase().includes(q) ||
          (inv.status ?? '').toLowerCase().includes(q),
      );
    }
    if (statusFilter() !== 'all') {
      filtered = filtered.filter((inv) => inv.status === statusFilter());
    }
    const sorted = [...filtered];
    sorted.sort((a, b) => {
      const aDate = new Date(a.issued_at ?? 0).getTime();
      const bDate = new Date(b.issued_at ?? 0).getTime();
      const aTotal = Number(a.total ?? 0);
      const bTotal = Number(b.total ?? 0);
      if (sortBy() === 'oldest') return aDate - bDate;
      if (sortBy() === 'total_desc') return bTotal - aTotal;
      if (sortBy() === 'total_asc') return aTotal - bTotal;
      return bDate - aDate;
    });
    return sorted;
  });

  const exportCsv = () => {
    const headers = [
      'Invoice #',
      'User Email',
      'Customer',
      'Subtotal',
      'CGST',
      'SGST',
      'IGST',
      'Total',
      'Status',
      'Issued At',
    ];
    const rows = filteredInvoices().map((item) => [
      item.invoice_number ?? '',
      item.user_email ?? '',
      item.customer_name ?? '',
      paiseToRupees(item.subtotal),
      paiseToRupees(item.cgst_amount),
      paiseToRupees(item.sgst_amount),
      paiseToRupees(item.igst_amount),
      paiseToRupees(item.total),
      item.status ?? '',
      item.issued_at ?? '',
    ]);
    const csv = [headers, ...rows]
      .map((line) => line.map((cell) => `"${String(cell).replace(/"/g, '""')}"`).join(','))
      .join('\n');
    const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = 'invoice-management.csv';
    link.click();
    URL.revokeObjectURL(url);
  };

  const openDetail = async (inv: AdminInvoiceSummary) => {
    setDetailLoading(true);
    setActionError('');
    try {
      const res = await getAdminInvoice(inv.id);
      setSelectedInvoice(res.data);
    } catch (e: any) {
      setActionError(e?.message || 'Failed to load invoice.');
    } finally {
      setDetailLoading(false);
    }
  };

  const closeDetail = () => {
    setSelectedInvoice(null);
    setVoidModalInvoice(null);
    setVoidReason('');
    setActionError('');
  };

  const handleVoid = async () => {
    const inv = voidModalInvoice();
    if (!inv) return;
    const reason = voidReason().trim();
    if (!reason) {
      setActionError('Void reason is required.');
      return;
    }
    setActionBusy('void');
    setActionError('');
    try {
      await voidAdminInvoice(inv.id, reason);
      setVoidModalInvoice(null);
      setVoidReason('');
      await refetch();
      if (selectedInvoice()?.invoice.id === inv.id) {
        const res = await getAdminInvoice(inv.id);
        setSelectedInvoice(res.data);
      }
    } catch (e: any) {
      setActionError(e?.message || 'Failed to void invoice.');
    } finally {
      setActionBusy('');
    }
  };

  const handleMarkPaid = async (inv: AdminInvoiceSummary) => {
    setActionBusy(`paid:${inv.id}`);
    setActionError('');
    try {
      await markAdminInvoicePaid(inv.id);
      await refetch();
      if (selectedInvoice()?.invoice.id === inv.id) {
        const res = await getAdminInvoice(inv.id);
        setSelectedInvoice(res.data);
      }
    } catch (e: any) {
      setActionError(e?.message || 'Failed to mark invoice as paid.');
    } finally {
      setActionBusy('');
    }
  };

  return (
    <div class="w-full space-y-6 pb-8">
      <div style="margin-bottom:1.5rem">
        <h1 class="text-[28px] font-bold leading-tight text-[#111827]">Invoice Management</h1>
        <p class="mt-1 text-[14px] text-[#6B7280]">
          View, void, and mark invoices as paid. Invoices are auto-generated when a Tracecoin package is purchased.
        </p>
      </div>

      <Show when={actionError()}>
        <div class="rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
          {actionError()}
        </div>
      </Show>

      <section class="rounded-xl border border-gray-200 bg-white shadow-sm">
        <div style="display:flex;align-items:center;gap:8px;padding:14px 20px;border-bottom:1px solid #F3F4F6;flex-wrap:wrap">
          <input
            type="text"
            placeholder="Search by invoice #, email, customer, or status..."
            value={search()}
            onInput={(e) => setSearch(e.currentTarget.value)}
            style="height:34px;flex:1;min-width:240px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 12px;font-size:13px;color:#111827;outline:none"
          />
          <select
            value={statusFilter()}
            onChange={(e) => setStatusFilter(e.currentTarget.value as FilterStatus)}
            style="height:34px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 12px;font-size:12px;color:#374151"
          >
            <option value="all">All Statuses</option>
            <option value="ISSUED">Issued</option>
            <option value="PAID">Paid</option>
            <option value="VOID">Void</option>
            <option value="REFUNDED">Refunded</option>
            <option value="DRAFT">Draft</option>
          </select>
          <select
            value={sortBy()}
            onChange={(e) => setSortBy(e.currentTarget.value as any)}
            style="height:34px;border-radius:8px;border:1px solid #E5E7EB;background:white;padding:0 12px;font-size:12px;color:#374151"
          >
            <option value="newest">Newest First</option>
            <option value="oldest">Oldest First</option>
            <option value="total_desc">Total High-Low</option>
            <option value="total_asc">Total Low-High</option>
          </select>
          <button
            type="button"
            class="btn-primary"
            style="height:34px;padding:0 14px;font-size:12px"
            onClick={() => void refetch()}
          >
            Refresh
          </button>
          <button
            type="button"
            style="display:inline-flex;height:34px;align-items:center;gap:6px;border-radius:8px;background:#0D0D2A;padding:0 12px;font-size:12px;font-weight:600;color:white;border:none;cursor:pointer"
            onClick={exportCsv}
          >
            Export CSV
          </button>
        </div>

        <Show
          when={!invoices.loading}
          fallback={
            <p style="padding:32px;text-align:center;color:#64748b">Loading invoices...</p>
          }
        >
          <Show
            when={!invoices.error}
            fallback={
              <div class="m-4 rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
                Failed to load invoices: {String(invoices.error)}
              </div>
            }
          >
            <Show
              when={filteredInvoices().length > 0}
              fallback={
                <p style="padding:32px;text-align:center;color:#94a3b8">
                  No invoices found.
                </p>
              }
            >
              <div class="overflow-x-auto">
                <table class="data-table w-full text-sm">
                  <thead>
                    <tr>
                      <th>Invoice #</th>
                      <th>Customer</th>
                      <th>Subtotal (₹)</th>
                      <th>Total (₹)</th>
                      <th>Status</th>
                      <th>Issued</th>
                      <th class="text-right">Actions</th>
                    </tr>
                  </thead>
                  <tbody>
                    <For each={filteredInvoices()}>
                      {(item) => (
                        <tr class="hover:bg-slate-50">
                          <td class="font-semibold text-slate-900" style="font-family:monospace">
                            {item.invoice_number ?? '—'}
                          </td>
                          <td>
                            <div class="text-slate-900 font-medium">
                              {item.customer_name ?? '—'}
                            </div>
                            <Show when={item.user_email}>
                              <div class="text-xs text-slate-500">{item.user_email}</div>
                            </Show>
                          </td>
                          <td class="text-slate-700">₹{paiseToRupees(item.subtotal)}</td>
                          <td class="text-slate-900 font-semibold">₹{paiseToRupees(item.total)}</td>
                          <td>
                            <span
                              class={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${statusClass(item.status)}`}
                            >
                              {item.status ?? '—'}
                            </span>
                          </td>
                          <td class="text-slate-500 text-xs">
                            {item.issued_at
                              ? new Date(item.issued_at).toLocaleDateString('en-IN', {
                                  day: '2-digit',
                                  month: 'short',
                                  year: 'numeric',
                                })
                              : '—'}
                          </td>
                          <td>
                            <div class="flex items-center justify-end gap-1">
                              <button
                                type="button"
                                class="btn-secondary"
                                style="padding:6px 10px;font-size:12px"
                                onClick={() => openDetail(item)}
                              >
                                View
                              </button>
                              <a
                                class="btn-secondary"
                                style="padding:6px 10px;font-size:12px"
                                href={adminInvoiceHtmlUrl(item.id)}
                                target="_blank"
                                rel="noopener noreferrer"
                              >
                                HTML
                              </a>
                              <Show when={item.status === 'ISSUED'}>
                                <button
                                  type="button"
                                  class="btn-secondary"
                                  style="padding:6px 10px;font-size:12px;color:#15803d;border-color:#86efac"
                                  disabled={actionBusy() === `paid:${item.id}`}
                                  onClick={() => handleMarkPaid(item)}
                                >
                                  {actionBusy() === `paid:${item.id}` ? '...' : 'Mark Paid'}
                                </button>
                              </Show>
                              <Show when={item.status === 'ISSUED' || item.status === 'PAID'}>
                                <button
                                  type="button"
                                  class="btn-secondary"
                                  style="padding:6px 10px;font-size:12px;color:#b91c1c;border-color:#fca5a5"
                                  onClick={() => setVoidModalInvoice(item)}
                                >
                                  Void
                                </button>
                              </Show>
                            </div>
                          </td>
                        </tr>
                      )}
                    </For>
                  </tbody>
                </table>
              </div>
            </Show>
          </Show>
        </Show>
      </section>

      {/* Detail modal */}
      <Show when={detailLoading() || selectedInvoice()}>
        <div
          style="position:fixed;inset:0;background:rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;z-index:50;padding:24px;overflow-y:auto"
          onClick={(e) => {
            if (e.target === e.currentTarget) closeDetail();
          }}
        >
          <div
            class="bg-white rounded-2xl shadow-2xl"
            style="width:100%;max-width:920px;max-height:90vh;overflow-y:auto;padding:32px"
          >
            <Show when={detailLoading()}>
              <div class="text-center py-12">
                <p class="text-slate-500">Loading invoice...</p>
              </div>
            </Show>
            <Show when={selectedInvoice()}>
              <InvoiceDetailPanel detail={selectedInvoice()!} onClose={closeDetail} />
            </Show>
          </div>
        </div>
      </Show>

      {/* Void modal */}
      <Show when={voidModalInvoice()}>
        <div
          style="position:fixed;inset:0;background:rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;z-index:60;padding:24px"
          onClick={(e) => {
            if (e.target === e.currentTarget) setVoidModalInvoice(null);
          }}
        >
          <div class="bg-white rounded-2xl shadow-2xl" style="width:100%;max-width:480px;padding:24px">
            <h2 class="text-xl font-bold mb-2">Void Invoice</h2>
            <p class="text-sm text-slate-600 mb-4">
              Void <strong>{voidModalInvoice()?.invoice_number}</strong>? This cannot be undone.
              Tracecoins may need to be refunded separately.
            </p>
            <label class="block text-sm font-medium mb-1">Reason *</label>
            <textarea
              value={voidReason()}
              onInput={(e) => setVoidReason(e.currentTarget.value)}
              placeholder="e.g. Customer requested refund"
              rows={3}
              style="width:100%;padding:8px 12px;border:1px solid #e2e8f0;border-radius:8px;font-size:14px;box-sizing:border-box;resize:vertical"
            />
            <Show when={actionError()}>
              <div class="mt-3 rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700">
                {actionError()}
              </div>
            </Show>
            <div class="flex justify-end gap-2 mt-5">
              <button
                type="button"
                class="btn-secondary"
                onClick={() => {
                  setVoidModalInvoice(null);
                  setVoidReason('');
                  setActionError('');
                }}
              >
                Cancel
              </button>
              <button
                type="button"
                class="btn-primary"
                style="background:#b91c1c"
                disabled={actionBusy() === 'void'}
                onClick={handleVoid}
              >
                {actionBusy() === 'void' ? 'Voiding...' : 'Void Invoice'}
              </button>
            </div>
          </div>
        </div>
      </Show>
    </div>
  );
}

function InvoiceDetailPanel(props: { detail: AdminInvoiceDetail; onClose: () => void }) {
  const inv = () => props.detail.invoice;
  return (
    <div>
      <div class="flex justify-between items-start mb-4">
        <div>
          <h2 class="text-2xl font-bold">TAX INVOICE</h2>
          <p class="text-slate-500 font-mono text-sm mt-1">{inv().invoice_number}</p>
        </div>
        <button
          type="button"
          class="btn-secondary"
          onClick={props.onClose}
          style="padding:6px 12px"
        >
          Close
        </button>
      </div>

      <div class="flex flex-wrap gap-2 mb-4">
        <span class={`inline-flex items-center rounded-full px-3 py-1 text-xs font-semibold ${statusClass(inv().status)}`}>
          {inv().status}
        </span>
        <Show when={inv().paid_at}>
          <span class="inline-flex items-center rounded-full px-3 py-1 text-xs font-semibold bg-green-100 text-green-700">
            Paid on {new Date(inv().paid_at!).toLocaleDateString('en-IN')}
          </span>
        </Show>
        <Show when={inv().voided_at}>
          <span class="inline-flex items-center rounded-full px-3 py-1 text-xs font-semibold bg-red-100 text-red-700">
            Voided on {new Date(inv().voided_at!).toLocaleDateString('en-IN')}
          </span>
        </Show>
      </div>

      <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
        <div class="border rounded-lg p-4">
          <p class="text-xs uppercase text-slate-500 mb-2">From</p>
          <p class="font-semibold">{inv().seller_name}</p>
          <p class="text-sm whitespace-pre-line mt-1">{inv().seller_address}</p>
          <p class="text-xs mt-2">
            {inv().seller_gstin && <>GSTIN: {inv().seller_gstin}<br /></>}
            {inv().seller_pan && <>PAN: {inv().seller_pan}</>}
          </p>
        </div>
        <div class="border rounded-lg p-4">
          <p class="text-xs uppercase text-slate-500 mb-2">Bill To</p>
          <p class="font-semibold">{inv().customer_name ?? '—'}</p>
          <p class="text-sm whitespace-pre-line mt-1">{inv().customer_billing_address ?? '—'}</p>
          <p class="text-xs mt-2">
            {inv().customer_gstin && <>GSTIN: {inv().customer_gstin}<br /></>}
            {inv().place_of_supply_state && <>Place of Supply: {inv().place_of_supply_state}</>}
          </p>
        </div>
      </div>

      <table class="w-full text-sm mb-4">
        <thead>
          <tr class="text-left text-xs uppercase text-slate-500 border-b">
            <th class="py-2">#</th>
            <th class="py-2">Description</th>
            <th class="py-2">HSN/SAC</th>
            <th class="py-2 text-right">Qty</th>
            <th class="py-2 text-right">Rate</th>
            <th class="py-2 text-right">Amount</th>
          </tr>
        </thead>
        <tbody>
          <For each={props.detail.lines}>
            {(line) => (
              <tr class="border-b">
                <td class="py-2">{line.line_number}</td>
                <td class="py-2">{line.description}</td>
                <td class="py-2">{line.hsn_sac_code ?? '—'}</td>
                <td class="py-2 text-right">{line.quantity}</td>
                <td class="py-2 text-right">{paiseToRupees(line.unit_price_paise)}</td>
                <td class="py-2 text-right">
                  {paiseToRupees(Math.round(line.unit_price_paise * line.quantity))}
                </td>
              </tr>
            )}
          </For>
        </tbody>
      </table>

      <div class="border-t pt-4 space-y-2 text-sm">
        <div class="flex justify-between">
          <span class="text-slate-600">Subtotal</span>
          <span>₹{paiseToRupees(props.detail.totals.subtotal)}</span>
        </div>
        <Show when={props.detail.totals.discount > 0}>
          <div class="flex justify-between">
            <span class="text-slate-600">Discount</span>
            <span>-₹{paiseToRupees(props.detail.totals.discount)}</span>
          </div>
        </Show>
        <div class="flex justify-between">
          <span class="text-slate-600">Taxable value</span>
          <span>₹{paiseToRupees(props.detail.totals.taxable_value)}</span>
        </div>
        <Show when={props.detail.totals.cgst > 0}>
          <div class="flex justify-between">
            <span class="text-slate-600">CGST ({(inv().cgst_rate).toFixed(2)}%)</span>
            <span>₹{paiseToRupees(props.detail.totals.cgst)}</span>
          </div>
          <div class="flex justify-between">
            <span class="text-slate-600">SGST ({(inv().sgst_rate).toFixed(2)}%)</span>
            <span>₹{paiseToRupees(props.detail.totals.sgst)}</span>
          </div>
        </Show>
        <Show when={props.detail.totals.igst > 0}>
          <div class="flex justify-between">
            <span class="text-slate-600">IGST ({(inv().igst_rate).toFixed(2)}%)</span>
            <span>₹{paiseToRupees(props.detail.totals.igst)}</span>
          </div>
        </Show>
        <div class="flex justify-between text-lg font-bold pt-2 border-t">
          <span>Total ({inv().currency})</span>
          <span class="text-orange-600">₹{paiseToRupees(props.detail.totals.total)}</span>
        </div>
      </div>

      <Show when={inv().void_reason}>
        <div class="mt-4 p-3 bg-red-50 border border-red-200 rounded-lg text-sm">
          <p class="text-red-800 font-semibold">Void reason</p>
          <p class="text-red-700 mt-1">{inv().void_reason}</p>
        </div>
      </Show>

      <div class="mt-6 flex gap-2">
        <a
          class="btn-primary"
          href={adminInvoiceHtmlUrl(inv().id)}
          target="_blank"
          rel="noopener noreferrer"
        >
          Open Printable View
        </a>
        <button type="button" class="btn-secondary" onClick={() => window.print()}>
          Print
        </button>
      </div>
    </div>
  );
}

function statusClass(status: string | null | undefined): string {
  switch ((status ?? '').toUpperCase()) {
    case 'PAID':
      return 'bg-green-100 text-green-700';
    case 'ISSUED':
      return 'bg-blue-100 text-blue-700';
    case 'VOID':
      return 'bg-red-100 text-red-700';
    case 'REFUNDED':
      return 'bg-gray-100 text-gray-700';
    case 'DRAFT':
      return 'bg-amber-100 text-amber-700';
    default:
      return 'bg-gray-100 text-gray-600';
  }
}

function paiseToRupees(paise: number | null | undefined): string {
  if (paise == null) return '—';
  const rupees = (paise / 100).toLocaleString('en-IN', {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  });
  return rupees;
}