import { useEffect, useMemo, useState } from 'react';
import jsPDF from 'jspdf';
import autoTable from 'jspdf-autotable';
import Layout from '../../components/Layout';
import SortTh from '../../components/SortTh';
import StatusBadge from '../../components/StatusBadge';
import LoadingButton from '../../components/LoadingButton';
import { useSortable } from '../../hooks/useSortable';
import { supabase } from '../../lib/supabase';
import { isReviewShadowDescription } from '../../lib/taskVersions';
import { parseVersionFromItemDescription } from '../../lib/invoiceVersionRules';

function fmtVersion(versionNumber) {
  return `R${String(Number(versionNumber || 0)).padStart(2, '0')}`;
}

function billingStatusFromInvoices(items = []) {
  // Only a sent or paid invoice counts as billed. Draft invoices and orphaned
  // line items (invoice deleted → invoice null) are treated as Not Invoiced,
  // matching what the Finances page actually shows as issued.
  const issued = items.filter((item) => item.invoice?.status === 'sent' || item.invoice?.status === 'paid');
  if (!issued.length) return 'not_started';
  if (issued.some((item) => item.invoice?.status === 'paid')) return 'paid';
  return 'invoiced';
}

// Sub billing: did the subcontractor invoice us for this version, and did we pay them?
function subBillingStatusFromInvoices(items = []) {
  if (!items.length) return 'not_started';
  if (items.some((item) => item.invoice_status === 'paid')) return 'paid';
  return 'invoiced';
}

function billingLabel(status) {
  if (status === 'paid') return 'Paid';
  if (status === 'invoiced') return 'Invoiced';
  return 'Not Invoiced';
}

function versionTypeLabel(versionNumber) {
  return Number(versionNumber || 0) === 0 ? 'New' : 'Revision';
}

function versionStateFor(task, versionNumber) {
  const currentVersion = Number(task?.current_version || 0);
  const version = Number(versionNumber || 0);
  if (version < currentVersion) return 'completed';
  const status = task?.status || 'not_started';
  // Approved work = done. client_approved (and legacy invoiced/paid billing leak)
  // all collapse to Completed. Billing is shown separately in the Billing columns.
  if (status === 'client_approved' || status === 'invoiced' || status === 'paid') return 'completed';
  return status;
}

function rowSort(a, b) {
  const companyCmp = (a.company_name || '').localeCompare(b.company_name || '');
  if (companyCmp !== 0) return companyCmp;
  const projectCmp = (a.project_name || '').localeCompare(b.project_name || '');
  if (projectCmp !== 0) return projectCmp;
  const taskCmp = (a.task_title || '').localeCompare(b.task_title || '');
  if (taskCmp !== 0) return taskCmp;
  return Number(a.version_number || 0) - Number(b.version_number || 0);
}

export default function TeamReports() {
  const [loading, setLoading] = useState(true);
  const [exporting, setExporting] = useState(false);
  const [error, setError] = useState('');
  const [companies, setCompanies] = useState([]);
  const [projects, setProjects] = useState([]);
  const [reportRows, setReportRows] = useState([]);
  const [companyFilter, setCompanyFilter] = useState('all');
  const [projectFilter, setProjectFilter] = useState('all');
  const { sortKey, sortDir, toggle, sort } = useSortable('company_name');

  useEffect(() => {
    let cancelled = false;

    async function load() {
      setLoading(true);
      setError('');
      try {
        const [
          { data: taskRows, error: tasksError },
          { data: submissionRows, error: submissionsError },
          { data: invoiceItemRows, error: invoiceItemsError },
          { data: subInvoiceRows, error: subInvoicesError },
        ] = await Promise.all([
          supabase
            .from('tasks')
            .select('id, title, status, current_version, project:projects(id, name, company:companies(id, name))')
            .order('title'),
          supabase
            .from('submissions')
            .select('id, task_id, type, version_number, submitted_at, invoiced, description')
            .in('type', ['initial', 'revision'])
            .order('submitted_at', { ascending: true }),
          supabase
            .from('invoice_items')
            .select('id, task_id, submission_id, invoice:invoices(id, status), submission:submissions(id, task_id, version_number)'),
          supabase
            .from('subcontractor_invoices')
            .select('status, items:subcontractor_invoice_items(task_id, version_number, description)')
            .in('status', ['submitted', 'approved', 'paid'])
        ]);

        if (tasksError) throw tasksError;
        if (submissionsError) throw submissionsError;
        if (invoiceItemsError) throw invoiceItemsError;
        if (subInvoicesError) throw subInvoicesError;
        if (cancelled) return;

        const taskMap = new Map((taskRows || []).map((task) => [task.id, task]));
        const companiesMap = new Map();
        const projectsMap = new Map();
        (taskRows || []).forEach((task) => {
          const company = task.project?.company;
          if (company?.id && !companiesMap.has(company.id)) companiesMap.set(company.id, company);
          if (task.project?.id && !projectsMap.has(task.project.id)) projectsMap.set(task.project.id, task.project);
        });

        const versionMap = new Map();
        for (const submission of (submissionRows || [])) {
          if (isReviewShadowDescription(submission.description)) continue;
          const versionNumber = Number(submission.version_number || 0);
          const key = `${submission.task_id}:${versionNumber}`;
          if (!versionMap.has(key)) {
            versionMap.set(key, {
              task_id: submission.task_id,
              version_number: versionNumber,
              submission_ids: [],
              first_submitted_at: submission.submitted_at || null,
            });
          }
          const entry = versionMap.get(key);
          entry.submission_ids.push(submission.id);
          if (!entry.first_submitted_at || (submission.submitted_at && submission.submitted_at < entry.first_submitted_at)) {
            entry.first_submitted_at = submission.submitted_at;
          }
        }

        const invoiceItemGroups = new Map();
        for (const item of (invoiceItemRows || [])) {
          const versionNumber = item.submission?.version_number ?? (item.submission_id ? null : 0);
          const taskId = item.submission?.task_id || item.task_id;
          if (!taskId || versionNumber === null) continue;
          const key = `${taskId}:${Number(versionNumber || 0)}`;
          if (!invoiceItemGroups.has(key)) invoiceItemGroups.set(key, []);
          invoiceItemGroups.get(key).push(item);
        }

        const subBillingGroups = new Map();
        for (const subInvoice of (subInvoiceRows || [])) {
          const status = subInvoice.status;
          for (const item of (subInvoice.items || [])) {
            if (!item.task_id) continue;
            // Stored version preferred; legacy rows (null) fall back to description parsing
            const version = item.version_number != null ? Number(item.version_number) : parseVersionFromItemDescription(item.description);
            const key = `${item.task_id}:${version}`;
            if (!subBillingGroups.has(key)) subBillingGroups.set(key, []);
            subBillingGroups.get(key).push({ invoice_status: status });
          }
        }

        const rows = [];
        for (const task of (taskRows || [])) {
          const company = task.project?.company;
          const project = task.project;
          const taskVersions = [];

          const initialKey = `${task.id}:0`;
          if (versionMap.has(initialKey) || task) {
            taskVersions.push(versionMap.get(initialKey) || {
              task_id: task.id,
              version_number: 0,
              submission_ids: [],
              first_submitted_at: null,
            });
          }

          for (const versionEntry of versionMap.values()) {
            if (versionEntry.task_id !== task.id) continue;
            if (Number(versionEntry.version_number || 0) === 0) continue;
            taskVersions.push(versionEntry);
          }

          taskVersions.sort((a, b) => Number(a.version_number || 0) - Number(b.version_number || 0));

          for (const versionEntry of taskVersions) {
            const key = `${task.id}:${Number(versionEntry.version_number || 0)}`;
            const invoiceItems = invoiceItemGroups.get(key) || [];
            const billingStatus = billingStatusFromInvoices(invoiceItems);
            const subBillingStatus = subBillingStatusFromInvoices(subBillingGroups.get(key) || []);
            rows.push({
              key,
              company_id: company?.id || '',
              company_name: company?.name || '—',
              project_id: project?.id || '',
              project_name: project?.name || '—',
              task_id: task.id,
              task_title: task.title || 'Untitled',
              version_number: Number(versionEntry.version_number || 0),
              version_label: fmtVersion(versionEntry.version_number),
              version_type: versionTypeLabel(versionEntry.version_number),
              version_state: versionStateFor(task, versionEntry.version_number),
              billing_status: billingStatus,
              billing_label: billingLabel(billingStatus),
              sub_billing_status: subBillingStatus,
              sub_billing_label: billingLabel(subBillingStatus),
              first_submitted_at: versionEntry.first_submitted_at,
            });
          }
        }

        rows.sort(rowSort);

        setCompanies([...companiesMap.values()].sort((a, b) => (a.name || '').localeCompare(b.name || '')));
        setProjects([...projectsMap.values()].sort((a, b) => (a.name || '').localeCompare(b.name || '')));
        setReportRows(rows);
      } catch (err) {
        if (!cancelled) setError(err.message || 'Failed to load reports.');
      } finally {
        if (!cancelled) setLoading(false);
      }
    }

    load();
    return () => { cancelled = true; };
  }, []);

  const filteredProjects = useMemo(() => {
    if (companyFilter === 'all') return projects;
    return projects.filter((project) => project.company?.id === companyFilter);
  }, [projects, companyFilter]);

  const visibleRows = useMemo(() => {
    return reportRows.filter((row) => {
      if (companyFilter !== 'all' && row.company_id !== companyFilter) return false;
      if (projectFilter !== 'all' && row.project_id !== projectFilter) return false;
      return true;
    });
  }, [reportRows, companyFilter, projectFilter]);

  const sortedRows = useMemo(() => sort(visibleRows, (row, key) => {
    if (key === 'company_name') return row.company_name || '';
    if (key === 'project_name') return row.project_name || '';
    if (key === 'task_title') return row.task_title || '';
    if (key === 'version_number') return Number(row.version_number || 0);
    if (key === 'version_type') return row.version_type || '';
    if (key === 'version_state') return row.version_state || '';
    if (key === 'billing_label') return row.billing_label || '';
    if (key === 'sub_billing_label') return row.sub_billing_label || '';
    return '';
  }), [visibleRows, sort]);

  const stats = useMemo(() => ({
    total: visibleRows.length,
    notInvoiced: visibleRows.filter((row) => row.billing_status === 'not_started').length,
    invoiced: visibleRows.filter((row) => row.billing_status === 'invoiced').length,
    paid: visibleRows.filter((row) => row.billing_status === 'paid').length,
  }), [visibleRows]);

  const handleExportPdf = async () => {
    setExporting(true);
    try {
      const doc = new jsPDF({ orientation: 'landscape', unit: 'pt', format: 'letter', compress: true });
      const title = 'Task Billing Report';
      const companyName = companyFilter === 'all' ? 'All Companies' : (companies.find((company) => company.id === companyFilter)?.name || 'Selected Company');
      const projectName = projectFilter === 'all' ? 'All Projects' : (projects.find((project) => project.id === projectFilter)?.name || 'Selected Project');
      const generatedOn = new Date().toLocaleString('en-US', { dateStyle: 'medium', timeStyle: 'short' });

      doc.setFontSize(18);
      doc.text(title, 40, 40);
      doc.setFontSize(10);
      doc.text(`Company: ${companyName}`, 40, 60);
      doc.text(`Project: ${projectName}`, 240, 60);
      doc.text(`Generated: ${generatedOn}`, 440, 60);

      autoTable(doc, {
        startY: 78,
        head: [['Company', 'Project', 'Task', 'Version', 'Type', 'Version Status', 'Client Billing', 'Sub Billing']],
        body: sortedRows.map((row) => [
          row.company_name,
          row.project_name,
          row.task_title,
          row.version_label,
          row.version_type,
          row.version_state === 'client_review' ? 'In Review' : row.version_state === 'completed' ? 'Completed' : row.version_state.replace(/_/g, ' '),
          row.billing_label,
          row.sub_billing_label,
        ]),
        styles: {
          fontSize: 9,
          cellPadding: 6,
          lineColor: [225, 225, 225],
          lineWidth: 0.25,
        },
        headStyles: {
          fillColor: [245, 165, 35],
          textColor: [17, 17, 17],
          fontStyle: 'bold',
        },
        alternateRowStyles: {
          fillColor: [250, 250, 250],
        },
        margin: { left: 40, right: 40, bottom: 30 },
        didDrawPage: ({ pageNumber }) => {
          doc.setFontSize(9);
          doc.text(`Page ${pageNumber}`, doc.internal.pageSize.width - 70, doc.internal.pageSize.height - 14);
        },
      });

      doc.save(`task-billing-report-${new Date().toISOString().slice(0, 10)}.pdf`);
    } finally {
      setExporting(false);
    }
  };

  return (
    <Layout loading={loading}>
      <div className="page-toolbar-grid" style={{ alignItems: 'center', marginBottom: 24 }}>
        <div>
          <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase', marginBottom: 4 }}>Company</div>
          <select value={companyFilter} onChange={(event) => { setCompanyFilter(event.target.value); setProjectFilter('all'); }}>
            <option value="all">All Companies</option>
            {companies.map((company) => (
              <option key={company.id} value={company.id}>{company.name}</option>
            ))}
          </select>
        </div>
        <div>
          <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase', marginBottom: 4 }}>Project</div>
          <select value={projectFilter} onChange={(event) => setProjectFilter(event.target.value)}>
            <option value="all">All Projects</option>
            {filteredProjects.map((project) => (
              <option key={project.id} value={project.id}>{project.name}</option>
            ))}
          </select>
        </div>
        <div style={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'end' }}>
          <LoadingButton className="btn btn-primary" loading={exporting} loadingText="Generating..." onClick={handleExportPdf} disabled={loading || sortedRows.length === 0}>
            Export PDF
          </LoadingButton>
        </div>
      </div>

      <div className="dash-stat-grid" style={{ gridTemplateColumns: '1fr 1fr 1fr 1fr', marginBottom: 24 }}>
        <div className="stat-card">
          <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase', marginBottom: 6 }}>Rows</div>
          <div style={{ fontSize: 28, lineHeight: 1.1 }}>{stats.total}</div>
        </div>
        <div className="stat-card">
          <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase', marginBottom: 6 }}>Not Invoiced</div>
          <div style={{ fontSize: 28, lineHeight: 1.1 }}>{stats.notInvoiced}</div>
        </div>
        <div className="stat-card">
          <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase', marginBottom: 6 }}>Invoiced</div>
          <div style={{ fontSize: 28, lineHeight: 1.1 }}>{stats.invoiced}</div>
        </div>
        <div className="stat-card">
          <div style={{ fontSize: 11, fontWeight: 500, color: 'var(--text-secondary)', letterSpacing: 0.8, textTransform: 'uppercase', marginBottom: 6 }}>Paid</div>
          <div style={{ fontSize: 28, lineHeight: 1.1 }}>{stats.paid}</div>
        </div>
      </div>

      <div className="table-wrapper" style={{ minHeight: 0 }}>
        {loading ? (
          <div style={{ padding: 24, fontSize: 13, color: 'var(--text-muted)', textAlign: 'center' }}>Loading report…</div>
        ) : error ? (
          <div style={{ padding: 24, fontSize: 13, color: 'var(--danger)', textAlign: 'center' }}>{error}</div>
        ) : sortedRows.length === 0 ? (
          <div style={{ padding: 24, fontSize: 13, color: 'var(--text-muted)', textAlign: 'center' }}>No report rows for the selected filters.</div>
        ) : (
          <table className="table-sticky-head" style={{ width: '100%', borderCollapse: 'collapse', tableLayout: 'fixed' }}>
            <colgroup>
              <col style={{ width: '15%' }} />
              <col style={{ width: '15%' }} />
              <col style={{ width: '20%' }} />
              <col style={{ width: '7%' }} />
              <col style={{ width: '9%' }} />
              <col style={{ width: '12%' }} />
              <col style={{ width: '11%' }} />
              <col style={{ width: '11%' }} />
            </colgroup>
            <thead>
              <tr>
                <SortTh col="company_name" sortKey={sortKey} sortDir={sortDir} onSort={toggle}>Company</SortTh>
                <SortTh col="project_name" sortKey={sortKey} sortDir={sortDir} onSort={toggle}>Project</SortTh>
                <SortTh col="task_title" sortKey={sortKey} sortDir={sortDir} onSort={toggle}>Task Name</SortTh>
                <SortTh col="version_number" sortKey={sortKey} sortDir={sortDir} onSort={toggle}>R#</SortTh>
                <SortTh col="version_type" sortKey={sortKey} sortDir={sortDir} onSort={toggle}>Type</SortTh>
                <SortTh col="version_state" sortKey={sortKey} sortDir={sortDir} onSort={toggle}>Version Status</SortTh>
                <SortTh col="billing_label" sortKey={sortKey} sortDir={sortDir} onSort={toggle}>Client Billing</SortTh>
                <SortTh col="sub_billing_label" sortKey={sortKey} sortDir={sortDir} onSort={toggle}>Sub Billing</SortTh>
              </tr>
            </thead>
            <tbody>
              {sortedRows.map((row) => (
                <tr key={row.key}>
                  <td>{row.company_name}</td>
                  <td>{row.project_name}</td>
                  <td>{row.task_title}</td>
                  <td>{row.version_label}</td>
                  <td><StatusBadge status={row.version_number === 0 ? 'initial' : 'revision'} label={row.version_type} /></td>
                  <td><StatusBadge status={row.version_state} /></td>
                  <td><StatusBadge status={row.billing_status} label={row.billing_label} /></td>
                  <td><StatusBadge status={row.sub_billing_status} label={row.sub_billing_label} /></td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>
    </Layout>
  );
}
