/**
 * @name 租赁业务台账
 */
import '../vehicle-management/style.css';
import './styles/index.css';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { CheckCircle2, Download, FileUp, Plus, Send } from 'lucide-react';
import {
  AnnotationViewer,
  type AnnotationDirectoryRouteNode,
  type AnnotationSourceDocument,
  type AnnotationViewerOptions,
} from '@axhub/annotation';
import seedRows from './data/rows.json';
import seedReceipts from './data/receipts.json';
import seedMaintenance from './data/maintenance-orders.json';
import seedAccidents from './data/accident-records.json';
import seedBiMileage from './data/bi-mileage.json';
import seedHydrogenFees from './data/hydrogen-fees.json';
import { FilterPanel } from './components/FilterPanel';
import { LedgerKpiRow } from './components/LedgerKpiRow';
import { LeaseLedgerTable } from './components/LeaseLedgerTable';
import { ConfirmMarkModal } from './components/ConfirmMarkModal';
import { DeleteConfirmModal } from './components/DeleteConfirmModal';
import { ReceiptLinkModal } from './components/ReceiptLinkModal';
import { MaintenanceLinkModal } from './components/MaintenanceLinkModal';
import { AccidentLinkModal } from './components/AccidentLinkModal';
import {
  EMPTY_LEASE_FILTERS,
  type AccidentRecord,
  type BiMileageRecord,
  type HydrogenFeeRecord,
  type LeaseLedgerFilters,
  type LeaseLedgerRow,
  type ListViewMode,
  type MaintenanceOrder,
  type ReceiptRecord,
} from './types';
import {
  applyLeaseFilters,
  applyListViewFilter,
  canStaffDeleteRow,
  canStaffEditRow,
  enrichLeaseRow,
  filterRecordsByRole,
  latestReceiptPaymentDate,
  LOAD_BATCH_SIZE,
  resolveStatusAfterReceipt,
  sumLeaseKpi,
} from './utils/ledger';
import annotationSourceDocument from './annotation-source.json';

const MAINTENANCE_ORDERS = seedMaintenance as MaintenanceOrder[];
const ACCIDENT_RECORDS = seedAccidents as AccidentRecord[];
const BI_MILEAGE = seedBiMileage as BiMileageRecord[];
const HYDROGEN_FEES = seedHydrogenFees as HydrogenFeeRecord[];

function mapRows(rows: LeaseLedgerRow[]): LeaseLedgerRow[] {
  return rows.map((row) => enrichLeaseRow(row, {
    maintenanceOrders: MAINTENANCE_ORDERS,
    accidentRecords: ACCIDENT_RECORDS,
    biMileage: BI_MILEAGE,
    hydrogenFees: HYDROGEN_FEES,
  }));
}

export default function LeaseBusinessLedgerApp() {
  const [records, setRecords] = useState<LeaseLedgerRow[]>(() => mapRows(seedRows as LeaseLedgerRow[]));
  const [receipts] = useState<ReceiptRecord[]>(seedReceipts as ReceiptRecord[]);
  const [pendingFilters, setPendingFilters] = useState<LeaseLedgerFilters>(EMPTY_LEASE_FILTERS);
  const [appliedFilters, setAppliedFilters] = useState<LeaseLedgerFilters>(EMPTY_LEASE_FILTERS);
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
  const [toast, setToast] = useState('');
  const [confirmOpen, setConfirmOpen] = useState(false);
  const [receiptRow, setReceiptRow] = useState<LeaseLedgerRow | null>(null);
  const [maintenanceRow, setMaintenanceRow] = useState<LeaseLedgerRow | null>(null);
  const [accidentRow, setAccidentRow] = useState<LeaseLedgerRow | null>(null);
  const [showUnpaidOnly, setShowUnpaidOnly] = useState(false);
  const [listViewMode, setListViewMode] = useState<ListViewMode>('all');
  const [visibleCount, setVisibleCount] = useState(LOAD_BATCH_SIZE);
  const [tableLoading, setTableLoading] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<LeaseLedgerRow | null>(null);
  const [submitApprovalOpen, setSubmitApprovalOpen] = useState(false);

  const showToast = useCallback((msg: string) => {
    setToast(msg);
    window.setTimeout(() => setToast(''), 3000);
  }, []);

  const roleScopedRecords = useMemo(() => filterRecordsByRole(records), [records]);
  const filtered = useMemo(
    () => applyLeaseFilters(records, appliedFilters),
    [records, appliedFilters],
  );
  const listFiltered = useMemo(
    () => applyListViewFilter(filtered, { showUnpaidOnly, listViewMode }),
    [filtered, showUnpaidOnly, listViewMode],
  );
  const kpi = useMemo(() => sumLeaseKpi(applyLeaseFilters(roleScopedRecords, appliedFilters)), [roleScopedRecords, appliedFilters]);
  const visibleRecords = useMemo(
    () => listFiltered.slice(0, visibleCount),
    [listFiltered, visibleCount],
  );
  const hasMore = visibleCount < listFiltered.length;

  useEffect(() => {
    setVisibleCount(LOAD_BATCH_SIZE);
  }, [appliedFilters, showUnpaidOnly, listViewMode]);

  const draftSelectedCount = useMemo(
    () => Array.from(selectedIds).filter((id) => records.find((r) => r.id === id)?.status === '草稿').length,
    [selectedIds, records],
  );

  const handleSearch = () => {
    setTableLoading(true);
    window.setTimeout(() => {
      setAppliedFilters(pendingFilters);
      setSelectedIds(new Set());
      setTableLoading(false);
    }, 320);
  };

  const handleReset = () => {
    setPendingFilters(EMPTY_LEASE_FILTERS);
    setAppliedFilters(EMPTY_LEASE_FILTERS);
    setSelectedIds(new Set());
    setShowUnpaidOnly(false);
    setListViewMode('all');
  };

  const handleMarkConfirmedClick = () => {
    if (draftSelectedCount === 0) {
      showToast('请先勾选草稿状态的记录');
      return;
    }
    setConfirmOpen(true);
  };

  const handleConfirmMark = () => {
    const draftIds = new Set(
      Array.from(selectedIds).filter((id) => records.find((r) => r.id === id)?.status === '草稿'),
    );
    setRecords((prev) => mapRows(
      prev.map((row) => (draftIds.has(row.id) ? { ...row, status: '已确认' as const } : row)),
    ));
    setConfirmOpen(false);
    setSelectedIds(new Set());
    showToast(`已确认 ${draftIds.size} 条记录，业务服务组人员不可再删改`);
  };

  const handleReceiptConfirm = (
    recordId: string,
    selectedReceiptIds: string[],
    linkedAmount: number,
    _allocations: Record<string, number>,
  ) => {
    const arrivalTimes = selectedReceiptIds
      .map((id) => receipts.find((r) => r.id === id)?.arrivalTime)
      .filter((v): v is string => Boolean(v));
    const paymentDate = latestReceiptPaymentDate(arrivalTimes);
    const billAmount = Math.min(linkedAmount, records.find((r) => r.id === recordId)?.receivableTotal ?? linkedAmount);

    setRecords((prev) => mapRows(
      prev.map((row) => {
        if (row.id !== recordId) return row;
        const receivedAmount = Math.round((row.receivedAmount + billAmount) * 100) / 100;
        return {
          ...row,
          receivedAmount,
          linkedReceiptIds: [...new Set([...(row.linkedReceiptIds ?? []), ...selectedReceiptIds])],
          actualPaymentDate: paymentDate,
          status: resolveStatusAfterReceipt(row.receivableTotal, receivedAmount),
        };
      }),
    ));
    setReceiptRow(null);
    showToast(linkedAmount > billAmount ? '收款关联成功，多出部分请在单据下自行分配' : '收款记录关联成功');
  };

  const handleMaintenanceConfirm = (recordId: string, selectedIds: string[]) => {
    setRecords((prev) => mapRows(
      prev.map((row) => (
        row.id === recordId
          ? { ...row, linkedMaintenanceIds: [...new Set([...row.linkedMaintenanceIds, ...selectedIds])] }
          : row
      )),
    ));
    setMaintenanceRow(null);
    showToast('维修/保养记录关联成功，运维费已自动计算');
  };

  const handleAccidentConfirm = (recordId: string, selectedIds: string[]) => {
    setRecords((prev) => mapRows(
      prev.map((row) => (
        row.id === recordId
          ? { ...row, linkedAccidentIds: [...new Set([...row.linkedAccidentIds, ...selectedIds])] }
          : row
      )),
    ));
    setAccidentRow(null);
    showToast('事故单据关联成功，保险上浮费已自动汇总');
  };

  const handleOtherIncomeChange = (recordId: string, value: number) => {
    setRecords((prev) => mapRows(
      prev.map((row) => (row.id === recordId ? { ...row, otherIncome: value } : row)),
    ));
  };

  const handleOtherCostChange = (recordId: string, value: number) => {
    setRecords((prev) => mapRows(
      prev.map((row) => (row.id === recordId ? { ...row, otherCost: value } : row)),
    ));
  };

  const handleBrokerageFeeChange = (recordId: string, value: number) => {
    setRecords((prev) => mapRows(
      prev.map((row) => (row.id === recordId ? { ...row, brokerageFee: value } : row)),
    ));
  };

  const handleRemarkChange = (recordId: string, value: string) => {
    setRecords((prev) => mapRows(
      prev.map((row) => (row.id === recordId ? { ...row, remark: value } : row)),
    ));
  };

  const handleDeductionDetailChange = (recordId: string, value: string) => {
    setRecords((prev) => mapRows(
      prev.map((row) => (row.id === recordId ? { ...row, otherDeductionDetail: value } : row)),
    ));
  };

  const handleListViewChange = (mode: ListViewMode) => {
    setListViewMode(mode);
    if (mode === 'unpaid') setShowUnpaidOnly(true);
    if (mode === 'all') setShowUnpaidOnly(false);
  };

  const annotationOptions = useMemo<AnnotationViewerOptions>(
    () => ({
      showToolbar: true,
      showThemeToggle: true,
      showColorFilter: true,
      emptyWhenNoData: false,
      toolbarEdge: 'right',
      currentPageId: 'list',
      onDirectoryRoute: (_node: AnnotationDirectoryRouteNode) => {},
    }),
    [],
  );

  return (
    <>
      <div className="vm-page ldb-page">
        <FilterPanel
          records={records}
          filters={pendingFilters}
          onChange={(patch) => setPendingFilters((prev) => ({ ...prev, ...patch }))}
          onReset={handleReset}
          onSearch={handleSearch}
        />

        <LedgerKpiRow
          summary={kpi}
          listViewMode={listViewMode}
          onListViewChange={handleListViewChange}
        />

        <section className="vm-table-section">
          <div className="vm-table-toolbar ldb-table-toolbar" data-annotation-id="lbl-toolbar">
            <label className="ldb-toolbar-unpaid-filter">
              <input
                type="checkbox"
                checked={showUnpaidOnly}
                onChange={(e) => {
                  setShowUnpaidOnly(e.target.checked);
                  setListViewMode(e.target.checked ? 'unpaid' : 'all');
                }}
              />
              仅显示未收款数据
            </label>
            <div className="vm-table-actions">
              <button type="button" className="vm-btn vm-btn-secondary ldb-toolbar-btn" onClick={() => showToast('批量导入（原型演示）')}>
                <FileUp size={16} aria-hidden />
                批量导入
              </button>
              <button type="button" className="vm-btn vm-btn-ghost ldb-toolbar-btn" onClick={() => showToast(`导出 ${listFiltered.length} 条（原型演示）`)}>
                <Download size={16} aria-hidden />
                导出
              </button>
              <button
                type="button"
                className="vm-btn vm-btn-ghost ldb-toolbar-btn"
                data-annotation-id="lbl-btn-mark-confirmed"
                onClick={handleMarkConfirmedClick}
              >
                <CheckCircle2 size={16} aria-hidden />
                标记为已确认
              </button>
              <button
                type="button"
                className="vm-btn vm-btn-primary ldb-toolbar-btn"
                onClick={() => {
                  if (selectedIds.size === 0) {
                    showToast('请先勾选需要提交审批的记录');
                    return;
                  }
                  setSubmitApprovalOpen(true);
                }}
              >
                <Send size={16} aria-hidden />
                提交收款审批
              </button>
            </div>
          </div>

          <div className="vm-table-card">
            <LeaseLedgerTable
              records={visibleRecords}
              loading={tableLoading}
              maintenanceOrders={MAINTENANCE_ORDERS}
              accidentRecords={ACCIDENT_RECORDS}
              selectedIds={selectedIds}
              onToggleRow={(id, checked) => {
                setSelectedIds((prev) => {
                  const next = new Set(prev);
                  if (checked) next.add(id);
                  else next.delete(id);
                  return next;
                });
              }}
              onToggleAll={(checked) => {
                setSelectedIds(checked ? new Set(listFiltered.map((r) => r.id)) : new Set());
              }}
              onEdit={(row) => {
                if (!canStaffEditRow(row)) {
                  showToast('已确认记录仅业务服务组主管可修改');
                  return;
                }
                showToast(`行内编辑：${row.plateNo}（原型演示）`);
              }}
              onDelete={(row) => {
                if (!canStaffDeleteRow(row)) return;
                setDeleteTarget(row);
              }}
              onLinkReceipt={(row) => setReceiptRow(row)}
              onLinkMaintenance={(row) => setMaintenanceRow(row)}
              onLinkAccident={(row) => setAccidentRow(row)}
              onOtherIncomeChange={handleOtherIncomeChange}
              onOtherCostChange={handleOtherCostChange}
              onBrokerageFeeChange={handleBrokerageFeeChange}
              onRemarkChange={handleRemarkChange}
              onDeductionDetailChange={handleDeductionDetailChange}
            />
            <div className="vm-table-footer ldb-table-footer">
              <span className="ldb-table-total">
                已显示 {visibleRecords.length} / 共 {listFiltered.length} 条
              </span>
              <div className="ldb-table-footer-actions">
                {hasMore && (
                  <button
                    type="button"
                    className="vm-btn vm-btn-ghost"
                    onClick={() => setVisibleCount((n) => n + LOAD_BATCH_SIZE)}
                  >
                    下拉显示更多
                  </button>
                )}
                <button
                  type="button"
                  className="vm-btn vm-btn-secondary"
                  data-annotation-id="lbl-btn-add-row"
                  onClick={() => showToast('表格底部新增行（原型演示）')}
                >
                  <Plus size={16} aria-hidden />
                  添加行
                </button>
              </div>
            </div>
          </div>
        </section>

        {toast && <div className="vm-toast" role="status">{toast}</div>}
      </div>

      <ConfirmMarkModal
        open={confirmOpen}
        count={draftSelectedCount}
        onCancel={() => setConfirmOpen(false)}
        onConfirm={handleConfirmMark}
      />
      <DeleteConfirmModal
        open={Boolean(deleteTarget)}
        plateNo={deleteTarget?.plateNo ?? ''}
        onCancel={() => setDeleteTarget(null)}
        onConfirm={() => {
          if (!deleteTarget) return;
          setRecords((prev) => prev.filter((row) => row.id !== deleteTarget.id));
          setSelectedIds((prev) => {
            const next = new Set(prev);
            next.delete(deleteTarget.id);
            return next;
          });
          setDeleteTarget(null);
          showToast(`已删除 ${deleteTarget.plateNo}（原型）`);
        }}
      />
      {submitApprovalOpen && (
        <div className="vm-modal-backdrop" role="presentation" onClick={() => setSubmitApprovalOpen(false)}>
          <div className="vm-modal vm-modal-sm" role="dialog" aria-modal="true" onClick={(e) => e.stopPropagation()}>
            <header className="vm-modal-header">
              <h2 className="vm-modal-title">提交收款审批</h2>
            </header>
            <div className="vm-modal-body">
              <p className="ldb-confirm-text">确认将所选 {selectedIds.size} 条记录提交收款审批？</p>
            </div>
            <footer className="vm-modal-footer">
              <button type="button" className="vm-btn vm-btn-ghost" onClick={() => setSubmitApprovalOpen(false)}>取消</button>
              <button
                type="button"
                className="vm-btn vm-btn-primary"
                onClick={() => {
                  setSubmitApprovalOpen(false);
                  showToast(`已提交 ${selectedIds.size} 条收款审批（原型演示）`);
                }}
              >
                确认提交
              </button>
            </footer>
          </div>
        </div>
      )}
      <ReceiptLinkModal
        key={receiptRow?.id ?? 'closed'}
        open={Boolean(receiptRow)}
        record={receiptRow}
        receipts={receipts}
        onClose={() => setReceiptRow(null)}
        onConfirm={handleReceiptConfirm}
      />
      <MaintenanceLinkModal
        key={maintenanceRow?.id ?? 'closed'}
        open={Boolean(maintenanceRow)}
        record={maintenanceRow}
        orders={MAINTENANCE_ORDERS}
        onClose={() => setMaintenanceRow(null)}
        onConfirm={handleMaintenanceConfirm}
      />
      <AccidentLinkModal
        key={accidentRow?.id ?? 'closed'}
        open={Boolean(accidentRow)}
        record={accidentRow}
        accidents={ACCIDENT_RECORDS}
        onClose={() => setAccidentRow(null)}
        onConfirm={handleAccidentConfirm}
      />

      <AnnotationViewer source={annotationSourceDocument as AnnotationSourceDocument} options={annotationOptions} />
    </>
  );
}
