/* Table screens: Invoices, Expenses, Payments, Employees */
(function () {
  const { money, fmtDate } = window.AC;

  function DataTable({ columns, rows, rowKey, empty, footer, maxHeight, getRowClassName, onRowClick, actions }) {
    const list = rows || [];
    const activeActions = actions && actions.length ? actions : null;
    const totalColumns = columns.length + (activeActions ? 1 : 0);
    const wrapStyle = maxHeight ? { maxHeight } : null;
    return (
      <div className="tbl-wrap" style={wrapStyle}>
        <table className="tbl">
          {columns.some((col) => col.header) && (
            <thead><tr>
              {columns.map((col) => <th key={col.key || col.header} className={col.headerClassName || col.className || ''} style={col.style}>{col.header}</th>)}
              {activeActions && <th style={{ width: 1 }}></th>}
            </tr></thead>
          )}
          <tbody>
            {list.map((row, index) => {
              const rowClass = getRowClassName ? getRowClassName(row, index) : '';
              const clickable = onRowClick ? 'clickable' : '';
              return (
                <tr key={rowKey ? rowKey(row, index) : index} className={[rowClass, clickable].filter(Boolean).join(' ')} onClick={onRowClick ? () => onRowClick(row, index) : undefined}>
                  {columns.map((col) => (
                    <td key={col.key || col.header} className={typeof col.className === 'function' ? col.className(row, index) : col.className || ''} style={typeof col.cellStyle === 'function' ? col.cellStyle(row, index) : col.cellStyle}>
                      {col.render ? col.render(row, index) : row[col.key]}
                    </td>
                  ))}
                  {activeActions && (
                    <td>
                      <div style={{ display: 'flex', gap: 4, justifyContent: 'flex-end' }}>
                        {activeActions.filter((action) => !action.show || action.show(row, index)).map((action) => (
                          <button
                            key={action.key || action.title || action.label}
                            className={action.className || (action.label ? 'btn sm ghost' : 'icon-btn')}
                            title={action.title}
                            onClick={(e) => { e.stopPropagation(); action.onClick(row, index); }}
                          >
                            {action.icon && <Icon name={action.icon} size={action.label ? 14 : 15} />}
                            {action.label}
                          </button>
                        ))}
                      </div>
                    </td>
                  )}
                </tr>
              );
            })}
            {list.length === 0 && <tr><td colSpan={totalColumns}><Empty>{empty || 'No records.'}</Empty></td></tr>}
          </tbody>
          {list.length > 0 && footer && <tfoot>{footer}</tfoot>}
        </table>
      </div>
    );
  }

  function StatusFilter({ value, onChange, options }) {
    return <Segmented value={value} onChange={onChange} options={options} />;
  }

  function Invoices({ db, query, onDrawer, onAction }) {
    const [status, setStatus] = React.useState('all');
    const rows = db.invoices.map((iv) => MODEL.enrich(db, iv))
      .filter((e) => {
        if (status === 'outstanding' && !e.open) return false;
        if (status === 'overdue' && !e.overdue) return false;
        if (status === 'draft' && e.invoice.status !== 'Draft') return false;
        if (status === 'paid' && e.invoice.status !== 'Paid') return false;
        if (query) {
          const q = query.toLowerCase();
          if (!(e.invoice.number.toLowerCase().includes(q) || (e.customer && e.customer.name.toLowerCase().includes(q)))) return false;
        }
        return true;
      })
      .sort((a, b) => b.invoice.issueDate.localeCompare(a.invoice.issueDate));

    const sum = rows.reduce((a, e) => ({ total: a.total + e.totals.total, paid: a.paid + e.totals.paid, out: a.out + e.totals.outstanding }), { total: 0, paid: 0, out: 0 });

    return (
      <div>
        <Toolbar>
          <StatusFilter value={status} onChange={setStatus} options={[
            { value: 'all', label: 'All' }, { value: 'outstanding', label: 'Outstanding' }, { value: 'overdue', label: 'Overdue' }, { value: 'draft', label: 'Draft' }, { value: 'paid', label: 'Paid' },
          ]} />
          <span className="muted" style={{ fontSize: 12 }}>{rows.length} invoices</span>
          <div style={{ marginLeft: 'auto' }}>
            <button className="btn" onClick={() => onDrawer('invoice')}><Icon name="plus" size={14} />New invoice</button>
          </div>
        </Toolbar>
        <Panel flush>
          <DataTable
            rows={rows}
            rowKey={(e) => e.invoice.id}
            empty="No invoices match this filter."
            columns={[
              { header: 'Invoice', render: (e) => <div className="cellstack"><span className="t-strong mono">{e.invoice.number}</span><span className="t-sub">{e.invoice.lines[0] ? e.invoice.lines[0].description : ''}</span></div> },
              { header: 'Customer', render: (e) => e.customer ? e.customer.name : '—' },
              { header: 'Issue', className: 'mono muted', cellStyle: { fontSize: 11.5 }, render: (e) => fmtDate(e.invoice.issueDate) },
              { header: 'Due', className: 'mono muted', cellStyle: { fontSize: 11.5 }, render: (e) => <React.Fragment>{fmtDate(e.invoice.dueDate)}{e.overdue && <span className="neg" style={{ fontSize: 10, marginLeft: 4 }}>+{e.overdueDays}d</span>}</React.Fragment> },
              { header: 'Status', render: (e) => <Pill kind={e.display} sm /> },
              { header: 'Total', className: 'num', render: (e) => money(e.totals.total) },
              { header: 'Paid', className: 'num muted', render: (e) => e.totals.paid ? money(e.totals.paid) : '—' },
              { header: 'Outstanding', className: 'num t-strong', cellStyle: (e) => e.totals.outstanding > 0 ? { color: e.overdue ? 'var(--neg)' : 'var(--ink)' } : { color: 'var(--faint)' }, render: (e) => e.totals.outstanding > 0 ? money(e.totals.outstanding) : '—' },
            ]}
            actions={[
              { key: 'finalize', label: 'Finalize', show: (e) => e.invoice.status === 'Draft', onClick: (e) => onAction('finalize', e.invoice) },
              { key: 'pay', label: 'Mark paid', show: (e) => e.open, onClick: (e) => onAction('pay', e.invoice) },
              { key: 'edit', title: 'Edit', icon: 'edit', show: (e) => e.invoice.status === 'Draft', onClick: (e) => onDrawer('invoice', e.invoice.id) },
              { key: 'delete', title: 'Delete invoice', icon: 'trash', show: (e) => e.invoice.status === 'Draft', onClick: (e) => onAction('delete', e.invoice) },
              { key: 'open', title: 'Open invoice', icon: 'external', onClick: (e) => onAction('print', e.invoice) },
            ]}
            footer={<tr><td colSpan={5}>{rows.length} invoices</td><td className="num">{money(sum.total)}</td><td className="num pos">{money(sum.paid)}</td><td className="num">{money(sum.out)}</td><td></td></tr>}
          />
        </Panel>
      </div>
    );
  }

  function Expenses({ db, query, onDrawer, onAction }) {
    const [cat, setCat] = React.useState('all');
    let list = db.expenses.slice().sort((a, b) => b.date.localeCompare(a.date));
    if (cat === 'recurring') list = list.filter((x) => x.recurrenceFrequency && x.recurrenceFrequency !== 'None');
    if (cat === 'wages') list = list.filter((x) => x.isWage);
    if (cat === 'oneoff') list = list.filter((x) => !x.recurrenceFrequency || x.recurrenceFrequency === 'None');
    if (query) { const q = query.toLowerCase(); list = list.filter((x) => x.category.toLowerCase().includes(q) || x.vendor.toLowerCase().includes(q) || x.description.toLowerCase().includes(q)); }
    const sum = list.reduce((a, x) => ({ net: a.net + x.amount, tax: a.tax + x.taxAmount }), { net: 0, tax: 0 });

    return (
      <div>
        <Toolbar>
          <StatusFilter value={cat} onChange={setCat} options={[
            { value: 'all', label: 'All' }, { value: 'recurring', label: 'Recurring' }, { value: 'wages', label: 'Wages' }, { value: 'oneoff', label: 'One-off' },
          ]} />
          <span className="muted" style={{ fontSize: 12 }}>{list.length} entries</span>
          <div style={{ marginLeft: 'auto' }}>
            <button className="btn" onClick={() => onDrawer('expense')}><Icon name="plus" size={14} />Record expense</button>
          </div>
        </Toolbar>
        <Panel flush>
          <DataTable
            rows={list}
            rowKey={(x) => x.id}
            empty="No expenses match this filter."
            columns={[
              { header: 'Date', className: 'mono muted', cellStyle: { fontSize: 11.5 }, render: (x) => fmtDate(x.date) },
              { header: 'Category', render: (x) => <React.Fragment><span className="t-strong">{x.category}</span>{x.isWage && <span className="pill partial sm" style={{ marginLeft: 6 }}><span className="dot" />Wage</span>}</React.Fragment> },
              { header: 'Vendor', key: 'vendor' },
              { header: 'Description', className: 'muted', cellStyle: { maxWidth: 280, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }, key: 'description' },
              { header: 'Recurrence', render: (x) => x.recurrenceFrequency && x.recurrenceFrequency !== 'None' ? <span className="chip"><Icon name="refresh" size={11} />{x.recurrenceFrequency}</span> : <span className="faint">One-off</span> },
              { header: 'Net', className: 'num', render: (x) => money(x.amount) },
              { header: 'Tax', className: 'num muted', render: (x) => x.taxAmount ? money(x.taxAmount) : '—' },
              { header: 'Total', className: 'num t-strong', render: (x) => money(x.amount + x.taxAmount) },
            ]}
            actions={[
              { key: 'doc', title: 'Document attached', icon: 'doc', show: (x) => !!x.document, onClick: (x) => onAction('doc', x) },
              { key: 'edit', title: 'Edit', icon: 'edit', onClick: (x) => onDrawer('expense', x.id) },
              { key: 'delete', title: 'Delete expense', icon: 'trash', show: (x) => !(x.payments || []).length, onClick: (x) => onAction('deleteExpense', x) },
            ]}
            footer={<tr><td colSpan={5}>{list.length} entries</td><td className="num">{money(sum.net)}</td><td className="num muted">{money(sum.tax)}</td><td className="num">{money(sum.net + sum.tax)}</td><td></td></tr>}
          />
        </Panel>
      </div>
    );
  }

  function Payments({ db, query, onDrawer, onAction }) {
    const [status, setStatus] = React.useState('open');
    let rows = MODEL.expensePaymentRows(db);
    if (status === 'open') rows = rows.filter((row) => !row.paid);
    if (status === 'paid') rows = rows.filter((row) => row.paid);
    if (query) {
      const q = query.toLowerCase();
      rows = rows.filter((row) => row.expense.category.toLowerCase().includes(q) || row.expense.vendor.toLowerCase().includes(q) || row.expense.description.toLowerCase().includes(q));
    }

    const due = rows.filter((row) => !row.paid).reduce((sum, row) => sum + row.amount, 0);
    const paid = rows.filter((row) => row.paid).reduce((sum, row) => sum + row.amount, 0);

    return (
      <div>
        <Toolbar>
          <StatusFilter value={status} onChange={setStatus} options={[
            { value: 'open', label: 'Open' }, { value: 'paid', label: 'Paid' }, { value: 'all', label: 'All' },
          ]} />
          <span className="muted" style={{ fontSize: 12 }}>{rows.length} payments</span>
        </Toolbar>
        <Panel flush>
          <DataTable
            rows={rows}
            rowKey={(row) => `${row.expense.id}-${row.occurrenceDate}`}
            empty="No payable expense items match this filter."
            columns={[
              { header: 'Due', className: 'mono muted', cellStyle: { fontSize: 11.5 }, render: (row) => fmtDate(row.occurrenceDate) },
              { header: 'Expense', render: (row) => <div className="cellstack"><span className="t-strong">{row.expense.category}</span><span className="t-sub">{row.expense.description}</span></div> },
              { header: 'Vendor', render: (row) => row.expense.vendor || '—' },
              { header: 'Recurrence', render: (row) => row.expense.recurrenceFrequency && row.expense.recurrenceFrequency !== 'None' ? <span className="chip"><Icon name="refresh" size={11} />{row.expense.recurrenceFrequency}</span> : <span className="faint">One-off</span> },
              { header: 'Status', render: (row) => row.paid ? <Pill kind="Paid" sm /> : <Pill kind="Open" sm /> },
              { header: 'Paid on', className: 'mono muted', cellStyle: { fontSize: 11.5 }, render: (row) => row.payment ? fmtDate(row.payment.paidOn) : '—' },
              { header: 'Amount', className: 'num t-strong', render: (row) => money(row.amount) },
            ]}
            actions={[
              { key: 'pay', label: 'Mark paid', show: (row) => !row.paid, onClick: (row) => onAction('payExpenseOccurrence', row) },
              { key: 'edit', title: 'Edit expense', icon: 'edit', onClick: (row) => onDrawer('expense', row.expense.id) },
            ]}
            footer={<tr><td colSpan={6}>Open {money(due)} · Paid {money(paid)}</td><td className="num">{money(due + paid)}</td><td></td></tr>}
          />
        </Panel>
      </div>
    );
  }

  function Employees({ db, query, onDrawer }) {
    let list = db.employees.slice();
    if (query) { const q = query.toLowerCase(); list = list.filter((e) => e.name.toLowerCase().includes(q) || (e.role || '').toLowerCase().includes(q)); }
    const wageRows = MODEL.expensePaymentRows(db).filter((row) => row.expense.isWage && row.expense.employeeId);
    const currentWageExpense = (employee) => {
      const period = MODEL.currentWagePeriod(employee);
      return period ? db.expenses.find((expense) => expense.isWage && expense.employeeId === employee.id && expense.wagePeriodId === period.id) : null;
    };
    const wageSummary = (employee) => {
      const rows = wageRows.filter((row) => row.expense.employeeId === employee.id);
      return {
        open: rows.filter((row) => !row.paid).reduce((sum, row) => sum + row.amount, 0),
        paid: rows.filter((row) => row.paid).reduce((sum, row) => sum + row.amount, 0),
        count: db.expenses.filter((expense) => expense.isWage && expense.employeeId === employee.id).length,
      };
    };
    const totalMonthly = list.filter((e) => e.active).reduce((s, e) => s + MODEL.employeeMonthlyWage(e), 0);

    return (
      <div>
        <Toolbar>
          <span className="muted" style={{ fontSize: 12 }}>{list.filter((e) => e.active).length} active · {list.length} total</span>
          <div style={{ marginLeft: 'auto' }}>
            <button className="btn" onClick={() => onDrawer('employee')}><Icon name="plus" size={14} />Add employee</button>
          </div>
        </Toolbar>
        <Panel flush>
          <DataTable
            rows={list}
            rowKey={(e) => e.id}
            columns={[
              { header: 'Name', render: (e) => <div style={{ display: 'flex', alignItems: 'center', gap: 9 }}><Avatar name={e.name} /><span className="t-strong">{e.name}</span></div> },
              { header: 'Role', key: 'role' },
              { header: 'Email', className: 'muted', key: 'email' },
              { header: 'Status', render: (e) => <Pill kind={e.active ? 'Active' : 'Inactive'} sm /> },
              { header: 'Wage', className: 'num', render: (e) => money(e.wageAmount) },
              { header: 'Frequency', className: 'muted', key: 'wageFrequency' },
              { header: 'Monthly cost', className: 'num', render: (e) => e.active ? money(MODEL.employeeMonthlyWage(e)) : <span className="faint">—</span> },
              { header: 'Wage payments', render: (e) => {
                const summary = wageSummary(e);
                return summary.count ? <div className="cellstack"><span className="t-strong">{money(summary.paid)} paid</span><span className="t-sub">{summary.open ? `${money(summary.open)} open` : 'No open payments'}</span></div> : <span className="faint">No linked payments</span>;
              } },
            ]}
            actions={[
              { key: 'wageExpense', title: 'Open current wage expense', icon: 'wallet', onClick: (e) => {
                const expense = currentWageExpense(e);
                const period = MODEL.currentWagePeriod(e);
                expense ? onDrawer('expense', expense.id) : onDrawer('expense', null, { employeeId: e.id, wagePeriodId: period && period.id });
              } },
              { key: 'edit', title: 'Edit', icon: 'edit', onClick: (e) => onDrawer('employee', e.id) },
            ]}
            footer={<tr><td colSpan={6}>Active monthly payroll</td><td className="num">{money(totalMonthly)}</td><td></td><td></td></tr>}
          />
        </Panel>
      </div>
    );
  }

  Object.assign(window, { DataTable, Invoices, Expenses, Payments, Employees });
})();
