import React, { useCallback, useMemo, useRef, useState } from 'react';
import { ArrowDown, ArrowUp, ArrowUpDown } from 'lucide-react';
import { OperationActions } from '../../../common/OperationActions';
import type { SelfOperatedLedgerRow } from '../types';
import {
  computeAmount,
  computeProfitLoss,
  computeTotalCost,
  displayText,
  formatDisplayMonth,
  formatMoney,
  profitLossClassName,
} from '../utils/ledger';
import { resolveSystemVehicleType } from '../utils/vehicle-ref';
import {
  DEFAULT_SELF_COLUMN_WIDTHS,
  SELF_STICKY_LEFT_KEYS,
  SELF_TABLE_COLUMNS,
  type SelfTableColumn,
} from './tableColumns';

interface SelfLedgerTableProps {
  records: SelfOperatedLedgerRow[];
  loading?: boolean;
  onEdit: (record: SelfOperatedLedgerRow) => void;
  onDelete: (record: SelfOperatedLedgerRow) => void;
}

type SortDir = 'asc' | 'desc';

const ACTION_COL_WIDTH = 168;

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

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

function HeaderSort({
  title,
  sortActive,
  sortDir,
  onSort,
}: {
  title: string;
  sortActive?: boolean;
  sortDir?: SortDir;
  onSort: () => void;
}) {
  return (
    <button type="button" className={`ldb-th-sort ${sortActive ? 'is-active' : ''}`} onClick={onSort}>
      <span className="ldb-th-label">{title}</span>
      <span className="ldb-th-sort-icon" aria-hidden>
        {sortActive
          ? (sortDir === 'asc' ? <ArrowUp size={14} /> : <ArrowDown size={14} />)
          : <ArrowUpDown size={14} />}
      </span>
    </button>
  );
}

function renderCell(row: SelfOperatedLedgerRow, col: SelfTableColumn) {
  if (col.key === 'month') {
    return formatDisplayMonth(row);
  }
  if (col.key === 'systemVehicleType') {
    return resolveSystemVehicleType(row.plateNo) || displayText(row.systemVehicleType);
  }
  if (col.key === 'amount') {
    return formatMoney(computeAmount(row));
  }
  if (col.key === 'totalCost') {
    return formatMoney(computeTotalCost(row));
  }
  if (col.key === 'profitLoss') {
    const profitLoss = computeProfitLoss(row);
    return (
      <span className={profitLossClassName(profitLoss)}>
        {formatMoney(profitLoss)}
      </span>
    );
  }
  const raw = row[col.key as keyof SelfOperatedLedgerRow];
  if (col.money && typeof raw === 'number') {
    if (col.key === 'quantity') return raw === 0 ? '' : String(raw);
    return formatMoney(raw);
  }
  return displayText(raw);
}

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 SelfLedgerTable({
  records,
  loading = false,
  onEdit,
  onDelete,
}: SelfLedgerTableProps) {
  const [sortKey, setSortKey] = useState<string | null>(null);
  const [sortDir, setSortDir] = useState<SortDir>('asc');
  const [columnWidths, setColumnWidths] = useState<Record<string, number>>(() => ({ ...DEFAULT_SELF_COLUMN_WIDTHS }));
  const resizeRef = useRef<{ key: string; startX: number; startWidth: number } | null>(null);

  const sortedRecords = useMemo(() => {
    if (!sortKey) return records;
    const dir = sortDir === 'asc' ? 1 : -1;
    return [...records].sort((a, b) => {
      if (sortKey === 'month') {
        return formatDisplayMonth(a).localeCompare(formatDisplayMonth(b), 'zh-CN') * dir;
      }
      if (sortKey === 'amount') {
        return (computeAmount(a) - computeAmount(b)) * dir;
      }
      if (sortKey === 'totalCost') {
        return (computeTotalCost(a) - computeTotalCost(b)) * dir;
      }
      if (sortKey === 'profitLoss') {
        return (computeProfitLoss(a) - computeProfitLoss(b)) * dir;
      }
      const av = a[sortKey as keyof SelfOperatedLedgerRow];
      const bv = b[sortKey as keyof SelfOperatedLedgerRow];
      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_SELF_COLUMN_WIDTHS[key] ?? 100,
    };
  }, [columnWidths]);

  React.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 = ACTION_COL_WIDTH + SELF_TABLE_COLUMNS.reduce(
    (sum, col) => sum + (columnWidths[col.key] ?? DEFAULT_SELF_COLUMN_WIDTHS[col.key] ?? 100),
    0,
  );
  const stickyLayout = useMemo(() => buildStickyLayout(columnWidths), [columnWidths]);

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

  if (!sortedRecords.length) {
    return <div className="vm-empty" data-annotation-id="sob-table"><p>暂无符合条件的台账记录</p></div>;
  }

  return (
    <div className="vm-table-wrap ldb-table-wrap" data-annotation-id="sob-table">
      <table className="vm-table ldb-table" style={{ minWidth: tableMinWidth }}>
        <colgroup>
          {SELF_TABLE_COLUMNS.map((col) => (
            <col key={col.key} style={{ width: columnWidths[col.key] ?? DEFAULT_SELF_COLUMN_WIDTHS[col.key] ?? 100 }} />
          ))}
          <col style={{ width: ACTION_COL_WIDTH }} />
        </colgroup>
        <thead>
          <tr>
            {SELF_TABLE_COLUMNS.map((col) => (
              <th
                key={col.key}
                className={[
                  col.money ? 'ldb-col-money' : '',
                  stickyClass(col),
                  'ldb-col-resizable',
                ].filter(Boolean).join(' ')}
                style={stickyStyle(col, stickyLayout, true)}
              >
                <div className="ldb-th-inner">
                  {col.sortable ? (
                    <HeaderSort
                      title={col.title}
                      sortActive={sortKey === col.key}
                      sortDir={sortDir}
                      onSort={() => handleSort(col.key)}
                    />
                  ) : (
                    <span className="ldb-th-label">{col.title}</span>
                  )}
                  <span
                    className="ldb-col-resize-handle"
                    role="separator"
                    aria-orientation="vertical"
                    aria-label={`调整${col.title}列宽`}
                    onMouseDown={(e) => handleResizeStart(col.key, e)}
                  />
                </div>
              </th>
            ))}
            <th className="sticky-col-right ldb-col-actions">操作</th>
          </tr>
        </thead>
        <tbody>
          {sortedRecords.map((row) => (
            <tr key={row.id}>
              {SELF_TABLE_COLUMNS.map((col) => (
                <td
                  key={col.key}
                  className={[
                    col.money ? 'ldb-col-money tabular-nums' : '',
                    stickyClass(col),
                  ].filter(Boolean).join(' ')}
                  style={stickyStyle(col, stickyLayout, false)}
                  title={['businessName', 'systemVehicleType', 'routePricing', 'remark'].includes(col.key)
                    ? (col.key === 'systemVehicleType'
                      ? (resolveSystemVehicleType(row.plateNo) || String(row.systemVehicleType ?? ''))
                      : String(row[col.key as keyof SelfOperatedLedgerRow] ?? ''))
                    : undefined}
                >
                  {renderCell(row, col)}
                </td>
              ))}
              <td className="sticky-col-right ldb-col-actions">
                <OperationActions
                  edit={{ onClick: () => onEdit(row) }}
                  more={[
                    {
                      key: 'delete',
                      label: '删除',
                      danger: true,
                      onClick: () => onDelete(row),
                    },
                  ]}
                />
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}
