import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react';
import { afterEach, expect, test, vi } from 'vitest';
import { MemoryRouter } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import type { VehicleRealtimeRow } from '../../api/types';
import { api } from '../../api/client';
import MonitorPage from './MonitorPage';

const vehicles = [{
  vin: 'LTEST000000000001', plate: '粤A12345', protocols: ['JT808'], primaryProtocol: 'JT808',
  longitude: 113.26, latitude: 23.13, speedKmh: 42, socPercent: 80, totalMileageKm: 1234,
  lastSeen: '2026-07-14T01:00:00Z', online: true, sourceCount: 1, onlineSourceCount: 1
}, {
  vin: 'LTEST000000000002', plate: '粤B67890', protocols: ['JT808'], primaryProtocol: 'JT808',
  longitude: 113.28, latitude: 23.15, speedKmh: 0, socPercent: 72, totalMileageKm: 2234,
  lastSeen: '2026-07-14T01:00:00Z', online: true, sourceCount: 1, onlineSourceCount: 1
}] as VehicleRealtimeRow[];
const monitorMap = { clusters: [], points: [], total: 2 };
const fleetMapRenderSpy = vi.hoisted(() => vi.fn());
const monitorQueryFlags = vi.hoisted(() => ({ isLoading: false, isFetching: false, isPlaceholderData: false }));

vi.mock('../map/FleetMap', () => ({
  FleetMap: ({ selectedVin, onSelectVin }: { selectedVin?: string; onSelectVin?: (vin: string) => void }) => {
    fleetMapRenderSpy(selectedVin);
    return <div data-testid="fleet-map" data-selected-vin={selectedVin ?? ''}>
      <button type="button" onClick={() => onSelectVin?.('LTEST000000000002')}>选择地图车辆</button>
    </div>;
  }
}));

vi.mock('../hooks/useMonitorData', () => ({
  MAX_MONITOR_SEARCH_TERMS: 100,
  MONITOR_REFRESH: { selected: 10_000, fleet: 15_000, summary: 30_000 },
  parseMonitorSearchTerms: (value: string) => Array.from(new Set(value.split(/[\s,，、;；]+/).map((item) => item.trim().toLocaleUpperCase()).filter(Boolean))).slice(0, 100),
  monitorQueryParams: (filters: { keyword: string; protocol: string; status: string }, limit: number) => {
    const params = new URLSearchParams({ limit: String(limit) });
    const terms = Array.from(new Set(filters.keyword.split(/[\s,，、;；]+/).map((item) => item.trim().toLocaleUpperCase()).filter(Boolean))).slice(0, 100);
    if (terms.length === 1) params.set('keyword', terms[0]);
    if (terms.length > 1) params.set('keywords', terms.join(','));
    if (filters.protocol) params.set('protocol', filters.protocol);
    if (filters.status) params.set('status', filters.status);
    return params;
  },
  useMonitorData: () => ({
    summary: { data: { totalVehicles: 2, onlineVehicles: 2, offlineVehicles: 0, drivingVehicles: 1, idleVehicles: 1, frameToday: 10 } },
    vehicles: { data: { items: vehicles, total: 2 }, isError: false, ...monitorQueryFlags },
    map: { data: monitorMap, isPlaceholderData: monitorQueryFlags.isPlaceholderData },
    selectedVehicle: { data: { items: [] } }
  }),
  useMonitorVehicleCard: () => ({ detail: {}, activeAlerts: {}, address: {} })
}));

afterEach(() => {
  cleanup();
  monitorQueryFlags.isLoading = false;
  monitorQueryFlags.isFetching = false;
  monitorQueryFlags.isPlaceholderData = false;
});

test('starts without a selection and supports expand, collapse, reselection, and clear', () => {
  const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  const view = render(<QueryClientProvider client={queryClient}><MemoryRouter><MonitorPage /></MemoryRouter></QueryClientProvider>);
  const workspace = view.container.querySelector('.v2-monitor-workspace')!;
  const firstVehicle = screen.getByRole('button', { name: /粤A12345 LTEST000000000001/ });
  const secondVehicle = screen.getByRole('button', { name: /粤B67890 LTEST000000000002/ });

  expect(workspace).not.toHaveClass('is-detail-open');
  expect(workspace).not.toHaveClass('is-detail-collapsed');
  expect(firstVehicle).not.toHaveClass('is-selected');
  expect(screen.queryByRole('button', { name: '取消选择车辆' })).not.toBeInTheDocument();
  expect(screen.getByTestId('fleet-map')).toHaveAttribute('data-selected-vin', '');
  expect(screen.getByText('有实时位置')).toBeInTheDocument();
  expect(screen.queryByText('接入车辆')).not.toBeInTheDocument();

  fireEvent.click(firstVehicle);
  expect(workspace).toHaveClass('is-detail-open');
  expect(firstVehicle).toHaveClass('is-selected');
  expect(screen.getByRole('button', { name: '取消选择车辆' })).toBeInTheDocument();
  expect(screen.getByTestId('fleet-map')).toHaveAttribute('data-selected-vin', 'LTEST000000000001');
  const mapRendersAfterSelection = fleetMapRenderSpy.mock.calls.length;

  fireEvent.click(screen.getByRole('button', { name: '收起车辆详情' }));
  expect(workspace).toHaveClass('is-detail-collapsed');
  expect(firstVehicle).toHaveClass('is-selected');
  expect(screen.getByRole('button', { name: '展开车辆详情' })).toBeInTheDocument();
  expect(fleetMapRenderSpy).toHaveBeenCalledTimes(mapRendersAfterSelection);

  fireEvent.click(secondVehicle);
  expect(workspace).toHaveClass('is-detail-open');
  expect(secondVehicle).toHaveClass('is-selected');
  expect(screen.queryByRole('button', { name: '展开车辆详情' })).not.toBeInTheDocument();

  fireEvent.click(screen.getByRole('button', { name: '取消选择车辆' }));
  expect(workspace).not.toHaveClass('is-detail-open');
  expect(workspace).not.toHaveClass('is-detail-collapsed');
  expect(secondVehicle).not.toHaveClass('is-selected');
  expect(screen.getByTestId('fleet-map')).toHaveAttribute('data-selected-vin', '');

  fireEvent.click(screen.getByRole('button', { name: '选择地图车辆' }));
  expect(workspace).toHaveClass('is-detail-open');
  expect(secondVehicle).toHaveClass('is-selected');
});

test('switches to a lightweight realtime list and resolves addresses only on demand', async () => {
  const row = vehicles[0];
  vi.spyOn(api, 'vehicleRealtime').mockResolvedValue({ items: [row], total: 1, limit: 50, offset: 0 });
  const reverseGeocode = vi.spyOn(api, 'reverseGeocode').mockResolvedValue({ provider: 'AMap', longitude: 113.26, latitude: 23.13, formattedAddress: '广东省广州市天河区测试路' });
  const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  render(<QueryClientProvider client={queryClient}><MemoryRouter><MonitorPage /></MemoryRouter></QueryClientProvider>);
  fireEvent.click(screen.getByRole('button', { name: /列表/ }));
  expect(await screen.findByText('车辆实时列表')).toBeInTheDocument();
  expect(screen.getByText('速度、里程和坐标实时刷新，文字地址按需解析')).toBeInTheDocument();
  expect(await screen.findAllByText('粤A12345')).toHaveLength(2);
  expect(screen.getAllByText('42')).toHaveLength(2);
  expect(screen.getAllByText(/1,234/)).toHaveLength(2);
  expect(screen.getAllByText(/113\.260000/)).toHaveLength(2);
  expect(reverseGeocode).not.toHaveBeenCalled();

  fireEvent.click(screen.getAllByRole('button', { name: '解析粤A12345位置' })[0]);
  expect(await screen.findByText('广东省广州市天河区测试路')).toBeInTheDocument();
  expect(reverseGeocode).toHaveBeenCalledTimes(1);
  expect(screen.queryByText('综合状态')).not.toBeInTheDocument();
  expect(screen.queryByText('三路正常')).not.toBeInTheDocument();
  expect(screen.queryByTestId('fleet-map')).not.toBeInTheDocument();
});

test('pastes, deduplicates, and submits multiple plates as one batch search', async () => {
  const vehicleRealtime = vi.spyOn(api, 'vehicleRealtime').mockResolvedValue({ items: vehicles, total: 2, limit: 50, offset: 0 });
  const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  render(<QueryClientProvider client={queryClient}><MemoryRouter><MonitorPage /></MemoryRouter></QueryClientProvider>);

  const input = screen.getByRole('textbox', { name: '搜索车辆' });
  fireEvent.paste(input, { clipboardData: { getData: () => '粤a12345\n粤B67890，粤A12345' } });
  expect(input).toHaveValue('粤A12345，粤B67890');
  expect(screen.getAllByText('已找到 2/2')).toHaveLength(3);

  fireEvent.click(screen.getByRole('button', { name: /列表/ }));
  await waitFor(() => {
    const params = vehicleRealtime.mock.calls[vehicleRealtime.mock.calls.length - 1]?.[0];
    expect(params?.get('keywords')).toBe('粤A12345,粤B67890');
    expect(params?.has('keyword')).toBe(false);
  });
});

test('hides stale fleet rows while a pasted batch is still loading', () => {
  monitorQueryFlags.isPlaceholderData = true;
  const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  render(<QueryClientProvider client={queryClient}><MemoryRouter><MonitorPage /></MemoryRouter></QueryClientProvider>);

  fireEvent.paste(screen.getByRole('textbox', { name: '搜索车辆' }), { clipboardData: { getData: () => '粤A12345\n粤B67890' } });
  expect(screen.getByText('正在查找 2 辆车')).toBeInTheDocument();
  expect(screen.getByText('查询中')).toBeInTheDocument();
  expect(screen.queryByRole('button', { name: /粤A12345 LTEST000000000001/ })).not.toBeInTheDocument();
});

test('reports pasted plates that have no exact realtime match', () => {
  const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  render(<QueryClientProvider client={queryClient}><MemoryRouter><MonitorPage /></MemoryRouter></QueryClientProvider>);

  fireEvent.paste(screen.getByRole('textbox', { name: '搜索车辆' }), { clipboardData: { getData: () => '粤A12345\n粤Z99999' } });
  expect(screen.getByText('已找到 1/2')).toBeInTheDocument();
  expect(screen.getAllByText('已找到 1/2 · 未找到 1 辆')).toHaveLength(2);
  expect(screen.getAllByTitle('未找到：粤Z99999')).toHaveLength(2);
});
