import { useCallback, useEffect, useState } from 'react';
import { Toast } from '@douyinfe/semi-ui';
import { api } from './api/client';
import type { VehicleSourceConsistency, VehicleServiceOverview, VehicleServiceStatus } from './api/types';
import { buildAppHash, parseAppHash } from './domain/appRoute';
import { AppShell, type PageKey } from './layout/AppShell';
import { Dashboard } from './pages/Dashboard';
import { History } from './pages/History';
import { Mileage } from './pages/Mileage';
import { Quality } from './pages/Quality';
import { Realtime } from './pages/Realtime';
import { VehicleDetail } from './pages/VehicleDetail';
import { Vehicles } from './pages/Vehicles';

export default function App() {
  const initialRoute = parseAppHash(window.location.hash);
  const initialVehicleKey = initialRoute.keyword || 'LB9A32A24R0LS1426';
  const [activePage, setActivePage] = useState<PageKey>(initialRoute.page ?? 'dashboard');
  const [activeVin, setActiveVin] = useState(initialVehicleKey);
  const [analysisVin, setAnalysisVin] = useState(initialVehicleKey);
  const [activeProtocol, setActiveProtocol] = useState(initialRoute.protocol ?? '');
  const [historyTab, setHistoryTab] = useState(initialRoute.filters?.tab ?? 'location');
  const [vehicleFilters, setVehicleFilters] = useState<Record<string, string>>(
    initialRoute.page === 'vehicles' ? vehicleFiltersFromRoute(initialRoute) : {}
  );
  const [realtimeFilters, setRealtimeFilters] = useState<Record<string, string>>(
    initialRoute.page === 'realtime' ? realtimeFiltersFromRoute(initialRoute) : {}
  );
  const [historyFilters, setHistoryFilters] = useState<Record<string, string>>(
    initialRoute.page === 'history' ? historyFiltersFromRoute(initialRoute) : {}
  );
  const [mileageFilters, setMileageFilters] = useState<Record<string, string>>(
    initialRoute.page === 'mileage' ? mileageFiltersFromRoute(initialRoute) : {}
  );
  const [qualityFilters, setQualityFilters] = useState<Record<string, string>>(
    initialRoute.page === 'quality' ? qualityFiltersFromRoute(initialRoute) : {}
  );
  const [linkIssueCount, setLinkIssueCount] = useState<number | null>(null);
  const [currentVehicleStatus, setCurrentVehicleStatus] = useState<VehicleServiceStatus | undefined>();
  const [currentVehicleLabel, setCurrentVehicleLabel] = useState('');
  const [currentVehicleConsistency, setCurrentVehicleConsistency] = useState<VehicleSourceConsistency | undefined>();

  const loadVehicleContext = useCallback(async (keyword: string, protocol?: string) => {
    const lookupKey = keyword.trim();
    if (!lookupKey) {
      return undefined;
    }
    const params = new URLSearchParams({ keyword: lookupKey });
    const source = protocol?.trim();
    if (source) {
      params.set('protocol', source);
    }
    const overview = await api.vehicleServiceOverview(params);
    const nextKey = overview.vin || lookupKey;
    const resolved = Boolean(overview.vin);
    setCurrentVehicleStatus(overview.serviceStatus ?? serviceStatusFromOverview(overview));
    setCurrentVehicleLabel(resolved ? [overview.plate, overview.vin || nextKey].filter(Boolean).join(' / ') : lookupKey);
    setCurrentVehicleConsistency(overview.sourceConsistency);
    return { resolved, nextKey, overview };
  }, []);

  const refreshOpsHealth = useCallback((showError = true) => {
    return api.opsHealth()
      .then((health) => {
        setLinkIssueCount(health.linkHealth.filter((item) => item.status !== 'ok').length);
        return health;
      })
      .catch((error: Error) => {
        if (showError) {
          Toast.error(error.message);
        }
      });
  }, [loadVehicleContext]);

  useEffect(() => {
    if (initialRoute.page !== 'detail' || !initialRoute.keyword) {
      return;
    }
    loadVehicleContext(initialRoute.keyword, initialRoute.protocol).catch((error) => {
      Toast.error(error instanceof Error ? error.message : '车辆查询失败');
    });
  }, [initialRoute.keyword, initialRoute.page, loadVehicleContext]);

  useEffect(() => {
    refreshOpsHealth();
    const timer = window.setInterval(() => {
      refreshOpsHealth(false);
    }, 60000);
    return () => window.clearInterval(timer);
  }, [refreshOpsHealth]);

  useEffect(() => {
    const applyHashRoute = () => {
      const route = parseAppHash(window.location.hash);
      if (!route.page) {
        return;
      }
      setActivePage(route.page);
      if (route.keyword) {
        if (route.page === 'detail') {
          setActiveVin(route.keyword);
        }
        if (route.page === 'history' || route.page === 'mileage') {
          setAnalysisVin(route.keyword);
        }
      }
      if (route.page === 'vehicles') {
        setVehicleFilters(vehicleFiltersFromRoute(route));
      }
      if (route.page === 'realtime') {
        setRealtimeFilters(realtimeFiltersFromRoute(route));
      }
      if (route.page === 'history') {
        setHistoryFilters(historyFiltersFromRoute(route));
      }
      if (route.page === 'mileage') {
        setMileageFilters(mileageFiltersFromRoute(route));
      }
      if (route.page === 'quality') {
        setQualityFilters(qualityFiltersFromRoute(route));
      }
      setActiveProtocol(route.protocol ?? '');
      setHistoryTab(route.filters?.tab ?? 'location');
    };
    window.addEventListener('hashchange', applyHashRoute);
    return () => window.removeEventListener('hashchange', applyHashRoute);
  }, []);

  const replaceHash = (page: PageKey, keyword?: string, protocol?: string, filters?: Record<string, string>) => {
    const nextHash = buildAppHash({ page, keyword, protocol, filters });
    if (window.location.hash !== nextHash) {
      window.history.replaceState(null, '', nextHash);
    }
  };

  const navigatePage = (page: PageKey) => {
    setActivePage(page);
    if (page === 'detail') {
      replaceHash(page, activeVin, activeProtocol);
      return;
    }
    if (page === 'history' || page === 'mileage') {
      if (page === 'history') {
        replaceHistoryHash(historyFilters);
        return;
      }
      replaceMileageHash(mileageFilters);
      return;
    }
    if (page === 'quality') {
      replaceQualityHash(qualityFilters);
      return;
    }
    if (page === 'vehicles') {
      replaceVehicleHash(vehicleFilters);
      return;
    }
    if (page === 'realtime') {
      replaceRealtimeHash(realtimeFilters);
      return;
    }
    replaceHash(page);
  };

  const openVehicles = (filters: Record<string, string> = {}) => {
    setVehicleFilters(filters);
    setActivePage('vehicles');
    replaceVehicleHash(filters);
  };

  const updateVehicleFilters = (filters: Record<string, string> = {}) => {
    setVehicleFilters(filters);
    replaceVehicleHash(filters);
  };

  const replaceVehicleHash = (filters: Record<string, string> = {}) => {
    const { keyword, protocol, ...restFilters } = filters;
    replaceHash('vehicles', keyword, protocol, restFilters);
  };

  const updateRealtimeFilters = (filters: Record<string, string> = {}) => {
    setRealtimeFilters(filters);
    replaceRealtimeHash(filters);
  };

  const replaceRealtimeHash = (filters: Record<string, string> = {}) => {
    const { keyword, protocol, ...restFilters } = filters;
    replaceHash('realtime', keyword, protocol, restFilters);
  };

  const updateHistoryFilters = (filters: Record<string, unknown> = {}, tab = historyTab) => {
    const nextFilters = normalizeHistoryFilterValues(filters);
    setHistoryFilters(nextFilters);
    if (nextFilters.keyword) {
      setAnalysisVin(nextFilters.keyword);
    }
    setActiveProtocol(nextFilters.protocol ?? '');
    setHistoryTab(tab);
    const { keyword, protocol, ...restFilters } = nextFilters;
    const routeFilters = { ...restFilters };
    if (tab && tab !== 'location') {
      routeFilters.tab = tab;
    }
    replaceHash('history', keyword ?? analysisVin, protocol, routeFilters);
  };

  const replaceHistoryHash = (filters: Record<string, string> = {}, tab = historyTab) => {
    const { keyword, protocol, ...restFilters } = filters;
    const routeFilters = { ...restFilters };
    if (tab && tab !== 'location') {
      routeFilters.tab = tab;
    }
    replaceHash('history', keyword ?? analysisVin, protocol ?? activeProtocol, routeFilters);
  };

  const updateMileageFilters = (filters: Record<string, unknown> = {}) => {
    const nextFilters = normalizeMileageFilterValues(filters);
    setMileageFilters(nextFilters);
    if (nextFilters.keyword) {
      setAnalysisVin(nextFilters.keyword);
    }
    setActiveProtocol(nextFilters.protocol ?? '');
    const { keyword, protocol, ...restFilters } = nextFilters;
    replaceHash('mileage', keyword ?? analysisVin, protocol, restFilters);
  };

  const replaceMileageHash = (filters: Record<string, string> = {}) => {
    const { keyword, protocol, ...restFilters } = filters;
    replaceHash('mileage', keyword ?? analysisVin, protocol ?? activeProtocol, restFilters);
  };

  const replaceQualityHash = (filters: Record<string, string> = {}) => {
    const keyword = filters.keyword;
    const protocol = filters.protocol;
    const issueFilters: Record<string, string> = {};
    if (filters.issueType) {
      issueFilters.issueType = filters.issueType;
    }
    replaceHash('quality', keyword, protocol, issueFilters);
  };

  const updateQualityFilters = (filters: Record<string, string> = {}) => {
    setQualityFilters(filters);
    replaceQualityHash(filters);
  };

  const openQuality = (filters: Record<string, string> = {}) => {
    setQualityFilters(filters);
    setActivePage('quality');
    replaceQualityHash(filters);
  };

  const openVehicle = async (keyword: string, protocol?: string) => {
    const lookupKey = keyword.trim();
    const nextProtocol = protocol?.trim() ?? '';
    if (!lookupKey) {
      return;
    }
    try {
      const context = await loadVehicleContext(lookupKey, nextProtocol);
      const resolved = context?.resolved;
      const nextKey = context?.nextKey ?? lookupKey;
      setActiveVin(nextKey);
      setActiveProtocol(nextProtocol);
      setActivePage('detail');
      replaceHash('detail', nextKey, nextProtocol);
      if (!resolved) {
        Toast.warning('未匹配到车辆身份，已打开问题排查视图');
      }
    } catch (error) {
      Toast.error(error instanceof Error ? error.message : '车辆查询失败');
    }
  };

  const openHistoryForVehicle = (vin: string, protocol?: string) => {
    const nextVin = vin.trim();
    const nextProtocol = protocol?.trim() ?? activeProtocol;
    if (!nextVin) {
      return;
    }
    setAnalysisVin(nextVin);
    setActiveProtocol(nextProtocol);
    setHistoryTab('location');
    setHistoryFilters({ keyword: nextVin, protocol: nextProtocol });
    setActivePage('history');
    replaceHash('history', nextVin, nextProtocol);
  };

  const openRawForVehicle = (vin: string, protocol?: string) => {
    const nextVin = vin.trim();
    const nextProtocol = protocol?.trim() ?? activeProtocol;
    if (!nextVin) {
      return;
    }
    setAnalysisVin(nextVin);
    setActiveProtocol(nextProtocol);
    setHistoryTab('raw');
    setHistoryFilters({ keyword: nextVin, protocol: nextProtocol });
    setActivePage('history');
    replaceHash('history', nextVin, nextProtocol, { tab: 'raw' });
  };

  const openRealtimeForVehicle = (vin: string, protocol?: string) => {
    const nextVin = vin.trim();
    const nextProtocol = protocol?.trim() ?? activeProtocol;
    if (!nextVin) {
      return;
    }
    const nextFilters = { keyword: nextVin, protocol: nextProtocol };
    setAnalysisVin(nextVin);
    setActiveProtocol(nextProtocol);
    setRealtimeFilters(nextFilters);
    setActivePage('realtime');
    replaceRealtimeHash(nextFilters);
  };

  const openMileageForVehicle = (vin: string, protocol?: string) => {
    const nextVin = vin.trim();
    const nextProtocol = protocol?.trim() ?? activeProtocol;
    if (!nextVin) {
      return;
    }
    setAnalysisVin(nextVin);
    setActiveProtocol(nextProtocol);
    setMileageFilters({ keyword: nextVin, protocol: nextProtocol });
    setActivePage('mileage');
    replaceHash('mileage', nextVin, nextProtocol);
  };

  const updateVehicleDetailQuery = (keyword: string, protocol?: string) => {
    const nextKeyword = keyword.trim();
    const nextProtocol = protocol?.trim() ?? '';
    if (!nextKeyword) {
      return;
    }
    setActiveVin(nextKeyword);
    setActiveProtocol(nextProtocol);
    replaceHash('detail', nextKeyword, nextProtocol);
  };

  const pages: Record<PageKey, JSX.Element> = {
    dashboard: <Dashboard onOpenVehicle={openVehicle} onOpenQuality={() => openQuality(qualityFilters)} onOpenVehicles={openVehicles} />,
    vehicles: <Vehicles onOpenVehicle={openVehicle} onFiltersChange={updateVehicleFilters} initialFilters={vehicleFilters} />,
    realtime: <Realtime onOpenVehicle={openVehicle} onFiltersChange={updateRealtimeFilters} initialFilters={realtimeFilters} />,
    detail: <VehicleDetail vin={activeVin} protocol={activeProtocol} onOpenRealtime={openRealtimeForVehicle} onOpenHistory={openHistoryForVehicle} onOpenRaw={openRawForVehicle} onOpenMileage={openMileageForVehicle} onOpenVehicles={openVehicles} onOpenQuality={openQuality} onQueryChange={updateVehicleDetailQuery} />,
    history: <History initialVin={analysisVin} initialProtocol={activeProtocol} initialTab={historyTab} initialFilters={historyFilters} onFiltersChange={updateHistoryFilters} onOpenVehicle={openVehicle} />,
    mileage: <Mileage initialVin={analysisVin} initialProtocol={activeProtocol} initialFilters={mileageFilters} onFiltersChange={updateMileageFilters} onOpenVehicle={openVehicle} />,
    quality: <Quality onOpenVehicle={openVehicle} onHealthLoaded={(health) => setLinkIssueCount(health.linkHealth.filter((item) => item.status !== 'ok').length)} onFiltersChange={updateQualityFilters} initialFilters={qualityFilters} />
  };

  return (
    <AppShell activePage={activePage} linkIssueCount={linkIssueCount} currentVehicleStatus={currentVehicleStatus} currentVehicleLabel={currentVehicleLabel} currentVehicleConsistency={currentVehicleConsistency} onChange={navigatePage} onVehicleSearch={openVehicle}>
      {pages[activePage]}
    </AppShell>
  );
}

function qualityFiltersFromRoute(route: ReturnType<typeof parseAppHash>): Record<string, string> {
  return {
    ...(route.keyword ? { keyword: route.keyword } : {}),
    ...(route.protocol ? { protocol: route.protocol } : {}),
    ...(route.filters?.issueType ? { issueType: route.filters.issueType } : {})
  };
}

function vehicleFiltersFromRoute(route: ReturnType<typeof parseAppHash>): Record<string, string> {
  return {
    ...(route.keyword ? { keyword: route.keyword } : {}),
    ...(route.protocol ? { protocol: route.protocol } : {}),
    ...(route.filters ?? {})
  };
}

function realtimeFiltersFromRoute(route: ReturnType<typeof parseAppHash>): Record<string, string> {
  return {
    ...(route.keyword ? { keyword: route.keyword } : {}),
    ...(route.protocol ? { protocol: route.protocol } : {}),
    ...(route.filters?.online ? { online: route.filters.online } : {}),
    ...(route.filters?.serviceStatus ? { serviceStatus: route.filters.serviceStatus } : {})
  };
}

function historyFiltersFromRoute(route: ReturnType<typeof parseAppHash>): Record<string, string> {
  return normalizeHistoryFilterValues({
    ...(route.keyword ? { keyword: route.keyword } : {}),
    ...(route.protocol ? { protocol: route.protocol } : {}),
    ...(route.filters?.dateFrom ? { dateFrom: route.filters.dateFrom } : {}),
    ...(route.filters?.dateTo ? { dateTo: route.filters.dateTo } : {}),
    ...(route.filters?.includeFields ? { includeFields: route.filters.includeFields } : {}),
    ...(route.filters?.fields ? { fields: route.filters.fields } : {})
  });
}

function mileageFiltersFromRoute(route: ReturnType<typeof parseAppHash>): Record<string, string> {
  return normalizeMileageFilterValues({
    ...(route.keyword ? { keyword: route.keyword } : {}),
    ...(route.protocol ? { protocol: route.protocol } : {}),
    ...(route.filters?.dateFrom ? { dateFrom: route.filters.dateFrom } : {}),
    ...(route.filters?.dateTo ? { dateTo: route.filters.dateTo } : {})
  });
}

function normalizeMileageFilterValues(filters: Record<string, unknown> = {}): Record<string, string> {
  const normalized: Record<string, string> = {};
  for (const key of ['keyword', 'protocol', 'dateFrom', 'dateTo'] as const) {
    const value = String(filters[key] ?? '').trim();
    if (value) {
      normalized[key] = value;
    }
  }
  return normalized;
}

function normalizeHistoryFilterValues(filters: Record<string, unknown> = {}): Record<string, string> {
  const normalized: Record<string, string> = {};
  for (const key of ['keyword', 'protocol', 'dateFrom', 'dateTo', 'fields'] as const) {
    const value = String(filters[key] ?? '').trim();
    if (value) {
      normalized[key] = value;
    }
  }
  const includeFields = filters.includeFields;
  if (includeFields === true || includeFields === 'true') {
    normalized.includeFields = 'true';
  }
  return normalized;
}

function serviceStatusFromOverview(overview: VehicleServiceOverview): VehicleServiceStatus {
  const sourceCount = overview.sourceCount;
  const onlineSourceCount = overview.onlineSourceCount;
  const missingProtocols = overview.sourceConsistency?.missingProtocols ?? [];
  if (!overview.vin) {
    return {
      status: 'identity_required',
      severity: 'warning',
      title: '身份未绑定',
      detail: '车辆关键词暂未解析到 VIN，需先维护身份绑定后才能形成完整车辆服务。',
      sourceCount,
      onlineSourceCount
    };
  }
  if (sourceCount <= 0) {
    return {
      status: 'no_data',
      severity: 'warning',
      title: '暂无数据来源',
      detail: '车辆已解析，但暂未查询到 32960、808 或 MQTT 数据来源。',
      sourceCount,
      onlineSourceCount
    };
  }
  if (onlineSourceCount <= 0) {
    return {
      status: 'offline',
      severity: 'error',
      title: '车辆离线',
      detail: '所有已知数据来源均未在线，需要检查平台转发、终端上报或链路状态。',
      sourceCount,
      onlineSourceCount
    };
  }
  if (missingProtocols.length > 0) {
    return {
      status: 'degraded',
      severity: 'warning',
      title: '来源不完整',
      detail: `${onlineSourceCount}/${sourceCount} 个来源在线，车辆服务可用但缺少 ${missingProtocols.join('、')} 来源。`,
      sourceCount,
      onlineSourceCount
    };
  }
  if (onlineSourceCount < sourceCount) {
    return {
      status: 'degraded',
      severity: 'warning',
      title: '来源不完整',
      detail: `${onlineSourceCount}/${sourceCount} 个来源在线，车辆服务可用但需要关注离线来源。`,
      sourceCount,
      onlineSourceCount
    };
  }
  return {
    status: 'healthy',
    severity: 'ok',
    title: '服务正常',
    detail: `${onlineSourceCount}/${sourceCount} 个来源在线，全部已知来源在线。`,
    sourceCount,
    onlineSourceCount
  };
}
