/**
 * @name 客户管理
 */

import '../vehicle-management/style.css';
import './styles/index.css';
import React, { useCallback, useMemo, useRef, useState } from 'react';
import { Download, FileUp, Plus, Tags } from 'lucide-react';
import {
  type AnnotationDirectoryRouteNode,
  type AnnotationSourceDocument,
  type AnnotationViewerOptions
} from '@axhub/annotation';
import { PrototypeAnnotationHost } from '../../common/prototype-annotation-host';
import seedCustomers from './data/customers.json';
import { FilterPanel } from './components/FilterPanel';
import { RiskKpiCards } from './components/RiskKpiCards';
import { CustomerTable } from './components/CustomerTable';
import { CreatePage } from './pages/CreatePage';
import { RiskTagDrawer } from './components/RiskTagDrawer';
import { BatchRiskTagModal } from './components/BatchRiskTagModal';
import { TablePagination } from '../vehicle-management/components/TablePagination';
import {
  EMPTY_CREATE_FORM,
  EMPTY_FILTERS,
  type CustomerCreateForm,
  type CustomerFilters,
  type CustomerPageId,
  type CustomerRecord,
  type CustomerRiskKpiKey,
} from './types';
import type { CustomerRiskTag, MockUser, RiskTagApplyForm } from './types/riskTag';
import { applyFilters } from './utils/filters';
import { countRiskKpi } from './utils/riskKpi';
import {
  buildApplyLog,
  buildApplyTag,
  buildApprovalLog,
  buildRemoveLog,
  buildRemovalApprovalLog,
  buildSeedRiskTags,
  buildWorkbenchTodoLog,
  formatNow,
  INITIAL_OPERATION_LOGS,
  isHighRiskLevel,
  normalizeRiskTag,
  syncRecordLabels,
  todayDate,
  triggersBlacklistHint,
} from './utils/riskTagStore';
import { canApplyRiskTagByName, canBatchTag, canAddRiskTags, canApproveRiskTag, canRemoveRiskTag, MOCK_USERS, roleLabel } from './utils/permissions';
import annotationSourceDocument from './annotation-source.json';

const DEFAULT_PAGE_SIZE = 10;

type NavigationRef = {
  openCreate?: () => void;
  backToList?: () => void;
};

function validateCreateForm(form: CustomerCreateForm): string | null {
  if (!form.customerType) return '请选择客户类型';
  if (!form.customerName.trim()) return '请输入客户全称';
  if (!form.address.trim()) return '请填写通讯地址';
  if (!form.cityProvince || !form.cityName) return '请填写通讯地址以识别所属城市';
  if (!form.department) return '请选择业务负责部门';
  if (!form.manager) return '请选择业务负责人员';
  if (!form.invoiceTitle.trim()) return '请填写发票抬头';
  if (!form.taxId.trim()) return '请输入纳税人识别号';
  if (!form.bankName.trim()) return '请输入开户银行';
  return null;
}

export default function CustomerManagementApp() {
  const seedRecords = seedCustomers as CustomerRecord[];
  const initialRiskTags = useMemo(() => buildSeedRiskTags(seedRecords), []);

  const [records, setRecords] = useState<CustomerRecord[]>(() =>
    syncRecordLabels(seedRecords, initialRiskTags),
  );
  const [riskTagsByCustomer, setRiskTagsByCustomer] = useState<Record<string, CustomerRiskTag[]>>(initialRiskTags);
  const [operationLogs, setOperationLogs] = useState(INITIAL_OPERATION_LOGS);
  const [currentUser, setCurrentUser] = useState<MockUser>(MOCK_USERS[1]);

  const [view, setView] = useState<CustomerPageId>('list');
  const [pendingFilters, setPendingFilters] = useState<CustomerFilters>(EMPTY_FILTERS);
  const [appliedFilters, setAppliedFilters] = useState<CustomerFilters>(EMPTY_FILTERS);
  const [riskKpiTab, setRiskKpiTab] = useState<CustomerRiskKpiKey>('all');
  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(DEFAULT_PAGE_SIZE);
  const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
  const [createForm, setCreateForm] = useState<CustomerCreateForm>(EMPTY_CREATE_FORM);
  const [toast, setToast] = useState('');
  const [tagDrawerRecord, setTagDrawerRecord] = useState<CustomerRecord | null>(null);
  const [batchTagOpen, setBatchTagOpen] = useState(false);
  const navigationRef = useRef<NavigationRef>({});

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

  const refreshRecordLabels = useCallback((nextTags: Record<string, CustomerRiskTag[]>) => {
    setRecords((prev) => syncRecordLabels(prev, nextTags));
  }, []);

  navigationRef.current = {
    openCreate: () => {
      setCreateForm(EMPTY_CREATE_FORM);
      setView('create');
    },
    backToList: () => setView('list'),
  };

  const kpiCounts = useMemo(() => ({
    all: countRiskKpi(records, riskTagsByCustomer, 'all'),
    withRisk: countRiskKpi(records, riskTagsByCustomer, 'withRisk'),
    finance: countRiskKpi(records, riskTagsByCustomer, 'finance'),
    legal: countRiskKpi(records, riskTagsByCustomer, 'legal'),
    business: countRiskKpi(records, riskTagsByCustomer, 'business'),
  }), [records, riskTagsByCustomer]);

  const filtered = useMemo(
    () => applyFilters(records, appliedFilters, riskTagsByCustomer, riskKpiTab),
    [records, appliedFilters, riskTagsByCustomer, riskKpiTab],
  );

  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 handleSearch = () => {
    setAppliedFilters(pendingFilters);
    setPage(1);
    setSelectedIds(new Set());
  };

  const handleReset = () => {
    setPendingFilters(EMPTY_FILTERS);
    setAppliedFilters(EMPTY_FILTERS);
    setRiskKpiTab('all');
    setPage(1);
    setSelectedIds(new Set());
  };

  const handlePageSizeChange = (size: number) => {
    setPageSize(size);
    setPage(1);
  };

  const handleToggleRow = (id: string, checked: boolean) => {
    setSelectedIds((prev) => {
      const next = new Set(prev);
      if (checked) next.add(id);
      else next.delete(id);
      return next;
    });
  };

  const handleToggleAll = (checked: boolean) => {
    if (!checked) {
      setSelectedIds(new Set());
      return;
    }
    setSelectedIds(new Set(paged.map((record) => record.id)));
  };

  const handleOpenCreate = () => {
    setCreateForm(EMPTY_CREATE_FORM);
    setView('create');
  };

  const handleSubmitCreate = () => {
    const error = validateCreateForm(createForm);
    if (error) {
      showToast(error);
      return;
    }
    showToast('客户已保存（原型演示）');
    setView('list');
  };

  const appendTagsForCustomer = useCallback((
    customerId: string,
    customerName: string,
    form: RiskTagApplyForm,
    batchCount?: number,
  ) => {
    if (!canAddRiskTags(currentUser)) return '当前角色无打标权限';

    const tag = buildApplyTag(customerId, {
      ...form,
      effectiveDate: form.effectiveDate || todayDate(),
    }, currentUser);
    if (!tag) return '标签不存在或无效';

    setRiskTagsByCustomer((prev) => {
      const next = {
        ...prev,
        [customerId]: [...(prev[customerId] ?? []), tag],
      };
      refreshRecordLabels(next);
      return next;
    });

    setOperationLogs((prev) => [
      buildApplyLog(tag, customerName, currentUser, batchCount),
      ...prev,
    ]);

    return null;
  }, [currentUser, refreshRecordLabels]);

  const handleApplyTag = useCallback((form: RiskTagApplyForm): string | null => {
    if (!tagDrawerRecord) return '未选择客户';
    if (!canApplyRiskTagByName(currentUser, form.tagName)) return '当前角色无权选择该标签';
    const result = appendTagsForCustomer(tagDrawerRecord.id, tagDrawerRecord.name, form);
    if (!result) {
      const blacklist = triggersBlacklistHint(form.tagName);
      if (isHighRiskLevel(form.riskLevel)) {
        showToast(blacklist
          ? '已提交审批；该标签可能触发黑名单审批'
          : '已提交审批，待法务/风控/管理层确认');
      } else {
        showToast('标签已生效');
      }
    }
    return result;
  }, [appendTagsForCustomer, currentUser, showToast, tagDrawerRecord]);

  const handleBatchApply = useCallback((form: RiskTagApplyForm, customerIds: string[]): string | null => {
    if (!canBatchTag(currentUser)) return '当前角色无批量打标权限';

    const newLogs = [...operationLogs];
    const nextTags = { ...riskTagsByCustomer };

    customerIds.forEach((customerId) => {
      const record = records.find((item) => item.id === customerId);
      if (!record) return;

      const tag = buildApplyTag(customerId, {
        ...form,
        effectiveDate: form.effectiveDate || todayDate(),
      }, currentUser);
      if (!tag) return;

      nextTags[customerId] = [...(nextTags[customerId] ?? []), tag];
      newLogs.unshift(buildApplyLog(tag, record.name, currentUser, customerIds.length));
    });

    setRiskTagsByCustomer(nextTags);
    refreshRecordLabels(nextTags);
    setOperationLogs(newLogs);
    showToast(`已为 ${customerIds.length} 个客户提交打标`);
    setSelectedIds(new Set());
    return null;
  }, [currentUser, operationLogs, records, refreshRecordLabels, riskTagsByCustomer, showToast]);

  const handleRemoveTag = useCallback((tagId: string, reason: string, isApplication = true): string | null => {
    if (!tagDrawerRecord) return '未选择客户';
    const tags = riskTagsByCustomer[tagDrawerRecord.id] ?? [];
    const target = tags.find((tag) => tag.id === tagId);
    if (!target) return '标签不存在';
    if (!canRemoveRiskTag(currentUser, target.tagCategory)) return '当前角色无权移除此类型标签';

    if (isApplication) {
      setRiskTagsByCustomer((prev) => {
        const nextTags = (prev[tagDrawerRecord.id] ?? []).map((tag) =>
          tag.id === tagId
            ? { ...tag, removalRequested: true, removeReason: reason }
            : tag,
        );
        return { ...prev, [tagDrawerRecord.id]: nextTags };
      });
      setOperationLogs((prev) => [
        buildRemoveLog(target, tagDrawerRecord.name, currentUser, reason, true),
        ...prev,
      ]);
      showToast('解除申请已提交，待审批');
      return null;
    }

    setRiskTagsByCustomer((prev) => {
      const nextTags = (prev[tagDrawerRecord.id] ?? []).map((tag) =>
        tag.id === tagId
          ? { ...tag, status: 'removed' as const, statusName: '已解除' }
          : tag,
      );
      const next = { ...prev, [tagDrawerRecord.id]: nextTags };
      refreshRecordLabels(next);
      return next;
    });

    setOperationLogs((prev) => [
      buildRemoveLog(
        { ...target, status: 'removed', statusName: '已解除' },
        tagDrawerRecord.name,
        currentUser,
        reason,
      ),
      ...prev,
    ]);
    showToast('标签已解除');
    return null;
  }, [currentUser, refreshRecordLabels, riskTagsByCustomer, showToast, tagDrawerRecord]);

  const legalTodoDispatchedRef = useRef(new Set<string>());

  const handleDispatchLegalTodos = useCallback((
    customerId: string,
    customerName: string,
    overdueTags: CustomerRiskTag[],
  ) => {
    const pending = overdueTags.filter((tag) => {
      const key = `${customerId}:${tag.id}`;
      if (legalTodoDispatchedRef.current.has(key)) return false;
      legalTodoDispatchedRef.current.add(key);
      return true;
    });
    if (pending.length === 0) return;

    setOperationLogs((prev) => [
      ...pending.map((tag) => buildWorkbenchTodoLog(tag, customerName)),
      ...prev,
    ]);
    showToast(`已向法务工作台推送 ${pending.length} 条复核待办（原型演示）`);
  }, [showToast]);

  const handleApproveTag = useCallback((tagId: string, approved: boolean, rejectReason?: string): string | null => {
    if (!tagDrawerRecord) return '未选择客户';
    if (!canApproveRiskTag(currentUser)) return '当前角色无审批权限';

    const tags = riskTagsByCustomer[tagDrawerRecord.id] ?? [];
    const target = tags.find((tag) => tag.id === tagId);
    if (!target) return '标签不存在';

    const isRemovalApproval = target.status === 'active' && target.removalRequested;
    const isAddApproval = target.status === 'pending';
    if (!isRemovalApproval && !isAddApproval) return '标签不可审批';

    const now = formatNow();

    if (isRemovalApproval) {
      setRiskTagsByCustomer((prev) => {
        const nextTags = (prev[tagDrawerRecord.id] ?? []).map((tag) => {
          if (tag.id !== tagId) return tag;
          if (approved) {
            return normalizeRiskTag({
              ...tag,
              status: 'removed' as const,
              statusName: '已解除',
              removalRequested: false,
              removedAt: now,
              removeReason: tag.removeReason ?? rejectReason,
              approvedBy: currentUser.name,
              approvedAt: now,
            });
          }
          return {
            ...tag,
            removalRequested: false,
            approvedBy: currentUser.name,
            approvedAt: now,
            rejectReason,
          };
        });
        const next = { ...prev, [tagDrawerRecord.id]: nextTags };
        refreshRecordLabels(next);
        return next;
      });

      setOperationLogs((prev) => [
        buildRemovalApprovalLog(
          { ...target, status: approved ? 'removed' : 'active', statusName: approved ? '已解除' : '生效中' },
          tagDrawerRecord.name,
          currentUser,
          approved,
          rejectReason,
        ),
        ...prev,
      ]);
      showToast(approved ? '解除申请已通过，标签已解除' : '已驳回解除申请');
      return null;
    }

    setRiskTagsByCustomer((prev) => {
      const nextTags = (prev[tagDrawerRecord.id] ?? []).map((tag) => {
        if (tag.id !== tagId) return tag;
        return approved
          ? {
              ...tag,
              status: 'active' as const,
              statusName: '生效中',
              approvedBy: currentUser.name,
              approvedAt: now,
            }
          : {
              ...tag,
              status: 'rejected' as const,
              statusName: '已驳回',
              approvedBy: currentUser.name,
              approvedAt: now,
              rejectReason,
            };
      });
      const next = { ...prev, [tagDrawerRecord.id]: nextTags };
      refreshRecordLabels(next);
      return next;
    });

    setOperationLogs((prev) => [
      buildApprovalLog(
        { ...target, status: approved ? 'active' : 'rejected', statusName: approved ? '生效中' : '已驳回' },
        tagDrawerRecord.name,
        currentUser,
        approved,
        rejectReason,
      ),
      ...prev,
    ]);
    showToast(approved ? '审批通过，标签已生效' : '已驳回该标签');
    return null;
  }, [currentUser, refreshRecordLabels, riskTagsByCustomer, showToast, tagDrawerRecord]);

  const handleDirectoryRoute = useCallback((node: AnnotationDirectoryRouteNode) => {
    const payload = node.payload as { pageId?: string } | undefined;
    const pageId: CustomerPageId = payload?.pageId === 'create' ? 'create' : 'list';
    if (pageId === 'create') {
      navigationRef.current.openCreate?.();
    } else {
      navigationRef.current.backToList?.();
    }
  }, []);

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

  const drawerTags = tagDrawerRecord ? (riskTagsByCustomer[tagDrawerRecord.id] ?? []) : [];

  return (
    <>
      <div className="vm-page cm-page">
        {view === 'create' ? (
          <CreatePage
            form={createForm}
            onChange={(patch) => setCreateForm((prev) => ({ ...prev, ...patch }))}
            onReset={() => setCreateForm(EMPTY_CREATE_FORM)}
            onSubmit={handleSubmitCreate}
            onBack={() => setView('list')}
          />
        ) : (
          <>

            <div className="cm-role-bar" data-annotation-id="cm-risk-role-switch">
              <span className="cm-role-bar-label">当前操作角色（原型演示）：</span>
              <select
                className="vm-input cm-role-select"
                value={currentUser.role}
                onChange={(e) => {
                  const user = MOCK_USERS.find((item) => item.role === e.target.value);
                  if (user) setCurrentUser(user);
                }}
              >
                {MOCK_USERS.map((user) => (
                  <option key={user.role} value={user.role}>
                    {roleLabel(user.role)} · {user.department}
                  </option>
                ))}
              </select>
              {!canAddRiskTags(currentUser) && (
                <span className="cm-role-hint">当前角色仅可查看，不可新增或解除标签</span>
              )}
            </div>

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

            <RiskKpiCards
              counts={kpiCounts}
              active={riskKpiTab}
              onChange={(key) => { setRiskKpiTab(key); setPage(1); setSelectedIds(new Set()); }}
            />

            <section className="vm-table-section">
              <div className="vm-table-toolbar" data-annotation-id="cm-list-toolbar">
                <div className="vm-table-actions">
                  <button type="button" className="vm-btn vm-btn-primary ldb-toolbar-btn" onClick={handleOpenCreate} data-vm-icon="plus">新增客户
                  </button>
                  <button
                    type="button"
                    className="vm-btn vm-btn-secondary ldb-toolbar-btn"
                    data-vm-icon="import"
                    onClick={() => showToast('批量导入（原型演示）')}
                  >
                    批量导入
                  </button>
                  {canBatchTag(currentUser) && selectedIds.size > 0 && (
                    <button
                      type="button"
                      className="vm-btn vm-btn-secondary ldb-toolbar-btn"
                      data-vm-icon="plus"
                      onClick={() => setBatchTagOpen(true)}
                      data-annotation-id="cm-batch-risk-tag-btn"
                    >
                      批量打标（{selectedIds.size}）
                    </button>
                  )}
                </div>
                <button
                  type="button"
                  className="vm-btn vm-btn-ghost ldb-toolbar-btn"
                  data-vm-icon="download"
                  onClick={() => showToast(`批量导出（原型演示）：当前列表共 ${filtered.length} 条`)}
                >
                  批量导出
                </button>
              </div>

              <div className="vm-table-card">
                <CustomerTable
                  records={paged}
                  selectedIds={selectedIds}
                  riskTagsByCustomer={riskTagsByCustomer}
                  currentUser={currentUser}
                  onToggleRow={handleToggleRow}
                  onToggleAll={handleToggleAll}
                  onView={(record) => showToast(`详情：${record.name}（原型演示）`)}
                  onEdit={(record) => showToast(`编辑：${record.name}（原型演示）`)}
                  onDelete={(record) => showToast(`删除：${record.name}（原型演示）`)}
                  onManageTags={setTagDrawerRecord}
                />
                <div className="vm-table-footer">
                  <TablePagination
                    page={Math.min(page, totalPages)}
                    pageSize={pageSize}
                    total={filtered.length}
                    onPageChange={setPage}
                    onPageSizeChange={handlePageSizeChange}
                  />
                </div>
              </div>
            </section>
          </>
        )}

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

      <RiskTagDrawer
        open={!!tagDrawerRecord}
        record={tagDrawerRecord}
        tags={drawerTags}
        logs={operationLogs}
        currentUser={currentUser}
        onClose={() => setTagDrawerRecord(null)}
        onApply={handleApplyTag}
        onRemove={handleRemoveTag}
        onApprove={handleApproveTag}
        onDispatchLegalTodos={handleDispatchLegalTodos}
      />

      <BatchRiskTagModal
        open={batchTagOpen}
        records={records}
        selectedIds={selectedIds}
        riskTagsByCustomer={riskTagsByCustomer}
        currentUser={currentUser}
        onClose={() => setBatchTagOpen(false)}
        onSubmit={handleBatchApply}
      />

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