import React from 'react';
import { CashFlowPanelData } from '../../types/financial';
import { formatMoney } from '../ui/StatementTableMinimal';

interface CashFlowPanelProps {
  data: CashFlowPanelData;
  onRunCommand?: (command: string) => void;
}

type CashFlowRow = CashFlowPanelData['periods'][number];

interface SectionHeader {
  key: string;
  label: string;
  isSectionHeader: true;
}

interface MetricRow {
  key: string;
  label: string;
  indent?: boolean;
  isSectionHeader?: false;
  render: (period: CashFlowRow) => React.ReactNode;
}

type CashFlowMetric = SectionHeader | MetricRow;

const SourceAttribution: React.FC<{ status: CashFlowPanelData['sourceStatus'] }> = ({ status }) => {
  return (
    <div className="text-[11px] font-mono text-term-text-muted">
      SEC EDGAR • companyfacts
      {status.degradedReason && (
        <div className="mt-1 text-warning">{status.degradedReason}</div>
      )}
    </div>
  );
};

const metrics: CashFlowMetric[] = [
  { key: 'section-operating', label: 'Operating Activities', isSectionHeader: true },
  {
    key: 'netIncome',
    label: 'Net Income / Net Earnings',
    render: (period: CashFlowRow) => formatMoney(period.netIncome),
  },
  {
    key: 'depreciationAndAmortization',
    label: 'Depreciation & Amortization',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.depreciationAndAmortization),
  },
  {
    key: 'stockBasedCompensation',
    label: 'Stock-Based Compensation',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.stockBasedCompensation),
  },
  {
    key: 'deferredIncomeTaxes',
    label: 'Deferred Income Taxes',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.deferredIncomeTaxes),
  },
  {
    key: 'impairmentCharges',
    label: 'Impairment Charges',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.impairmentCharges),
  },
  {
    key: 'lossGainOnSaleOfAssets',
    label: 'Loss / Gain on Sale of Assets',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.lossGainOnSaleOfAssets),
  },
  {
    key: 'otherNonCashItems',
    label: 'Other Non-Cash Items',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.otherNonCashItems),
  },
  {
    key: 'accountsReceivable',
    label: 'Accounts Receivable',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.accountsReceivable),
  },
  {
    key: 'inventory',
    label: 'Inventory',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.inventory),
  },
  {
    key: 'prepaidExpensesAndOtherCurrentAssets',
    label: 'Prepaid Expenses and Other Current Assets',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.prepaidExpensesAndOtherCurrentAssets),
  },
  {
    key: 'accountsPayable',
    label: 'Accounts Payable',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.accountsPayable),
  },
  {
    key: 'accruedExpenses',
    label: 'Accrued Expenses',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.accruedExpenses),
  },
  {
    key: 'deferredRevenue',
    label: 'Deferred Revenue',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.deferredRevenue),
  },
  {
    key: 'otherWorkingCapitalChanges',
    label: 'Other Working Capital Changes',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.otherWorkingCapitalChanges),
  },
  {
    key: 'operatingCashFlow',
    label: 'Net Cash Provided by Operating Activities',
    render: (period: CashFlowRow) => formatMoney(period.operatingCashFlow),
  },
  { key: 'section-investing', label: 'Investing Activities', isSectionHeader: true },
  {
    key: 'capex',
    label: 'Capital Expenditures / Purchases of Property and Equipment',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.capex),
  },
  {
    key: 'proceedsFromSaleOfPpe',
    label: 'Proceeds from Sale of Property and Equipment',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.proceedsFromSaleOfPpe),
  },
  {
    key: 'acquisitions',
    label: 'Acquisitions, Net of Cash Acquired',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.acquisitions),
  },
  {
    key: 'purchasesOfInvestments',
    label: 'Purchases of Investments',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.purchasesOfInvestments),
  },
  {
    key: 'salesOfInvestments',
    label: 'Proceeds from Sale or Maturity of Investments',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.salesOfInvestments),
  },
  {
    key: 'otherInvestingActivities',
    label: 'Other Investing Activities',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.otherInvestingActivities),
  },
  {
    key: 'investingCashFlow',
    label: 'Net Cash Used in Investing Activities',
    render: (period: CashFlowRow) => formatMoney(period.investingCashFlow),
  },
  { key: 'section-financing', label: 'Financing Activities', isSectionHeader: true },
  {
    key: 'debtIssuance',
    label: 'Proceeds from Debt Issuance',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.debtIssuance),
  },
  {
    key: 'debtRepayment',
    label: 'Repayments of Debt',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.debtRepayment),
  },
  {
    key: 'equityIssuance',
    label: 'Proceeds from Equity Issuance',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.equityIssuance),
  },
  {
    key: 'stockRepurchases',
    label: 'Repurchases of Common Stock',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.stockRepurchases),
  },
  {
    key: 'dividendsPaid',
    label: 'Dividends Paid',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.dividendsPaid),
  },
  {
    key: 'financeLeaseObligations',
    label: 'Payment of Finance Lease Obligations',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.financeLeaseObligations),
  },
  {
    key: 'otherFinancingActivities',
    label: 'Other Financing Activities',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.otherFinancingActivities),
  },
  {
    key: 'financingCashFlow',
    label: 'Net Cash Provided by / Used in Financing Activities',
    render: (period: CashFlowRow) => formatMoney(period.financingCashFlow),
  },
  { key: 'section-summary', label: 'Supplemental / Other Cash Flow', isSectionHeader: true },
  {
    key: 'exchangeRateEffects',
    label: 'Effect of Exchange Rate Changes on Cash',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.exchangeRateEffects),
  },
  {
    key: 'netIncreaseDecreaseCash',
    label: 'Net Increase / Decrease in Cash and Cash Equivalents',
    render: (period: CashFlowRow) => formatMoney(period.netIncreaseDecreaseCash),
  },
  {
    key: 'beginningCash',
    label: 'Cash and Cash Equivalents at Beginning of Period',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.beginningCash),
  },
  {
    key: 'endingCash',
    label: 'Cash and Cash Equivalents at End of Period',
    render: (period: CashFlowRow) => formatMoney(period.endingCash),
  },
  {
    key: 'cashPaidInterest',
    label: 'Cash Paid for Interest',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.cashPaidInterest),
  },
  {
    key: 'cashPaidIncomeTaxes',
    label: 'Cash Paid for Income Taxes',
    indent: true,
    render: (period: CashFlowRow) => formatMoney(period.cashPaidIncomeTaxes),
  },
];

export const buildCashFlowCommand = (
  symbol: string,
  frequency: CashFlowPanelData['frequency'],
  options: {
    start?: string;
    end?: string;
  } = {},
) => {
  const parts = ['/cf', symbol, frequency];
  if (options.start && options.end) {
    parts.push(options.start, options.end);
  }
  return parts.join(' ');
};

export const CashFlowPanel: React.FC<CashFlowPanelProps> = ({ data, onRunCommand }) => {
  const [selectedStart, setSelectedStart] = React.useState(
    data.selectedPeriodStart ?? '',
  );
  const [selectedEnd, setSelectedEnd] = React.useState(
    data.selectedPeriodEnd ?? '',
  );

  const hasRangeControls =
    data.availablePeriods.length > 0 &&
    Boolean(data.selectedPeriodStart) &&
    Boolean(data.selectedPeriodEnd);

  React.useEffect(() => {
    setSelectedStart((current) =>
      current === (data.selectedPeriodStart ?? '')
        ? current
        : (data.selectedPeriodStart ?? ''),
    );
    setSelectedEnd((current) =>
      current === (data.selectedPeriodEnd ?? '')
        ? current
        : (data.selectedPeriodEnd ?? ''),
    );
  }, [data.selectedPeriodEnd, data.selectedPeriodStart]);

  const commitRange = React.useCallback(
    (start: string, end: string) => {
      if (!onRunCommand || !start || !end) {
        return;
      }

      if (
        start === (data.selectedPeriodStart ?? '') &&
        end === (data.selectedPeriodEnd ?? '')
      ) {
        return;
      }

      const nextCommand = buildCashFlowCommand(data.symbol, data.frequency, {
        start,
        end,
      });
      onRunCommand(nextCommand);
    },
    [
      data.frequency,
      data.selectedPeriodEnd,
      data.selectedPeriodStart,
      data.symbol,
      onRunCommand,
    ],
  );

  const handleStartChange = React.useCallback(
    (nextStart: string) => {
      const effectiveEnd = selectedEnd || nextStart;
      if (nextStart > effectiveEnd) {
        setSelectedStart(effectiveEnd);
        setSelectedEnd(nextStart);
        commitRange(effectiveEnd, nextStart);
      } else {
        setSelectedStart(nextStart);
        setSelectedEnd(effectiveEnd);
        commitRange(nextStart, effectiveEnd);
      }
    },
    [commitRange, selectedEnd],
  );

  const handleEndChange = React.useCallback(
    (nextEnd: string) => {
      const effectiveStart = selectedStart || nextEnd;
      if (effectiveStart > nextEnd) {
        setSelectedStart(nextEnd);
        setSelectedEnd(effectiveStart);
        commitRange(nextEnd, effectiveStart);
      } else {
        setSelectedStart(effectiveStart);
        setSelectedEnd(nextEnd);
        commitRange(effectiveStart, nextEnd);
      }
    },
    [commitRange, selectedStart],
  );

  return (
    <div className="cashflow-panel py-4 overflow-auto">
      <header className="mb-4">
        <div className="flex items-start justify-between">
          <div>
            <h2 className="text-heading-lg text-term-text">{data.symbol} Cash Flow</h2>
            <p className="mt-1 text-body-xs text-term-text-muted">
              {data.companyName} • {data.frequency}
            </p>
          </div>
          <div className="text-right text-body-xs">
            <div className="text-term-text-muted">CIK {data.cik}</div>
            {data.latestFiling && (
              <div className="mt-1 text-term-text-tertiary">
                {data.latestFiling.form} filed {data.latestFiling.filingDate}
              </div>
            )}
          </div>
        </div>
      </header>

      <section>
        {hasRangeControls && (
          <div className="mb-4 rounded-lg border border-term-border-subtle bg-term-bg-secondary/40 px-3 py-3">
            <div className="mb-3 text-[10px] font-mono uppercase tracking-[0.18em] text-term-text-muted">
              Reported Range
            </div>
            <div className="grid gap-3 md:grid-cols-2">
              <label className="block text-body-xs text-term-text-muted">
                <span className="mb-1 block font-mono uppercase tracking-[0.18em] text-[10px]">
                  Start Period
                </span>
                <select
                  aria-label="Start cash flow period"
                  className="w-full rounded-md border border-term-border-subtle bg-term-bg px-3 py-2 text-term-text"
                  onChange={(event) =>
                    handleStartChange(event.currentTarget.value)
                  }
                  value={selectedStart}
                >
                  {data.availablePeriods.map((period) => (
                    <option key={period.id} value={period.id}>
                      {period.label}
                    </option>
                  ))}
                </select>
              </label>
              <label className="block text-body-xs text-term-text-muted">
                <span className="mb-1 block font-mono uppercase tracking-[0.18em] text-[10px]">
                  End Period
                </span>
                <select
                  aria-label="End cash flow period"
                  className="w-full rounded-md border border-term-border-subtle bg-term-bg px-3 py-2 text-term-text"
                  onChange={(event) =>
                    handleEndChange(event.currentTarget.value)
                  }
                  value={selectedEnd}
                >
                  {data.availablePeriods.map((period) => (
                    <option key={period.id} value={period.id}>
                      {period.label}
                    </option>
                  ))}
                </select>
              </label>
            </div>
          </div>
        )}
        <div className="overflow-x-auto">
          <table className="min-w-full border-collapse font-mono text-sm">
            <thead className="text-term-text-muted">
              <tr className="border-b border-term-border-subtle">
                <th className="sticky left-0 border-r border-term-border-subtle bg-term-bg px-3 py-2 text-left text-[10px] uppercase tracking-[0.18em]">
                  Item
                </th>
                {data.periods.map((period) => (
                  <th
                    key={period.label}
                    className="border-b border-term-border-subtle px-3 py-2 text-right text-[10px] uppercase tracking-[0.18em]"
                  >
                    {period.label}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {metrics.map((metric) => {
                if (metric.isSectionHeader) {
                  return (
                    <tr key={metric.key} className="border-b border-term-border-subtle">
                      <th
                        colSpan={data.periods.length + 1}
                        className="bg-term-bg-secondary px-3 py-2 text-left text-[10px] uppercase tracking-[0.18em] font-semibold text-term-text-muted"
                      >
                        {metric.label}
                      </th>
                    </tr>
                  );
                }

                const labelClass = metric.indent
                  ? 'pl-6 font-normal text-term-text-muted'
                  : 'font-medium text-term-text';

                return (
                  <tr key={metric.key} className="border-b border-term-border-subtle last:border-b-0">
                    <th className={`sticky left-0 border-r border-term-border-subtle bg-term-bg px-3 py-2 text-left text-term-text ${labelClass}`}>
                      {metric.label}
                    </th>
                    {data.periods.map((period) => (
                      <td key={`${metric.key}-${period.label}`} className="px-3 py-2 text-right text-term-text">
                        <span className="inline-block">{metric.render(period)}</span>
                      </td>
                    ))}
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </section>

      <footer className="mt-4 border-t border-term-border-subtle pt-4">
        <SourceAttribution status={data.sourceStatus} />
      </footer>
    </div>
  );
};
