import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { IconChevronRight, IconDelete, IconPlus, IconRefresh, IconSearch } from '@douyinfe/semi-icons';
import { Avatar, Button, Card, Checkbox, Collapse, Empty, Input, List, Select, SideSheet, Spin, Switch, Tabs, Tag, Typography } from '@douyinfe/semi-ui';
import { FormEvent, useDeferredValue, useEffect, useMemo, useState } from 'react';
import { api } from '../../api/client';
import type { AdminUser, CustomerUserInput, CustomerVehicleGrantInput } from '../../api/types';
import { useMobileLayout } from '../hooks/useMobileLayout';
import { useSideSheetA11y } from '../hooks/useSideSheetA11y';
import { TablePagination } from '../shared/TablePagination';
import { VehicleCandidateList } from '../shared/VehicleCandidateList';
import { WorkspaceFilterPanel } from '../shared/WorkspaceFilterPanel';
import { WorkspaceCommandBar } from '../shared/WorkspaceCommandBar';
import { WorkspacePanelHeader } from '../shared/WorkspacePanelHeader';
import { mergeVehicleCandidates } from '../shared/vehicleCandidates';
import { PanelEmpty, PanelLoading } from '../shared/AsyncState';

const customerMenus = [
  { key: 'monitor', label: '全局监控', description: '查看授权车辆的实时位置与状态' },
  { key: 'vehicles', label: '车辆查询', description: '查看车辆档案与最新遥测' },
  { key: 'tracks', label: '轨迹回放', description: '查询授权车辆的历史轨迹' },
  { key: 'statistics', label: '里程查询', description: '查询授权车辆的每日与区间里程' }
];

type Draft = {
  username: string;
  displayName: string;
  password: string;
  status: 'enabled' | 'disabled';
  customerRef: string;
  tenantRef: string;
  menuKeys: string[];
  vehicleGrants: CustomerVehicleGrantInput[];
};

type EditorSection = 'identity' | 'menus' | 'vehicles';

const shanghaiDateTimeFormatter = new Intl.DateTimeFormat('sv-SE', {
  timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', hour12: false
});

function dateTimeInput(value?: string) {
  if (!value) return '';
  const parsed = new Date(value);
  if (Number.isNaN(parsed.getTime())) return '';
  return shanghaiDateTimeFormatter.format(parsed).replace(' ', 'T');
}

const emptyDraft: Draft = { username: '', displayName: '', password: '', status: 'enabled', customerRef: '', tenantRef: '', menuKeys: ['monitor', 'vehicles', 'tracks', 'statistics'], vehicleGrants: [] };

function draftFromUser(user?: AdminUser): Draft {
  if (!user) return { ...emptyDraft, menuKeys: [...emptyDraft.menuKeys], vehicleGrants: [] };
  return {
    username: user.username, displayName: user.displayName, password: '', status: user.status,
    customerRef: user.customerRef, tenantRef: user.tenantRef, menuKeys: [...user.menuKeys],
    vehicleGrants: user.vehicles.map((vehicle) => ({ vin: vehicle.vin, validFrom: dateTimeInput(vehicle.validFrom), validTo: dateTimeInput(vehicle.validTo) }))
  };
}

function formatTime(value?: string) {
  if (!value) return '尚未登录';
  return new Date(value).toLocaleString('zh-CN', { hour12: false });
}

function formatGrantTime(value?: string) {
  if (!value) return '未设置';
  return value.replace('T', ' ').slice(0, 16);
}

export default function UsersPage() {
  const queryClient = useQueryClient();
  const mobileLayout = useMobileLayout();
  const users = useQuery({ queryKey: ['admin-users'], queryFn: ({ signal }) => api.adminUsers(signal), staleTime: 10_000 });
  const customers = useMemo(() => (users.data ?? []).filter((user) => user.userType === 'customer'), [users.data]);
  const [customerKeyword, setCustomerKeyword] = useState('');
  const deferredCustomerKeyword = useDeferredValue(customerKeyword.trim());
  const [customerStatus, setCustomerStatus] = useState<'all' | Draft['status']>('all');
  const [filtersCollapsed, setFiltersCollapsed] = useState(true);
  const visibleCustomers = useMemo(() => {
    const keyword = deferredCustomerKeyword.toLocaleLowerCase('zh-CN');
    return customers.filter((user) => {
      if (customerStatus !== 'all' && user.status !== customerStatus) return false;
      if (!keyword) return true;
      return [user.displayName, user.username, user.customerRef, user.tenantRef]
        .some((value) => value?.toLocaleLowerCase('zh-CN').includes(keyword));
    });
  }, [customerStatus, customers, deferredCustomerKeyword]);
  const [selectedID, setSelectedID] = useState<number | null>(null);
  const [creating, setCreating] = useState(false);
  const [activeSection, setActiveSection] = useState<EditorSection>('identity');
  const selected = useMemo(() => customers.find((user) => user.id === selectedID), [customers, selectedID]);
  const [draft, setDraft] = useState<Draft>(() => draftFromUser());
  const [vehicleKeyword, setVehicleKeyword] = useState('');
  const deferredVehicleKeyword = useDeferredValue(vehicleKeyword.trim());
  const [assignedKeyword, setAssignedKeyword] = useState('');
  const [assignedPage, setAssignedPage] = useState(1);
  const [bulkVINs, setBulkVINs] = useState('');
  const [vehicleLabels, setVehicleLabels] = useState<Record<string, string>>({});
  const [feedback, setFeedback] = useState('');
  const [editingGrantVIN, setEditingGrantVIN] = useState('');
  const enabledCustomers = useMemo(() => visibleCustomers.filter((user) => user.status === 'enabled').length, [visibleCustomers]);
  const grantedVehicles = useMemo(() => visibleCustomers.reduce((total, user) => total + user.vehicles.length, 0), [visibleCustomers]);
  const editingGrant = useMemo(() => draft.vehicleGrants.find((grant) => grant.vin === editingGrantVIN), [draft.vehicleGrants, editingGrantVIN]);
  const editingGrantPlate = editingGrant ? vehicleLabels[editingGrant.vin] : '';
  const grantWindowInvalid = Boolean(editingGrant && (!editingGrant.validFrom || (editingGrant.validTo && editingGrant.validTo <= editingGrant.validFrom)));
  const editorVisible = creating || Boolean(selected);
  useSideSheetA11y(editorVisible, '.v2-user-editor-sidesheet', 'v2-user-editor-sheet', '客户账号详情', '关闭账号详情');
  useSideSheetA11y(Boolean(editingGrant), '.v2-user-grant-sidesheet', 'v2-user-grant-window', '车辆授权有效期', '关闭车辆授权有效期');

  useEffect(() => {
    if (!creating && selected) {
      setDraft(draftFromUser(selected));
      setVehicleLabels(Object.fromEntries(selected.vehicles.map((vehicle) => [vehicle.vin, vehicle.plate])));
    }
  }, [creating, selected]);

  const candidates = useQuery({
    queryKey: ['permission-vehicle-candidates', deferredVehicleKeyword],
    queryFn: ({ signal }) => api.vehicleCoverage(new URLSearchParams({ keyword: deferredVehicleKeyword, limit: '20', offset: '0' }), signal),
    enabled: deferredVehicleKeyword.length >= 1,
    staleTime: 30_000
  });
  const assigned = useMemo(() => new Set(draft.vehicleGrants.map((grant) => grant.vin)), [draft.vehicleGrants]);
  const candidateVehicles = useMemo(() => mergeVehicleCandidates(candidates.data?.items ?? []), [candidates.data?.items]);
  const assignedPageSize = mobileLayout ? 4 : 10;
  const filteredAssignedGrants = useMemo(() => {
    const keyword = assignedKeyword.trim().toLocaleLowerCase('zh-CN');
    if (!keyword) return draft.vehicleGrants;
    return draft.vehicleGrants.filter((grant) => [grant.vin, vehicleLabels[grant.vin]]
      .some((value) => value?.toLocaleLowerCase('zh-CN').includes(keyword)));
  }, [assignedKeyword, draft.vehicleGrants, vehicleLabels]);
  const assignedTotalPages = Math.max(1, Math.ceil(filteredAssignedGrants.length / assignedPageSize));
  const safeAssignedPage = Math.min(assignedPage, assignedTotalPages);
  const visibleAssignedGrants = useMemo(() => {
    const offset = (safeAssignedPage - 1) * assignedPageSize;
    return filteredAssignedGrants.slice(offset, offset + assignedPageSize);
  }, [assignedPageSize, filteredAssignedGrants, safeAssignedPage]);
  useEffect(() => {
    if (candidateVehicles.length === 0) return;
    setVehicleLabels((current) => {
      const next = { ...current };
      for (const vehicle of candidateVehicles) next[vehicle.vin] = vehicle.plate;
      return next;
    });
  }, [candidateVehicles]);

  const save = useMutation({
    mutationFn: async () => {
      const input: CustomerUserInput = {
        displayName: draft.displayName.trim(), password: draft.password || undefined, status: draft.status,
        customerRef: draft.customerRef.trim(), tenantRef: draft.tenantRef.trim(), menuKeys: draft.menuKeys,
        vehicleVins: draft.vehicleGrants.map((grant) => grant.vin), vehicleGrants: draft.vehicleGrants
      };
      if (creating) return api.createCustomerUser({ ...input, username: draft.username.trim(), password: draft.password });
      if (!selected) throw new Error('请先选择客户账号');
      return api.updateCustomerUser(selected.id, input);
    },
    onSuccess: async (result) => {
      setFeedback(creating ? '客户账号已创建' : '账号与权限已更新');
      setCreating(false);
      setSelectedID(result.id);
      setDraft((value) => ({ ...value, password: '' }));
      await queryClient.invalidateQueries({ queryKey: ['admin-users'] });
    },
    onError: (error) => setFeedback(error instanceof Error ? error.message : '保存失败')
  });

  const startCreate = () => {
    setCreating(true);
    setSelectedID(null);
    setActiveSection('identity');
    setDraft(draftFromUser());
    setVehicleKeyword('');
    setAssignedKeyword('');
    setAssignedPage(1);
    setBulkVINs('');
    setVehicleLabels({});
    setFeedback('');
    setEditingGrantVIN('');
  };
  const closeEditor = () => {
    setCreating(false);
    setSelectedID(null);
    setDraft(draftFromUser());
    setVehicleKeyword('');
    setAssignedKeyword('');
    setAssignedPage(1);
    setBulkVINs('');
    setVehicleLabels({});
    setFeedback('');
    setEditingGrantVIN('');
  };
  const selectCustomer = (user: AdminUser) => {
    setCreating(false);
    setSelectedID(user.id);
    setActiveSection('vehicles');
    setDraft(draftFromUser(user));
    setVehicleKeyword('');
    setAssignedKeyword('');
    setAssignedPage(1);
    setBulkVINs('');
    setFeedback('');
    setEditingGrantVIN('');
  };
  const toggleVIN = (vin: string) => {
    if (!assigned.has(vin)) {
      setAssignedKeyword('');
      setAssignedPage(1);
    }
    setDraft((value) => ({
      ...value,
      vehicleGrants: value.vehicleGrants.some((grant) => grant.vin === vin)
        ? value.vehicleGrants.filter((grant) => grant.vin !== vin)
        : [...value.vehicleGrants, { vin, validFrom: dateTimeInput(new Date().toISOString()), validTo: '' }].sort((left, right) => left.vin.localeCompare(right.vin))
    }));
    if (editingGrantVIN === vin) setEditingGrantVIN('');
  };
  const updateGrant = (vin: string, patch: Partial<CustomerVehicleGrantInput>) => setDraft((value) => ({
    ...value, vehicleGrants: value.vehicleGrants.map((grant) => grant.vin === vin ? { ...grant, ...patch } : grant)
  }));
  const addBulkVINs = () => {
    const next = bulkVINs.split(/[\s,，;；]+/).map((value) => value.trim().toUpperCase()).filter(Boolean);
    setDraft((value) => {
      const existing = new Set(value.vehicleGrants.map((grant) => grant.vin));
      const added = next.filter((vin) => !existing.has(vin)).map((vin) => ({ vin, validFrom: dateTimeInput(new Date().toISOString()), validTo: '' }));
      return { ...value, vehicleGrants: [...value.vehicleGrants, ...added].sort((left, right) => left.vin.localeCompare(right.vin)) };
    });
    setAssignedKeyword('');
    setAssignedPage(1);
    setBulkVINs('');
  };
  const persistDraft = () => {
    if (save.isPending) return;
    setFeedback('');
    if (!draft.displayName.trim() || (creating && (!draft.username.trim() || !draft.password))) {
      setActiveSection('identity');
      setFeedback('请先完善登录身份中的必填信息');
      return;
    }
    const invalidGrant = draft.vehicleGrants.find((grant) => !grant.validFrom || (grant.validTo && grant.validTo <= grant.validFrom));
    if (invalidGrant) {
      setActiveSection('vehicles');
      setEditingGrantVIN(invalidGrant.vin);
      setFeedback('请检查车辆授权有效期：停用时间必须晚于启用时间');
      return;
    }
    save.mutate();
  };
  const submit = (event: FormEvent) => {
    event.preventDefault();
    persistDraft();
  };

  return <div className="v2-user-admin">
    <WorkspaceCommandBar
      className="v2-user-command-bar"
      ariaLabel="账号管理操作"
      title="客户访问治理"
      description="菜单与车辆按最小权限开放，变更最多 30 秒生效"
      status={`${customers.length} 个客户账号`}
      meta={<Typography.Text type="tertiary">本地账号 · 可扩展外部身份源</Typography.Text>}
      actions={<Button theme="solid" icon={<IconPlus />} aria-label="新建客户账号" onClick={startCreate}>新建客户账号</Button>}
    />
    <WorkspaceFilterPanel
      className="v2-user-filter-panel"
      title="账号范围"
      description="按客户名称、登录账号、客户标识与启停状态查找"
      mobileSummary={`${customerStatus === 'all' ? '全部状态' : customerStatus === 'enabled' ? '启用账号' : '停用账号'}${customerKeyword.trim() ? ` · ${customerKeyword.trim()}` : ''}`}
      expanded={!filtersCollapsed}
      status={users.isPending ? '正在读取账号' : `${visibleCustomers.length} / ${customers.length} 个账号`}
      statusColor={customerKeyword.trim() || customerStatus !== 'all' ? 'blue' : 'grey'}
      collapsedLabel="修改"
      onToggle={() => setFiltersCollapsed((value) => !value)}
    >
      <div className={`v2-user-filter-form${filtersCollapsed ? ' is-mobile-collapsed' : ''}`}>
        <label className="v2-user-filter-keyword">
          <span>客户账号</span>
          <Input className="v2-user-list-search" aria-label="搜索客户账号" prefix={<IconSearch />} showClear value={customerKeyword} onChange={setCustomerKeyword} placeholder="搜索名称、账号或客户标识" />
        </label>
        <label>
          <span id="v2-user-status-filter-label">账号状态</span>
          <Select
            aria-labelledby="v2-user-status-filter-label"
            value={customerStatus}
            onChange={(value) => setCustomerStatus(String(value) as typeof customerStatus)}
            optionList={[
              { value: 'all', label: '全部状态' },
              { value: 'enabled', label: '启用账号' },
              { value: 'disabled', label: '停用账号' }
            ]}
          />
        </label>
        <Button
          className="v2-user-filter-reset"
          theme="light"
          type="tertiary"
          icon={<IconRefresh />}
          aria-label="清空账号筛选"
          disabled={!customerKeyword.trim() && customerStatus === 'all'}
          onClick={() => {
            setCustomerKeyword('');
            setCustomerStatus('all');
          }}
        >
          清空
        </Button>
      </div>
    </WorkspaceFilterPanel>
    <div className={`v2-user-admin-grid${creating || selected ? ' is-editor-open' : ''}`}>
      <Card className="v2-user-list" bodyStyle={{ padding: 0 }}>
        <WorkspacePanelHeader
          className="v2-user-directory-header"
          title="客户权限目录"
          description="当前范围内的账号、菜单与车辆授权摘要"
          meta={<Tag color={visibleCustomers.length === customers.length ? 'grey' : 'blue'} type="light" size="small">{visibleCustomers.length} / {customers.length} 个账号</Tag>}
        />
        <div className="v2-user-directory-body">
          <div className="v2-user-directory-metrics" aria-label="客户账号概览">
            <span className="is-primary"><small>启用账号</small><strong>{enabledCustomers}</strong></span>
            <span><small>停用账号</small><strong>{customers.length - enabledCustomers}</strong></span>
            <span><small>车辆授权</small><strong>{grantedVehicles}</strong></span>
          </div>
          {users.isPending ? <PanelLoading className="v2-user-list-loading" title="正在加载客户账号" description="账号目录和授权摘要就绪后会自动显示。" /> : customers.length === 0 ? <PanelEmpty className="v2-user-list-empty" title="还没有客户账号" description="创建客户账号后，可在这里配置菜单和车辆范围。" action={<Button theme="solid" onClick={startCreate}>创建第一个客户账号</Button>} /> : <>
            <div className="v2-customer-list-scroll" role="region" aria-label="客户账号目录，可上下滚动" tabIndex={0}>
              <List
                className="v2-customer-list"
                dataSource={visibleCustomers}
                emptyContent={<Empty className="v2-user-filter-empty" title="没有匹配账号" description="请更换名称或账号关键词。" />}
                renderItem={(user) => <List.Item key={user.id} className={`v2-user-list-row${selectedID === user.id && !creating ? ' is-active' : ''}`}>
                  <Button
                    className="v2-user-list-item"
                    theme="borderless"
                    type="tertiary"
                    aria-label={`选择客户 ${user.displayName}，账号 ${user.username}，${user.vehicles.length} 辆授权车`}
                    aria-pressed={selectedID === user.id && !creating}
                    aria-expanded={selectedID === user.id && !creating}
                    onClick={() => selectCustomer(user)}
                  >
                    <Avatar className="v2-user-avatar" color={user.status === 'enabled' ? 'light-blue' : 'grey'} shape="square" size="small">{user.displayName.slice(0, 1)}</Avatar>
                    <span className="v2-user-list-identity"><b>{user.displayName}</b><small>@{user.username}</small></span>
                    <span className="v2-user-list-facts"><small>菜单权限</small><b>{user.menuKeys.length} 项</b></span>
                    <span className="v2-user-list-facts"><small>车辆权限</small><b>{user.vehicles.length} 辆</b></span>
                    <span className="v2-user-list-facts is-login"><small>最近登录</small><b>{formatTime(user.lastLoginAt)}</b></span>
                    <span className="v2-user-list-trailing"><Tag className={`v2-user-status-tag is-${user.status}`} color={user.status === 'enabled' ? 'green' : 'grey'} type="light" size="small">{user.status === 'enabled' ? '启用' : '停用'}</Tag><IconChevronRight /></span>
                  </Button>
                </List.Item>}
              />
            </div>
          </>}
        </div>
      </Card>
    </div>
    <SideSheet
      className="v2-user-editor-sidesheet"
      visible={editorVisible}
      width={mobileLayout ? '100%' : 'min(840px, 100vw)'}
      aria-label="客户账号详情"
      title={<div className="v2-user-editor-sheet-title">
        <span><strong>{creating ? '创建客户账号' : selected?.displayName}</strong><small>{creating ? '设置登录身份和最小必要权限' : `@${selected?.username} · ${draft.menuKeys.length} 个菜单 · ${draft.vehicleGrants.length} 辆车 · 最近登录 ${formatTime(selected?.lastLoginAt)}`}</small></span>
        <label className="v2-user-status"><Switch aria-label={draft.status === 'enabled' ? '账号启用' : '账号停用'} checked={draft.status === 'enabled'} onChange={(checked) => setDraft((value) => ({ ...value, status: checked ? 'enabled' : 'disabled' }))} /><span>{draft.status === 'enabled' ? '账号启用' : '账号停用'}</span></label>
      </div>}
      onCancel={closeEditor}
      footer={<div className="v2-user-editor-sheet-footer">
        <Typography.Text className={`v2-user-feedback${save.isError ? ' is-error' : ''}`} role="status" type={save.isError ? 'danger' : 'tertiary'}>{feedback || '权限变更最多 30 秒生效，保存前请核对车辆有效期'}</Typography.Text>
        <Button theme="solid" htmlType="submit" form="v2-user-editor-form" disabled={save.isPending}>{save.isPending ? '正在保存…' : creating ? '创建账号' : '保存权限'}</Button>
      </div>}
    >
      {editorVisible ? <form id="v2-user-editor-form" className="v2-user-editor-form" onSubmit={submit}>
          <Tabs className="v2-user-editor-tabs" activeKey={activeSection} onChange={(key) => setActiveSection(String(key) as EditorSection)}>
          <Tabs.TabPane tab="登录身份" itemKey="identity">
          <Card className="v2-user-editor-section v2-user-identity-section" title="登录身份" headerLine>
            <div className="v2-user-fields">
            <label><span>用户名</span><Input required disabled={!creating} value={draft.username} onChange={(value) => setDraft((current) => ({ ...current, username: value }))} placeholder="例如 customer-huadong" /></label>
            <label><span>客户名称</span><Input required value={draft.displayName} onChange={(value) => setDraft((current) => ({ ...current, displayName: value }))} placeholder="显示在平台右上角" /></label>
            <label><span>{creating ? '初始密码' : '重置密码（可选）'}</span><Input required={creating} mode="password" autoComplete="new-password" value={draft.password} onChange={(value) => setDraft((current) => ({ ...current, password: value }))} placeholder="至少 10 位，包含三类字符" /></label>
            <label><span>客户标识（可选）</span><Input value={draft.customerRef} onChange={(value) => setDraft((current) => ({ ...current, customerRef: value }))} placeholder="为 OneOS / RuoYi 映射预留" /></label>
            </div>
          </Card>
          </Tabs.TabPane>
          <Tabs.TabPane tab={<span className="v2-user-tab-label">菜单权限<Tag color="blue" type="light" size="small">{draft.menuKeys.length}</Tag></span>} itemKey="menus">
          <Card className="v2-user-editor-section v2-user-menu-section" title={<span className="v2-user-section-title">菜单权限 <Tag color="blue" type="light" size="small">客户开放菜单</Tag></span>} headerLine>
            <div className="v2-menu-permissions">{customerMenus.map((menu) => <label key={menu.key} className={draft.menuKeys.includes(menu.key) ? 'is-selected' : ''}><Checkbox checked={draft.menuKeys.includes(menu.key)} onChange={() => setDraft((value) => ({ ...value, menuKeys: value.menuKeys.includes(menu.key) ? value.menuKeys.filter((item) => item !== menu.key) : [...value.menuKeys, menu.key] }))} /><span><b>{menu.label}</b><small>{menu.description}</small></span></label>)}</div>
          </Card>
          </Tabs.TabPane>
          <Tabs.TabPane tab={<span className="v2-user-tab-label">车辆权限<Tag color={draft.vehicleGrants.length ? 'blue' : 'grey'} type="light" size="small">{draft.vehicleGrants.length}</Tag></span>} itemKey="vehicles">
          <Card className="v2-user-editor-section v2-user-vehicle-section" title={<span className="v2-user-section-title">车辆权限与有效期 <Tag color={draft.vehicleGrants.length ? 'blue' : 'grey'} type="light" size="small">{draft.vehicleGrants.length} 辆</Tag></span>} headerLine headerExtraContent={draft.vehicleGrants.length ? <Button theme="borderless" type="tertiary" size="small" onClick={() => setDraft((value) => ({ ...value, vehicleGrants: [] }))}>清空</Button> : null}>
            <div className="v2-vehicle-permission-tools"><label><span>按车牌或 VIN 搜索</span><Input aria-label="按车牌或 VIN 搜索" value={vehicleKeyword} onChange={setVehicleKeyword} placeholder="输入后显示候选车辆" /></label><label><span>批量粘贴 VIN</span><span className="v2-bulk-vin"><Input value={bulkVINs} onChange={setBulkVINs} placeholder="空格、逗号或换行分隔" /><Button theme="light" disabled={!bulkVINs.trim()} onClick={addBulkVINs}>加入</Button></span></label></div>
            {deferredVehicleKeyword ? <VehicleCandidateList
              className="v2-vehicle-candidates"
              layout="grid"
              items={candidateVehicles}
              loading={candidates.isPending}
              error={candidates.isError ? (candidates.error instanceof Error ? candidates.error.message : '车辆候选加载失败') : undefined}
              onRetry={() => candidates.refetch()}
              selectedVins={assigned}
              selectedLabel="已分配"
              onSelect={(vehicle) => toggleVIN(vehicle.vin)}
            /> : null}
            {draft.vehicleGrants.length ? <>
              <div className="v2-assigned-toolbar">
                <span><strong>已授权车辆</strong><small>{assignedKeyword ? `${filteredAssignedGrants.length} 条匹配结果` : `${draft.vehicleGrants.length} 辆车拥有当前访问权限`}</small></span>
                <Input
                  aria-label="筛选已授权车辆"
                  prefix={<IconSearch />}
                  showClear
                  value={assignedKeyword}
                  onChange={(value) => {
                    setAssignedKeyword(value);
                    setAssignedPage(1);
                  }}
                  placeholder="筛选已授权车牌或 VIN"
                />
              </div>
              {visibleAssignedGrants.length ? <div className="v2-assigned-vins">{visibleAssignedGrants.map((grant) => { const plate = vehicleLabels[grant.vin]; return <Card key={grant.vin} className="v2-assigned-vehicle-card" bodyStyle={{ padding: 0 }}>
                <header><span><b>{plate || '未登记车牌'}</b><small>{grant.vin}</small></span><span className="v2-assigned-vehicle-actions"><Button theme="light" type="tertiary" size="small" aria-haspopup="dialog" aria-controls="v2-user-grant-window" aria-label={`调整 ${plate || grant.vin} 有效期`} onClick={() => setEditingGrantVIN(grant.vin)}>调整有效期</Button><Button theme="borderless" type="tertiary" size="small" aria-label={`移除 ${plate || grant.vin}`} icon={<IconDelete />} onClick={() => toggleVIN(grant.vin)} /></span></header>
                <div className="v2-assigned-vehicle-interval"><span><small>启用</small><strong>{formatGrantTime(grant.validFrom)}</strong></span><i aria-hidden="true">→</i><span><small>停用</small><strong>{grant.validTo ? formatGrantTime(grant.validTo) : '持续有效'}</strong></span></div>
              </Card>; })}</div> : <Empty className="v2-user-assigned-filter-empty" title="没有匹配的授权车辆" description="请更换车牌或 VIN 关键词。" />}
              <div className="v2-assigned-pagination">
                <TablePagination
                  page={safeAssignedPage}
                  totalPages={assignedTotalPages}
                  info={<>第 {(safeAssignedPage - 1) * assignedPageSize + (filteredAssignedGrants.length ? 1 : 0)}–{Math.min(safeAssignedPage * assignedPageSize, filteredAssignedGrants.length)} 条，共 {filteredAssignedGrants.length} 辆</>}
                  onPageChange={setAssignedPage}
                />
              </div>
            </> : <Empty className="v2-user-vehicle-empty" title="尚未分配车辆" description="客户将无法看到任何车辆数据。" />}
            {!creating && selected?.grantHistory?.length ? <Collapse className="v2-grant-history">
              <Collapse.Panel itemKey="grant-history" header={<span className="v2-grant-history-title">历次开放记录 <Tag color="blue" type="light" size="small">{selected.grantHistory.length} 条</Tag></span>}>
                <div className="v2-grant-history-list">{selected.grantHistory.map((item) => <Card key={item.id} className="v2-grant-history-card" bodyStyle={{ padding: 0 }}>
                  <header><span><strong>{item.plate || '未登记车牌'}</strong><small>{item.vin}</small></span><Tag color={item.validTo ? 'grey' : 'green'} type="light" size="small">{item.validTo ? '已结束' : '有效中'}</Tag></header>
                  <p>{formatTime(item.validFrom)} <i>→</i> {item.validTo ? formatTime(item.validTo) : '持续有效'}</p>
                  <small>开通：{item.grantedBy || '—'}{item.revokedBy ? ` · 停用：${item.revokedBy}` : ''} · {item.sourceSystem}</small>
                </Card>)}</div>
              </Collapse.Panel>
            </Collapse> : null}
          </Card>
          </Tabs.TabPane>
          </Tabs>
        </form> : null}
    </SideSheet>
    <SideSheet
      className="v2-user-grant-sidesheet"
      visible={Boolean(editingGrant)}
      width={420}
      aria-label="车辆授权有效期"
      title={<div className="v2-user-grant-sheet-title"><strong>调整车辆有效期</strong><span>{editingGrant ? `${editingGrantPlate || '未登记车牌'} · ${editingGrant.vin}` : '车辆授权时间窗口'}</span></div>}
      onCancel={() => setEditingGrantVIN('')}
      footer={<div className="v2-user-grant-sheet-footer"><Typography.Text type="tertiary">完成后仍需保存账号权限才会生效</Typography.Text><Button theme="solid" disabled={grantWindowInvalid} onClick={() => setEditingGrantVIN('')}>完成</Button></div>}
    >
      {editingGrant ? <div className="v2-user-grant-form">
        <Card className="v2-user-grant-summary" bodyStyle={{ padding: 0 }}>
          <span><small>车牌</small><strong>{editingGrantPlate || '未登记车牌'}</strong></span>
          <span><small>VIN</small><strong>{editingGrant.vin}</strong></span>
        </Card>
        <label><span>启用时间</span><Input aria-label={`${editingGrantPlate || editingGrant.vin} 启用时间`} type="datetime-local" required value={editingGrant.validFrom} onChange={(value) => updateGrant(editingGrant.vin, { validFrom: value })} /></label>
        <label><span>停用时间（可选）</span><Input aria-label={`${editingGrantPlate || editingGrant.vin} 停用时间`} type="datetime-local" min={editingGrant.validFrom} value={editingGrant.validTo} onChange={(value) => updateGrant(editingGrant.vin, { validTo: value })} /></label>
        {grantWindowInvalid ? <p role="alert">请设置启用时间，并确保停用时间晚于启用时间。</p> : <p>不设置停用时间时，车辆授权将持续有效。</p>}
      </div> : null}
    </SideSheet>
  </div>;
}
