import { useEffect, useState, useMemo } from 'react';
import Layout from '../../components/Layout';
import StatusBadge from '../../components/StatusBadge';
import SortTh from '../../components/SortTh';
import LoadingButton from '../../components/LoadingButton';
import { supabase } from '../../lib/supabase';
import { useAuth } from '../../context/AuthContext';
import { readPageCache, writePageCache } from '../../lib/pageCache';
import { useSortable } from '../../hooks/useSortable';
import { isCompletedVersionEligible } from '../../lib/invoiceVersionRules';
import SubcontractorInvoiceForm from '../../components/SubcontractorInvoiceForm';
import { popupOverlayStyle, popupSurfaceStyle } from '../../lib/popupStyles';
import InvoiceDetailPopup, { POPUP_FIELD_LABEL } from '../../components/InvoiceDetailPopup';
import InvoicePopupTable from '../../components/InvoicePopupTable';
import { generateSubcontractorPOPDF } from '../../lib/invoice';

const STATUS_BADGE = { draft: 'not_started', submitted: 'in_progress', paid: 'client_approved' };
const STATUS_LABEL = { draft: 'Draft', submitted: 'Submitted', paid: 'Paid' };
const FIELD_LABEL_STYLE = { fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', textTransform: 'uppercase', letterSpacing: 0.8, display: 'block', marginBottom: 4 };

const STAT_ICONS = {
  newTasks: '<rect x="3" y="4" width="18" height="16" rx="2"/><line x1="7" y1="9" x2="17" y2="9"/><line x1="7" y1="13" x2="17" y2="13"/>',
  revisions: '<path d="M4 12a8 8 0 018-8v0a8 8 0 018 8"/><polyline points="18,8 20,12 16,12"/>',
  invoiced: '<path d="M5 3h11l3 3v15H5z"/><path d="M16 3v4h4"/><line x1="8" y1="11" x2="16" y2="11"/><line x1="8" y1="15" x2="16" y2="15"/>',
  paid: '<polyline points="4,12 9,17 20,6"/>',
};

function fmt(val) {
  return `$${Number(val || 0).toFixed(2)}`;
}

function invoiceTotal(items) {
  return (items || []).reduce((s, i) => s + Number(i.unit_price || 0) * Number(i.quantity || 1), 0);
}

function TaskStatCard({ label, value, sub, iconBg, iconColor, iconPath }) {
  return (
    <div style={{ background: 'var(--card-bg)', backdropFilter: 'blur(12px)', WebkitBackdropFilter: 'blur(12px)', border: 'var(--card-border)', borderRadius: 8, padding: '18px 21px', minHeight: 120 }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10 }}>
        <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase', marginBottom: 5 }}>{label}</div>
        <div style={{ width: 27, height: 27, borderRadius: '50%', background: iconBg, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
          <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke={iconColor} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" dangerouslySetInnerHTML={{ __html: iconPath }} />
        </div>
      </div>
      <div style={{ fontSize: 30, fontWeight: 400, color: 'var(--text-primary)', letterSpacing: -0.5, lineHeight: 1.1 }}>{value}</div>
      <div style={{ fontSize: 12, color: 'var(--text-secondary)', marginTop: 5 }}>{sub}</div>
    </div>
  );
}

function asArray(value) {
  if (Array.isArray(value)) return value;
  if (value == null) return [];
  return typeof value === 'object' ? [value] : [];
}

function parseItemVersionNumber(item) {
  if (item?.version_number != null && Number.isFinite(Number(item.version_number))) return Number(item.version_number);
  const match = String(item?.description || '').match(/\bR(\d{2})\b/i);
  return match ? Number(match[1]) : 0;
}

function itemVersionLabel(item) {
  return `R${String(parseItemVersionNumber(item)).padStart(2, '0')}`;
}

function itemWorkLabel(item) {
  return parseItemVersionNumber(item) > 0 ? 'Revision' : 'New';
}

function cleanItemDescription(item) {
  return String(item?.description || '—').replace(/\s*[–-]\s*R\d{2}\b/i, '').trim() || '—';
}

async function fetchTaskTypeMap(taskIds) {
  const uniqueTaskIds = [...new Set((taskIds || []).filter(Boolean))];
  if (uniqueTaskIds.length === 0) return {};
  const { data, error } = await supabase
    .from('tasks')
    .select('id, title, submissions(service_type, type)')
    .in('id', uniqueTaskIds);
  if (error) throw error;
  const next = {};
  for (const task of (data || [])) {
    const submissions = asArray(task.submissions);
    const initial = submissions.find((submission) => submission?.type === 'initial' && submission?.service_type);
    const fallback = submissions.find((submission) => submission?.service_type);
    next[task.id] = initial?.service_type || fallback?.service_type || task.title || 'Other';
  }
  return next;
}

function buildPDFArgs(invoice, profile, total, statusOverride) {
  return {
    po_number: invoice.invoice_number,
    status: statusOverride || invoice.status || 'draft',
    profile,
    project: { name: 'Subcontractor Invoice', company: { name: 'Fourge Branding' } },
    date: invoice.created_at?.split('T')[0],
    due_date: invoice.paid_at?.split('T')[0] || invoice.submitted_at?.split('T')[0] || invoice.created_at?.split('T')[0],
    amount: total,
    description: invoice.status === 'paid'
      ? 'Payment received for completed subcontractor work.'
      : 'Subcontractor invoice for completed work.',
    notes: invoice.notes,
    items: (invoice.items || []).map((item, idx) => ({
      description: item.description,
      amount: Number(item.unit_price || 0) * Number(item.quantity || 1),
      sort_order: item.sort_order ?? idx,
    })),
  };
}

export default function MyInvoices() {
  const { currentUser } = useAuth();
  const cacheKey = `ext-invoices:${currentUser?.id}`;
  const cached = readPageCache(cacheKey, 3 * 60_000);
  const [invoices, setInvoices] = useState(() => cached?.invoices || []);
  const [stats, setStats] = useState(() => cached?.stats || { completedNewTasks: 0, completedRevisions: 0, invoicedUnits: 0, paidUnits: 0 });
  const [loading, setLoading] = useState(() => !cached);
  const [error, setError] = useState('');
  const [showInvoiceForm, setShowInvoiceForm] = useState(false);
  const { sortKey, sortDir, toggle, sort } = useSortable('created_at', 'desc');
  const { sortKey: detailSortKey, sortDir: detailSortDir, toggle: toggleDetailSort, sort: sortDetailItems } = useSortable('description');
  const [viewingInvoice, setViewingInvoice] = useState(null);
  const [detailLoading, setDetailLoading] = useState(false);
  const [detailError, setDetailError] = useState('');
  const [detailTaskTypeMap, setDetailTaskTypeMap] = useState({});
  const [submittingInvoice, setSubmittingInvoice] = useState(false);
  const [downloadingInvoice, setDownloadingInvoice] = useState(false);
  const [downloadingReceipt, setDownloadingReceipt] = useState(false);

  useEffect(() => {
    async function load() {
      if (!currentUser?.id) {
        setInvoices([]);
        setStats({ completedNewTasks: 0, completedRevisions: 0, invoicedUnits: 0, paidUnits: 0 });
        setLoading(false);
        return;
      }

      setLoading(true);
      setError('');

      try {
        const [{ data: invoiceRows, error: invoiceError }, { data: taskRows, error: taskError }] = await Promise.all([
          supabase
            .from('subcontractor_invoices')
            .select('*, items:subcontractor_invoice_items(*)')
            .order('created_at', { ascending: false }),
          supabase
            .from('tasks')
            .select('id, title, status, current_version, assigned_to')
            .in('status', ['not_started', 'in_progress', 'on_hold', 'client_review', 'client_approved', 'invoiced', 'paid'])
            .eq('assigned_to', currentUser.id)
            .order('title'),
        ]);

        if (invoiceError) throw invoiceError;
        if (taskError) throw taskError;

        const tasks = taskRows || [];
        const invoicesData = invoiceRows || [];

        const taskIds = tasks.map((task) => task.id).filter(Boolean);
        const { data: submissionRows, error: submissionsError } = taskIds.length > 0
          ? await supabase
              .from('submissions')
              .select('task_id, deliveries(version_number, sent_by, sent_at)')
              .in('task_id', taskIds)
          : { data: [], error: null };
        if (submissionsError) throw submissionsError;

        const deliveriesByTask = new Map();
        for (const row of (submissionRows || [])) {
          const taskId = row.task_id;
          if (!taskId) continue;
          const bucket = deliveriesByTask.get(taskId) || new Map();
          for (const delivery of asArray(row.deliveries)) {
            if ((delivery.sent_by || '').trim().toLowerCase() !== (currentUser.name || '').trim().toLowerCase()) continue;
            const version = Number(delivery.version_number || 0);
            if (!bucket.has(version)) bucket.set(version, delivery);
          }
          deliveriesByTask.set(taskId, bucket);
        }

        let completedNewTasks = 0;
        let completedRevisions = 0;
        for (const task of tasks) {
          const versions = [...(deliveriesByTask.get(task.id)?.keys() || [])];
          for (const version of versions) {
            if (!isCompletedVersionEligible(task, version)) continue;
            if (version <= 0) completedNewTasks += 1;
            else completedRevisions += 1;
          }
        }

        const invoiceUnits = invoicesData.reduce((sum, invoice) => sum + asArray(invoice.items).filter((item) => item.task_id).length, 0);
        const paidUnits = invoicesData
          .filter((invoice) => invoice.status === 'paid')
          .reduce((sum, invoice) => sum + asArray(invoice.items).filter((item) => item.task_id).length, 0);

        const nextStats = {
          completedNewTasks,
          completedRevisions,
          invoicedUnits: invoiceUnits,
          paidUnits,
        };

        setInvoices(invoicesData);
        setStats(nextStats);
        writePageCache(cacheKey, { invoices: invoicesData, stats: nextStats });
      } catch (err) {
        console.error('Failed to load subcontractor invoices:', err);
        setError(err?.message || 'Failed to load invoices.');
      } finally {
        setLoading(false);
      }
    }

    load();
  }, [cacheKey, currentUser?.id, currentUser?.name]);

  const totalInvoiceAmount = useMemo(
    () => invoices.reduce((sum, invoice) => sum + invoiceTotal(invoice.items), 0),
    [invoices]
  );
  const paidInvoiceAmount = useMemo(
    () => invoices.filter((invoice) => invoice.status === 'paid').reduce((sum, invoice) => sum + invoiceTotal(invoice.items), 0),
    [invoices]
  );

  const sortedInvoices = sort(invoices, (inv, key) => {
    if (key === 'total') return invoiceTotal(inv.items);
    if (key === 'line_count') return asArray(inv.items).length;
    if (key === 'submitted_at') return inv.submitted_at ? new Date(inv.submitted_at).getTime() : 0;
    if (key === 'created_at') return inv.created_at ? new Date(inv.created_at).getTime() : 0;
    return inv[key] || '';
  });

  async function openInvoicePopup(invoiceId) {
    if (!invoiceId) return;
    setDetailLoading(true);
    setDetailError('');
    try {
      const { data, error: err } = await supabase
        .from('subcontractor_invoices')
        .select('*, items:subcontractor_invoice_items(*)')
        .eq('id', invoiceId)
        .single();
      if (err || !data) throw err || new Error('Invoice not found.');
      const taskTypeMap = await fetchTaskTypeMap(asArray(data.items).map((item) => item.task_id));
      setDetailTaskTypeMap(taskTypeMap);
      setViewingInvoice(data);
    } catch (err) {
      setDetailError(err?.message || 'Failed to load invoice.');
    } finally {
      setDetailLoading(false);
    }
  }

  async function handleSubmitInvoice() {
    if (!viewingInvoice?.id) return;
    setSubmittingInvoice(true);
    setDetailError('');
    try {
      const submittedAt = new Date().toISOString();
      const { error: err } = await supabase
        .from('subcontractor_invoices')
        .update({ status: 'submitted', submitted_at: submittedAt })
        .eq('id', viewingInvoice.id);
      if (err) throw err;
      setViewingInvoice((current) => current ? { ...current, status: 'submitted', submitted_at: submittedAt } : current);
      setInvoices((current) => current.map((invoice) => invoice.id === viewingInvoice.id ? { ...invoice, status: 'submitted', submitted_at: submittedAt } : invoice));
    } catch (err) {
      setDetailError(err?.message || 'Failed to submit invoice.');
    } finally {
      setSubmittingInvoice(false);
    }
  }

  async function handleDownloadReceipt() {
    if (!viewingInvoice) return;
    setDownloadingReceipt(true);
    setDetailError('');
    try {
      const total = invoiceTotal(viewingInvoice.items);
      await generateSubcontractorPOPDF(
        buildPDFArgs(viewingInvoice, { name: currentUser?.name, email: currentUser?.email }, total, 'paid')
      );
    } catch (err) {
      setDetailError(err?.message || 'Failed to download receipt.');
    } finally {
      setDownloadingReceipt(false);
    }
  }

  async function handleDownloadInvoice() {
    if (!viewingInvoice) return;
    setDownloadingInvoice(true);
    setDetailError('');
    try {
      const total = invoiceTotal(viewingInvoice.items);
      await generateSubcontractorPOPDF(
        buildPDFArgs(viewingInvoice, { name: currentUser?.name, email: currentUser?.email }, total)
      );
    } catch (err) {
      setDetailError(err?.message || 'Failed to download invoice.');
    } finally {
      setDownloadingInvoice(false);
    }
  }

  return (
    <Layout loading={loading}>
      <div style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column', overflow: 'hidden' }}>
        {error && <div className="notification notification-info" style={{ marginBottom: 16 }}>{error}</div>}

        <div className="dash-stat-grid" style={{ gridTemplateColumns: '1fr 1fr 1fr 1fr', flexShrink: 0 }}>
          <TaskStatCard
            label="Completed New Tasks"
            value={stats.completedNewTasks}
            sub={`${stats.completedNewTasks} completed R00 units`}
            iconBg="color-mix(in srgb, var(--info) 15%, transparent)"
            iconColor="var(--info)"
            iconPath={STAT_ICONS.newTasks}
          />
          <TaskStatCard
            label="Completed Revisions"
            value={stats.completedRevisions}
            sub={`${stats.completedRevisions} completed revision units`}
            iconBg="color-mix(in srgb, var(--accent) 15%, transparent)"
            iconColor="var(--accent)"
            iconPath={STAT_ICONS.revisions}
          />
          <TaskStatCard
            label="Invoiced"
            value={fmt(totalInvoiceAmount)}
            sub={`${invoices.length} invoices submitted`}
            iconBg="color-mix(in srgb, var(--violet) 15%, transparent)"
            iconColor="var(--violet)"
            iconPath={STAT_ICONS.invoiced}
          />
          <TaskStatCard
            label="Paid"
            value={fmt(paidInvoiceAmount)}
            sub={`${invoices.filter((invoice) => invoice.status === 'paid').length} paid invoices`}
            iconBg="color-mix(in srgb, var(--positive) 15%, transparent)"
            iconColor="var(--positive)"
            iconPath={STAT_ICONS.paid}
          />
        </div>

        {invoices.length === 0 ? (
          <>
            <div style={{ display: 'flex', alignItems: 'center', gap: 4, marginBottom: 10, flexShrink: 0, minHeight: 'var(--btn-height)' }}>
              <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 8 }}>
                <button className="btn btn-outline" onClick={() => setShowInvoiceForm(true)} disabled={loading}>
                  + Invoice
                </button>
              </div>
            </div>
            <div className="card card-empty-center" style={{ flex: 1, minHeight: 0 }}>No invoices</div>
          </>
        ) : (
          <>
            <div style={{ display: 'flex', alignItems: 'center', gap: 4, marginBottom: 10, flexShrink: 0, minHeight: 'var(--btn-height)' }}>
              <div style={{ marginLeft: 'auto', display: 'flex', alignItems: 'center', gap: 8 }}>
                <button className="btn btn-outline" onClick={() => setShowInvoiceForm(true)} disabled={loading}>
                  + Invoice
                </button>
              </div>
            </div>
            <div
              style={{
                background: 'var(--card-bg)',
                border: '1px solid var(--border)',
                borderRadius: 8,
                padding: '18px 21px',
                backdropFilter: 'blur(12px)',
                WebkitBackdropFilter: 'blur(12px)',
                display: 'flex',
                flexDirection: 'column',
                flex: 1,
                minHeight: 0,
              }}
            >
              <div className="scrollbar-thin-theme table-scroll-hidden" style={{ flex: 1, minHeight: 0, overflowY: 'auto' }}>
                <table className="table-sticky-head" style={{ tableLayout: 'fixed', borderCollapse: 'collapse', width: '100%' }}>
                  <colgroup>
                    <col style={{ width: '28%' }} />
                    <col style={{ width: '15%' }} />
                    <col style={{ width: '15%' }} />
                    <col style={{ width: '15%' }} />
                    <col style={{ width: '12%' }} />
                    <col style={{ width: '15%' }} />
                  </colgroup>
                  <thead>
                    <tr>
                      <SortTh col="invoice_number" sortKey={sortKey} sortDir={sortDir} onSort={toggle}>Invoice #</SortTh>
                      <SortTh col="created_at" sortKey={sortKey} sortDir={sortDir} onSort={toggle}>Created</SortTh>
                      <SortTh col="submitted_at" sortKey={sortKey} sortDir={sortDir} onSort={toggle}>Submitted</SortTh>
                      <SortTh col="status" sortKey={sortKey} sortDir={sortDir} onSort={toggle}>Status</SortTh>
                      <SortTh col="line_count" sortKey={sortKey} sortDir={sortDir} onSort={toggle} style={{ textAlign: 'center' }}>Items</SortTh>
                      <SortTh col="total" sortKey={sortKey} sortDir={sortDir} onSort={toggle} style={{ textAlign: 'right' }}>Total</SortTh>
                    </tr>
                  </thead>
                  <tbody>
                    {sortedInvoices.map((inv) => {
                      const total = invoiceTotal(inv.items);
                      return (
                        <tr key={inv.id} style={{ cursor: 'pointer' }} onClick={() => openInvoicePopup(inv.id)}>
                          <td style={{ fontWeight: 400 }}>{inv.invoice_number || 'Subcontractor Invoice'}</td>
                          <td style={{ color: 'var(--text-muted)' }}>{inv.created_at ? new Date(inv.created_at).toLocaleDateString() : '—'}</td>
                          <td style={{ color: 'var(--text-muted)' }}>{inv.submitted_at ? new Date(inv.submitted_at).toLocaleDateString() : '—'}</td>
                          <td><StatusBadge status={STATUS_BADGE[inv.status]} label={STATUS_LABEL[inv.status]} /></td>
                          <td style={{ textAlign: 'center', color: 'var(--text-primary)' }}>{asArray(inv.items).length}</td>
                          <td style={{ textAlign: 'right', fontWeight: 400, color: 'var(--accent)' }}>{fmt(total)}</td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
            </div>
          </>
        )}
      </div>

      {showInvoiceForm && (
        <div style={popupOverlayStyle}>
          <div
            style={{ ...popupSurfaceStyle, width: '80vw', height: '80vh', display: 'flex', flexDirection: 'column', gap: 0 }}
            onClick={(e) => e.stopPropagation()}
          >
            <SubcontractorInvoiceForm
              embedded
              onCancel={() => setShowInvoiceForm(false)}
              onSubmitted={(inv) => {
                setShowInvoiceForm(false);
                openInvoicePopup(inv.id);
              }}
            />
          </div>
        </div>
      )}

      {(viewingInvoice || detailLoading || detailError) && (() => {
        const inv = viewingInvoice;
        const total = inv ? invoiceTotal(inv.items) : 0;
        const baseItems = inv ? [...(inv.items || [])].sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0)) : [];
        const invoiceStatus = inv?.status ? inv.status.charAt(0).toUpperCase() + inv.status.slice(1) : '—';
        const busy = submittingInvoice || downloadingInvoice || downloadingReceipt;
        const tableItems = sortDetailItems(baseItems.map(item => ({
          ...item,
          _inferredType: { label: itemWorkLabel(item), badgeClass: itemWorkLabel(item) === 'New' ? 'badge-initial' : 'badge-client_revision' },
          description: cleanItemDescription(item),
        })), (item, key) => {
          if (key === 'type') return item._inferredType?.label || '';
          if (key === 'description') return item.description || '';
          if (key === 'quantity') return Number(item.quantity || 0);
          if (key === 'unit_price') return Number(item.unit_price || 0);
          if (key === 'line_total') return Number(item.unit_price || 0) * Number(item.quantity || 1);
          return '';
        });
        const F = POPUP_FIELD_LABEL;
        return (
          <InvoiceDetailPopup
            title={inv?.invoice_number || 'Subcontractor Invoice'}
            subtitle={`${currentUser?.name || 'Subcontractor'}${currentUser?.email ? ` · ${currentUser.email}` : ''}`}
            headerRight={inv ? <StatusBadge status={STATUS_BADGE[inv.status] || 'not_started'} label={invoiceStatus} /> : null}
            loading={detailLoading && !inv}
            metaContent={inv ? <>
              <div><div style={F}>Created</div><div style={{ fontSize: 13, color: 'var(--text-primary)' }}>{inv.created_at ? new Date(inv.created_at).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) : '—'}</div></div>
              <div><div style={F}>Submitted</div><div style={{ fontSize: 13, color: 'var(--text-primary)' }}>{inv.submitted_at ? new Date(inv.submitted_at).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' }) : '—'}</div></div>
              <div><div style={F}>Line Items</div><div style={{ fontSize: 13, color: 'var(--text-primary)' }}>{baseItems.length}</div></div>
              <div><div style={F}>Total</div><div style={{ fontSize: 18, fontWeight: 500, color: 'var(--accent)', lineHeight: 1.1 }}>${total.toFixed(2)}</div></div>
            </> : null}
            footerActions={inv ? (
              <>
                <LoadingButton className="btn btn-outline" loading={downloadingInvoice} loadingText="Generating…" disabled={busy} onClick={handleDownloadInvoice}>Download Invoice</LoadingButton>
                {inv.status === 'draft' && <LoadingButton className="btn btn-outline" loading={submittingInvoice} loadingText="Submitting…" disabled={busy} onClick={handleSubmitInvoice}>Submit to Team</LoadingButton>}
                {inv.status === 'paid' && <LoadingButton className="btn btn-outline" loading={downloadingReceipt} loadingText="Generating…" disabled={busy} onClick={handleDownloadReceipt}>Download Receipt</LoadingButton>}
                <button type="button" className="btn btn-outline" onClick={() => { setViewingInvoice(null); setDetailError(''); }} disabled={busy}>Close</button>
              </>
            ) : null}
          >
            {detailError && <div className="notification notification-info" style={{ marginBottom: 16 }}>{detailError}</div>}
            {inv
              ? <InvoicePopupTable sortKey={detailSortKey} sortDir={detailSortDir} onSort={toggleDetailSort} items={tableItems} notes={inv.notes} />
              : !detailError ? <div className="card-empty-center">Invoice not found.</div> : null
            }
          </InvoiceDetailPopup>
        );
      })()}
    </Layout>
  );
}
