/**
 * @name 租赁业务明细
 * 设计规范：ledger-shared/DESIGN.md · vm-page + ldb-page
 */
import '../vehicle-management/style.css';
import '../lease-business-ledger/styles/index.css';
import './styles/index.css';
import React, { useCallback, useMemo, useState } from 'react';
import { Download, FileUp } from 'lucide-react';
import {
  type AnnotationDirectoryRouteNode,
  type AnnotationSourceDocument,
  type AnnotationViewerOptions
} from '@axhub/annotation';
import { PrototypeAnnotationHost } from '../../common/prototype-annotation-host';
import seedRows from './data/rows.json';
import changeLogSeed from './data/change-log-seed.json';
import { FilterPanel } from './components/FilterPanel';
import { DetailKpiRow } from './components/DetailKpiRow';
import { DetailTable } from './components/DetailTable';
import { DetailImportModal } from './components/DetailImportModal';
import { DetailEditModal } from './components/DetailEditModal';
import { DetailChangeLogModal } from './components/DetailChangeLogModal';
import { DetailDeleteConfirmModal } from './components/DetailDeleteConfirmModal';
import { TablePagination, DEFAULT_PAGE_SIZE } from '../../common/TablePagination';
import {
  EMPTY_LEASE_DETAIL_FILTERS,
  type LeaseBusinessDetailRow,
  type LeaseDetailFilters,
} from './types';
import { applyDetailFilters, detailRowYearMonth, sumDetailKpi } from './utils/detail';
import { applyDetailCalculations } from './utils/calc-detail';
import {
  downloadDetailImportTemplate,
  downloadDetailImportErrorLog,
  exportDetailRows,
  parseDetailImportFile,
  type DetailImportErrorRow,
} from './utils/batch-io';
import {
  appendChangeLogs,
  collectRowChangeLogs,
  createChangeLogEntry,
  type DetailChangeLogsByRowId,
} from './utils/change-log';
import { isDetailSupervisor, resolveDetailOperator } from './utils/role';
import annotationSourceDocument from './annotation-source.json';

const ARCHIVED_DEMO_ROW_IDS = new Set(['lbd-33']);

export default function LeaseBusinessDetailApp() {
  const operator = useMemo(() => resolveDetailOperator(), []);
  const isSupervisor = isDetailSupervisor(operator);

  const [records, setRecords] = useState<LeaseBusinessDetailRow[]>(() =>
    (seedRows as LeaseBusinessDetailRow[]).map((row) => applyDetailCalculations({
      ...row,
      archiveStatus: ARCHIVED_DEMO_ROW_IDS.has(row.id) ? 'archived' : (row.archiveStatus ?? 'active'),
      reconciledAt: ARCHIVED_DEMO_ROW_IDS.has(row.id) ? '2026-01-18' : (row.reconciledAt ?? ''),
    })),
  );
  const [changeLogs, setChangeLogs] = useState<DetailChangeLogsByRowId>(
    () => ({ ...(changeLogSeed as DetailChangeLogsByRowId) }),
  );
  const [pendingFilters, setPendingFilters] = useState<LeaseDetailFilters>(EMPTY_LEASE_DETAIL_FILTERS);
  const [appliedFilters, setAppliedFilters] = useState<LeaseDetailFilters>(EMPTY_LEASE_DETAIL_FILTERS);
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(DEFAULT_PAGE_SIZE);
  const [tableLoading, setTableLoading] = useState(false);
  const [importOpen, setImportOpen] = useState(false);
  const [importErrors, setImportErrors] = useState<DetailImportErrorRow[]>([]);
  const [importErrorHeaders, setImportErrorHeaders] = useState<string[]>([]);
  const [toast, setToast] = useState('');
  const [editRow, setEditRow] = useState<LeaseBusinessDetailRow | null>(null);
  const [deleteRow, setDeleteRow] = useState<LeaseBusinessDetailRow | null>(null);
  const [changeLogRow, setChangeLogRow] = useState<LeaseBusinessDetailRow | null>(null);

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

  const filtered = useMemo(
    () => applyDetailFilters(records, appliedFilters),
    [records, appliedFilters],
  );
  const kpi = useMemo(() => sumDetailKpi(filtered), [filtered]);
  const totalPages = Math.max(1, Math.ceil(filtered.length / pageSize));
  const paged = useMemo(() => {
    const start = (page - 1) * pageSize;
    return filtered.slice(start, start + pageSize);
  }, [filtered, page, pageSize]);

  const updateRow = useCallback((
    id: string,
    patch: Partial<LeaseBusinessDetailRow>,
    logMeta?: { forceField?: string; fieldLabel?: string },
  ) => {
    setRecords((prev) => {
      const before = prev.find((row) => row.id === id);
      if (!before) return prev;
      const after = applyDetailCalculations({ ...before, ...patch });
      const logs = collectRowChangeLogs(operator, before, after);
      if (logs.length) {
        setChangeLogs((prevLogs) => appendChangeLogs(prevLogs, id, logs));
      } else if (logMeta?.forceField) {
        const entry = createChangeLogEntry(
          operator,
          logMeta.forceField,
          before[logMeta.forceField as keyof LeaseBusinessDetailRow],
          after[logMeta.forceField as keyof LeaseBusinessDetailRow],
          { fieldLabel: logMeta.fieldLabel, force: true },
        );
        if (entry) setChangeLogs((prevLogs) => appendChangeLogs(prevLogs, id, [entry]));
      }
      return prev.map((row) => (row.id === id ? after : row));
    });
  }, [operator]);

  const handleSearch = () => {
    setTableLoading(true);
    window.setTimeout(() => {
      setAppliedFilters(pendingFilters);
      setPage(1);
      setTableLoading(false);
    }, 280);
  };

  const handleReset = () => {
    setPendingFilters(EMPTY_LEASE_DETAIL_FILTERS);
    setAppliedFilters(EMPTY_LEASE_DETAIL_FILTERS);
    setPage(1);
  };

  const handleImport = async (file: File) => {
    try {
      const result = await parseDetailImportFile(file);
      setImportErrors(result.errors);
      setImportErrorHeaders(result.fileHeaders);

      if (result.success.length === 0 && result.errors.length === 0) {
        showToast('未解析到有效数据，请检查模板与必填列');
        return;
      }

      if (result.success.length > 0) {
        const imported = result.success.map((row) => applyDetailCalculations({
          ...row,
          archiveStatus: 'active',
          reconciledAt: '',
        }));
        setRecords((prev) => [...imported, ...prev]);
        setChangeLogs((prev) => {
          let next = { ...prev };
          imported.forEach((row) => {
            const entry = createChangeLogEntry(operator, '_import', null, null, {
              fieldLabel: '批量导入',
              beforeText: '—',
              afterText: '新增明细',
              force: true,
            });
            if (entry) next = appendChangeLogs(next, row.id, [entry]);
          });
          return next;
        });
        setPage(1);
      }

      if (result.errors.length > 0 && result.success.length > 0) {
        showToast(`已导入 ${result.success.length} 条；${result.errors.length} 条失败，可下载错误日志`);
      } else if (result.errors.length > 0) {
        showToast(`${result.errors.length} 条导入失败，请下载错误日志查看原因`);
      } else {
        setImportOpen(false);
        showToast(`已导入 ${result.success.length} 条明细，公式列已自动计算`);
      }
    } catch {
      showToast('导入失败，请检查文件格式');
    }
  };

  const handleDeleteConfirm = () => {
    if (!deleteRow) return;
    const entry = createChangeLogEntry(operator, '_delete', null, null, {
      fieldLabel: '删除记录',
      beforeText: `${detailRowYearMonth(deleteRow)} · ${deleteRow.plateNo}`,
      afterText: '已删除',
      force: true,
    });
    if (entry) setChangeLogs((prev) => appendChangeLogs(prev, deleteRow.id, [entry]));
    setRecords((prev) => prev.filter((row) => row.id !== deleteRow.id));
    setDeleteRow(null);
    showToast('已删除该条明细');
  };

  const changeLogEntries = changeLogRow ? (changeLogs[changeLogRow.id] ?? []) : [];
  const changeLogLabel = changeLogRow
    ? `${detailRowYearMonth(changeLogRow)} · ${changeLogRow.plateNo}`
    : '';

  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 lc-page lc-page--list-dense lbd-page">
        <div className="lbd-role-banner" role="status">
          <span>
            当前视角：
            {isSupervisor ? '业务管理部主管（可修改已锁定记录）' : '业管人员'}
          </span>
          {!isSupervisor && (
            <span className="lbd-role-banner-hint">主管预览：URL 追加 ?role=supervisor</span>
          )}
        </div>

        <FilterPanel
          records={records}
          filters={pendingFilters}
          onChange={(patch) => setPendingFilters((prev) => ({ ...prev, ...patch }))}
          onReset={handleReset}
          onSearch={handleSearch}
        />

        <DetailKpiRow summary={kpi} />

        <section className="vm-table-section">
          <div className="vm-table-toolbar ldb-table-toolbar" data-annotation-id="lbd-toolbar">
            <div className="vm-table-actions">
              <button
                type="button"
                className="vm-btn vm-btn-secondary ldb-toolbar-btn"
                data-vm-icon="import"
                onClick={() => {
                  setImportErrors([]);
                  setImportErrorHeaders([]);
                  setImportOpen(true);
                }}
              >
                批量导入
              </button>
              <button
                type="button"
                className="vm-btn vm-btn-ghost ldb-toolbar-btn"
                data-vm-icon="download"
                onClick={() => {
                  exportDetailRows(filtered);
                  showToast(`已导出 ${filtered.length} 条明细`);
                }}
              >
                批量导出
              </button>
            </div>
          </div>

          <div className="vm-table-card">
            <DetailTable
              records={paged}
              summary={kpi}
              loading={tableLoading}
              isSupervisor={isSupervisor}
              onEdit={setEditRow}
              onDelete={setDeleteRow}
              onChangeLog={setChangeLogRow}
              onRowPatch={(id, patch) => updateRow(id, patch)}
            />
            <div className="vm-table-footer ldb-table-footer">
              <TablePagination
                page={Math.min(page, totalPages)}
                pageSize={pageSize}
                total={filtered.length}
                onPageChange={setPage}
                onPageSizeChange={(size) => {
                  setPageSize(size);
                  setPage(1);
                }}
              />
            </div>
          </div>
        </section>

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

      <DetailImportModal
        open={importOpen}
        onClose={() => setImportOpen(false)}
        onDownloadTemplate={downloadDetailImportTemplate}
        onImport={handleImport}
        failedCount={importErrors.length}
        onDownloadErrorLog={
          importErrors.length > 0
            ? () => downloadDetailImportErrorLog(importErrors, importErrorHeaders)
            : undefined
        }
      />

      <DetailEditModal
        open={Boolean(editRow)}
        row={editRow}
        onClose={() => setEditRow(null)}
        onSave={(patch) => {
          if (!editRow) return;
          updateRow(editRow.id, patch);
          setEditRow(null);
          showToast('明细已保存，公式列已自动重算');
        }}
      />

      <DetailDeleteConfirmModal
        open={Boolean(deleteRow)}
        rowLabel={deleteRow ? `${detailRowYearMonth(deleteRow)} · ${deleteRow.plateNo}` : ''}
        onCancel={() => setDeleteRow(null)}
        onConfirm={handleDeleteConfirm}
      />

      <DetailChangeLogModal
        open={Boolean(changeLogRow)}
        rowLabel={changeLogLabel}
        entries={changeLogEntries}
        onClose={() => setChangeLogRow(null)}
      />

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