import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { ArrowDown, ArrowUp, ArrowUpDown } from 'lucide-react';
import { OperationActions } from '../../../common/OperationActions';
import type { LeaseBusinessDetailRow } from '../types';
import {
  DEFAULT_DETAIL_COLUMN_WIDTHS,
  DETAIL_TABLE_COLUMNS,
  DETAIL_TABLE_MIN_WIDTH,
  type DetailTableColumn,
} from './tableColumns';
import type { LeaseDetailKpiSummary } from '../types';
import {
  detailRowYearMonth,
  displayDeposit,
  displayMoney,
  displayOutstanding,
  displayText,
  formatMoney,
} from '../utils/detail';
import { resolveColumnHeaderTip } from '../columnHeaderTips';
import { HeaderWithTip } from './TableHeaderTip';
import { getFieldCheck, normalizeDeductionForDisplay } from '../utils/field-checks';
import { wrapFieldCell } from './FieldCheckIcon';
import { getVehicleRef, resolvePaymentMethodLabel } from '../utils/system-ref';
import { getHydrogenRefuelRecords } from '../utils/hydrogen-fee';
import {
  DETAIL_PAYMENT_STATUS_CLASS,
  paymentStatusSortValue,
  resolveDetailPaymentStatus,
} from '../utils/payment-status';
import { canEditDetailRow } from '../utils/change-log';
import {
  LedgerDetailPopover,
  LedgerDetailTable,
} from '../../lease-business-ledger/components/LedgerDetailPopover';

interface DetailTableProps {
  records: LeaseBusinessDetailRow[];
  summary: LeaseDetailKpiSummary;
  loading?: boolean;
  isSupervisor: boolean;
  onEdit: (row: LeaseBusinessDetailRow) => void;
  onDelete: (row: LeaseBusinessDetailRow) => void;
  onChangeLog: (row: LeaseBusinessDetailRow) => void;
  onRowPatch?: (id: string, patch: Partial<LeaseBusinessDetailRow>) => void;
}

type SortDir = 'asc' | 'desc';

const ACTION_COL_WIDTH = 168;

const STICKY_LEFT_KEYS = ['paymentStatus', 'yearMonth', 'plateNo'] as const;

function buildStickyLayout(widths: Record<string, number>) {
  let left = 0;
  const offsets: Record<string, number> = {};
  STICKY_LEFT_KEYS.forEach((key) => {
    offsets[key] = left;
    left += widths[key] ?? DEFAULT_DETAIL_COLUMN_WIDTHS[key] ?? 100;
  });
  return { offsets, totalWidth: left };
}

function stickyClass(col: DetailTableColumn): string {
  if (col.sticky !== 'left') return col.className ?? '';
  const classes = ['sticky-col-left'];
  if (col.key === 'plateNo') classes.push('sticky-col-left-last');
  if (col.className) classes.push(col.className);
  return classes.join(' ');
}

function stickyStyle(
  col: DetailTableColumn,
  layout: ReturnType<typeof buildStickyLayout>,
  isHeader: boolean,
): React.CSSProperties | undefined {
  if (col.sticky !== 'left') return undefined;
  const index = STICKY_LEFT_KEYS.indexOf(col.key as typeof STICKY_LEFT_KEYS[number]);
  if (index < 0) return undefined;
  return {
    left: layout.offsets[col.key],
    zIndex: (isHeader ? 4 : 3) + index,
  };
}

function getSortValue(row: LeaseBusinessDetailRow, key: string): string | number {
  if (key === 'paymentStatus') {
    return paymentStatusSortValue(row.receivableTotal, row.receivedAmount);
  }
  if (key === 'yearMonth') return row.year * 100 + row.month;
  return row[key as keyof LeaseBusinessDetailRow] as string | number;
}

function renderCellContent(
  row: LeaseBusinessDetailRow,
  col: DetailTableColumn,
): React.ReactNode {
  switch (col.render) {
    case 'payment-status': {
      const label = resolveDetailPaymentStatus(row.receivableTotal, row.receivedAmount);
      const statusClass = DETAIL_PAYMENT_STATUS_CLASS[label];
      return <span className={`ldb-status-tag ${statusClass}`}>{label}</span>;
    }
    case 'year-month':
      return <span className="tabular-nums">{detailRowYearMonth(row)}</span>;
    case 'stack-dept':
      return (
        <div className="ldb-cell-stack">
          <span className="ldb-cell-primary">{displayText(row.businessDept)}</span>
          <span className="ldb-cell-secondary">{displayText(row.salesperson)}</span>
        </div>
      );
    case 'vehicle-type': {
      const vehicle = getVehicleRef(row.plateNo);
      const label = vehicle?.brandModel || row.vehicleType;
      return <span title={label}>{displayText(label)}</span>;
    }
    case 'payment-method':
      return displayText(resolvePaymentMethodLabel(row));
    case 'hydrogen-fee': {
      const amount = row.hydrogenFee;
      const text = displayMoney(amount, true);
      if (!text) return '';
      const records = getHydrogenRefuelRecords(row);
      const tableRows = records.map((item) => ({
        hydrogenTime: item.hydrogenTime,
        stationName: item.stationName,
        customerName: item.customerName,
        plateNo: item.plateNo,
        hydrogenKg: String(item.hydrogenKg),
        unitPrice: formatMoney(item.unitPrice),
        totalPrice: formatMoney(item.totalPrice),
      }));
      return (
        <LedgerDetailPopover
          label={text}
          title="车辆氢费明细"
          triggerClassName="tabular-nums"
        >
          <LedgerDetailTable
            columns={[
              { key: 'hydrogenTime', title: '加氢时间' },
              { key: 'stationName', title: '加氢站名称' },
              { key: 'customerName', title: '客户名称' },
              { key: 'plateNo', title: '车牌号码' },
              { key: 'hydrogenKg', title: '加氢量' },
              { key: 'unitPrice', title: '加氢单价（元/kg）' },
              { key: 'totalPrice', title: '加氢总价（元）', align: 'right' },
            ]}
            rows={tableRows}
          />
        </LedgerDetailPopover>
      );
    }
    default:
      break;
  }

  if (col.key === 'outstanding') {
    const { text, warn } = displayOutstanding(row.outstanding);
    if (!text) return '';
    return warn
      ? <span className="lbd-outstanding-warn tabular-nums">{text}</span>
      : <span className="tabular-nums">{text}</span>;
  }
  if (col.key === 'deposit') {
    return <span className="tabular-nums">{displayDeposit(row.deposit)}</span>;
  }
  if (col.key === 'profitLoss') {
    const text = displayMoney(row.profitLoss, false);
    if (!text) return '';
    const cls = row.profitLoss >= 0 ? 'lbd-profit-pos' : 'lbd-profit-neg';
    return <span className={`tabular-nums ${cls}`}>{text}</span>;
  }
  if (col.key === 'customerName') {
    return <span className="lbd-cell-customer" title={row.customerName}>{displayText(row.customerName)}</span>;
  }
  if (col.key === 'mileageDeduction' || col.key === 'otherDeduction') {
    const normalized = normalizeDeductionForDisplay(row[col.key]);
    if (normalized === 0) return '';
    return <span className="tabular-nums">{displayMoney(normalized, false)}</span>;
  }
  if (col.key === 'otherDeductionDetail' || col.key === 'remark') {
    const text = displayText(row[col.key]);
    return text ? <span className="lbd-cell-remark" title={text}>{text}</span> : '';
  }
  const raw = row[col.key as keyof LeaseBusinessDetailRow];
  if (col.money && typeof raw === 'number') return displayMoney(raw);
  if (col.key === 'avgDays') {
    return raw === 0 ? '' : Number(raw).toFixed(2);
  }
  return displayText(raw);
}

function renderCell(
  row: LeaseBusinessDetailRow,
  col: DetailTableColumn,
  onRowPatch?: (id: string, patch: Partial<LeaseBusinessDetailRow>) => void,
) {
  const content = renderCellContent(row, col);
  if (!col.checkField) return content;

  const check = getFieldCheck(row, col.checkField);
  return wrapFieldCell(
    content,
    check,
    check.replaceAction && onRowPatch
      ? () => onRowPatch(row.id, check.replaceAction!)
      : undefined,
  );
}

function renderSummaryCell(col: DetailTableColumn, summary: LeaseDetailKpiSummary) {
  if (col.key === 'yearMonth') {
    return <span className="lbd-summary-label">汇总</span>;
  }
  if (!col.summaryKey) return '';

  const value = summary[col.summaryKey];
  if (col.summaryKey === 'outstanding') {
    const { text, warn } = displayOutstanding(value);
    return warn
      ? <span className="lbd-outstanding-warn tabular-nums">{text}</span>
      : <span className="tabular-nums">{text}</span>;
  }
  if (col.summaryKey === 'profitLoss') {
    const text = formatMoney(value);
    const cls = value >= 0 ? 'lbd-profit-pos' : 'lbd-profit-neg';
    return <span className={`tabular-nums ${cls}`}>{text}</span>;
  }
  if (col.summaryKey === 'mileageDeduction' || col.summaryKey === 'otherDeduction') {
    const normalized = normalizeDeductionForDisplay(value);
    return normalized === 0 ? '' : displayMoney(normalized, false);
  }
  return displayMoney(value, false);
}

function TableSkeleton() {
  return (
    <div className="ldb-table-skeleton" aria-busy="true" aria-label="表格加载中">
      {Array.from({ length: 6 }, (_, i) => (
        <div key={i} className="ldb-skeleton-row" />
      ))}
    </div>
  );
}

export function DetailTable({
  records,
  summary,
  loading = false,
  isSupervisor,
  onEdit,
  onDelete,
  onChangeLog,
  onRowPatch,
}: DetailTableProps) {
  const [sortKey, setSortKey] = useState<string | null>(null);
  const [sortDir, setSortDir] = useState<SortDir>('asc');
  const [columnWidths, setColumnWidths] = useState<Record<string, number>>(() => ({ ...DEFAULT_DETAIL_COLUMN_WIDTHS }));
  const resizeRef = useRef<{ key: string; startX: number; startWidth: number } | null>(null);

  const stickyLayout = useMemo(() => buildStickyLayout(columnWidths), [columnWidths]);

  const sortedRecords = useMemo(() => {
    if (!sortKey) return records;
    const dir = sortDir === 'asc' ? 1 : -1;
    return [...records].sort((a, b) => {
      const av = getSortValue(a, sortKey);
      const bv = getSortValue(b, sortKey);
      if (typeof av === 'number' && typeof bv === 'number') return (av - bv) * dir;
      return String(av ?? '').localeCompare(String(bv ?? ''), 'zh-CN') * dir;
    });
  }, [records, sortKey, sortDir]);

  const handleSort = useCallback((key: string) => {
    setSortKey((prev) => {
      if (prev === key) {
        setSortDir((d) => (d === 'asc' ? 'desc' : 'asc'));
        return key;
      }
      setSortDir('asc');
      return key;
    });
  }, []);

  const handleResizeStart = useCallback((key: string, event: React.MouseEvent) => {
    event.preventDefault();
    event.stopPropagation();
    resizeRef.current = {
      key,
      startX: event.clientX,
      startWidth: columnWidths[key] ?? DEFAULT_DETAIL_COLUMN_WIDTHS[key] ?? 100,
    };
  }, [columnWidths]);

  useEffect(() => {
    const onMove = (event: MouseEvent) => {
      if (!resizeRef.current) return;
      const delta = event.clientX - resizeRef.current.startX;
      const next = Math.max(56, resizeRef.current.startWidth + delta);
      setColumnWidths((prev) => ({ ...prev, [resizeRef.current!.key]: next }));
    };
    const onUp = () => {
      resizeRef.current = null;
    };
    window.addEventListener('mousemove', onMove);
    window.addEventListener('mouseup', onUp);
    return () => {
      window.removeEventListener('mousemove', onMove);
      window.removeEventListener('mouseup', onUp);
    };
  }, []);

  const tableMinWidth = Math.max(
    DETAIL_TABLE_MIN_WIDTH,
    ACTION_COL_WIDTH + DETAIL_TABLE_COLUMNS.reduce(
      (sum, col) => sum + (columnWidths[col.key] ?? DEFAULT_DETAIL_COLUMN_WIDTHS[col.key] ?? 100),
      0,
    ),
  );

  if (loading) {
    return (
      <div className="vm-table-wrap ldb-table-wrap lbd-table-wrap" data-annotation-id="lbd-table">
        <TableSkeleton />
      </div>
    );
  }

  if (!sortedRecords.length) {
    return (
      <div className="vm-empty lbd-empty" data-annotation-id="lbd-table">
        <p>暂无符合条件的租赁业务明细</p>
        <p className="vm-empty-hint">调整筛选条件，或使用工具栏「批量导入」上传 Excel</p>
      </div>
    );
  }

  return (
    <div className="vm-table-wrap ldb-table-wrap lbd-table-wrap" data-annotation-id="lbd-table">
      <table className="vm-table ldb-table lbd-detail-table" style={{ minWidth: tableMinWidth }}>
        <colgroup>
          {DETAIL_TABLE_COLUMNS.map((col) => (
            <col key={col.key} style={{ width: columnWidths[col.key] ?? DEFAULT_DETAIL_COLUMN_WIDTHS[col.key] ?? 100 }} />
          ))}
          <col style={{ width: ACTION_COL_WIDTH }} />
        </colgroup>
        <thead>
          <tr>
            {DETAIL_TABLE_COLUMNS.map((col) => {
              const headerTip = resolveColumnHeaderTip(col.annotationId, col.headerTip);
              return (
                <th
                  key={col.key}
                  className={[
                    col.money ? 'ldb-col-money tabular-nums' : '',
                    col.calculated ? 'lbd-col-calc' : '',
                    stickyClass(col),
                    'ldb-col-resizable',
                  ].filter(Boolean).join(' ')}
                  style={stickyStyle(col, stickyLayout, true)}
                  {...(col.annotationId ? { 'data-annotation-id': col.annotationId } : {})}
                >
                  <div className="ldb-th-inner">
                    <HeaderWithTip
                      title={col.title}
                      tip={headerTip}
                      sortable={Boolean(col.dateSort)}
                      sortActive={sortKey === col.key}
                      sortDir={sortDir}
                      onSort={col.dateSort ? () => handleSort(col.key) : undefined}
                    />
                    <span
                      className="ldb-col-resize-handle"
                      role="separator"
                      aria-orientation="vertical"
                      aria-label={`调整${col.title}列宽`}
                      onMouseDown={(event) => handleResizeStart(col.key, event)}
                    />
                  </div>
                </th>
              );
            })}
            <th className="sticky-col-right ldb-col-actions" data-annotation-id="lbd-col-actions">操作</th>
          </tr>
        </thead>
        <tbody>
          {sortedRecords.map((row) => {
            const canEdit = canEditDetailRow(row, isSupervisor);
            const archived = row.archiveStatus === 'archived';
            return (
              <tr key={row.id} className={archived ? 'lbd-row-archived' : undefined}>
                {DETAIL_TABLE_COLUMNS.map((col) => (
                  <td
                    key={col.key}
                    className={[
                      col.money ? 'ldb-col-money tabular-nums' : '',
                      col.calculated ? 'lbd-col-calc' : '',
                      stickyClass(col),
                    ].filter(Boolean).join(' ')}
                    style={stickyStyle(col, stickyLayout, false)}
                  >
                    {renderCell(row, col, onRowPatch)}
                  </td>
                ))}
                <td className="sticky-col-right ldb-col-actions">
                  <OperationActions
                    edit={canEdit ? { onClick: () => onEdit(row) } : undefined}
                    more={[
                      ...(canEdit
                        ? [{
                            key: 'delete',
                            label: '删除',
                            danger: true,
                            onClick: () => onDelete(row),
                          }]
                        : []),
                      {
                        key: 'changeLog',
                        label: '变更日志',
                        onClick: () => onChangeLog(row),
                      },
                    ]}
                  />
                </td>
              </tr>
            );
          })}
        </tbody>
        <tfoot>
          <tr className="lbd-summary-row">
            {DETAIL_TABLE_COLUMNS.map((col) => (
              <td
                key={col.key}
                className={[
                  col.money ? 'ldb-col-money tabular-nums' : '',
                  col.calculated ? 'lbd-col-calc' : '',
                  stickyClass(col),
                  'lbd-summary-cell',
                ].filter(Boolean).join(' ')}
                style={stickyStyle(col, stickyLayout, false)}
              >
                {renderSummaryCell(col, summary)}
              </td>
            ))}
            <td className="sticky-col-right ldb-col-actions" />
          </tr>
        </tfoot>
      </table>
    </div>
  );
}
