import { useEffect, useState, useMemo } from 'react';
import {
  LineChart,
  Line,
  BarChart,
  Bar,
  PieChart,
  Pie,
  Cell,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
  ResponsiveContainer,
} from 'recharts';
import {
  Activity,
  AlertTriangle,
  Droplets,
  Building2,
  TrendingUp,
  TrendingDown,
  Users,
} from 'lucide-react';
import { caseApi, riskApi, alertApi, envApi } from '@/services/api';
import { StatCard } from '@/components/StatCard';
import { ErrorBanner } from '@/components/ErrorBanner';
import type {
  CaseTrendPoint,
  DistrictCaseData,
  PollutantPoint,
  DiagnosisBreakdown,
  Alert,
} from '@/types';

// --- Types for fetched data ---
interface KpiData {
  totalCases: number;
  todayCases: number;
  changeRatio: number | null;
  activeAlerts: number;
  highRiskGrids: number;
  avgAQI: number;
}

interface MergedTrendItem {
  date: string;
  cases: number;
  aqi: number;
}

function formatDateLabel(dateStr: string): string {
  const d = new Date(dateStr);
  return `${d.getMonth() + 1}/${d.getDate()}`;
}

function computeChangeRatio(trend: CaseTrendPoint[]): number | null {
  if (trend.length < 8) return null;
  const recent7 = trend.slice(-7).reduce((s, p) => s + p.total, 0);
  const prior7 = trend.slice(-14, -7).reduce((s, p) => s + p.total, 0);
  if (prior7 === 0) return null;
  return ((recent7 - prior7) / prior7) * 100;
}

export function OverviewDashboard() {
  const [kpi, setKpi] = useState<KpiData | null>(null);
  const [mergedTrend, setMergedTrend] = useState<MergedTrendItem[]>([]);
  const [topDistricts, setTopDistricts] = useState<DistrictCaseData[]>([]);
  const [topDiagnoses, setTopDiagnoses] = useState<DiagnosisBreakdown[]>([]);
  const [alertPie, setAlertPie] = useState<{ name: string; value: number; color: string }[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [errors, setErrors] = useState<string[]>([]);

  useEffect(() => {
    let cancelled = false;

    const fetchAll = async () => {
      setIsLoading(true);
      setErrors([]);

      const now = new Date();
      const endStr = now.toISOString().split('T')[0];
      const start14 = new Date(now);
      start14.setDate(start14.getDate() - 14);
      const start14Str = start14.toISOString().split('T')[0];
      const start30 = new Date(now);
      start30.setDate(start30.getDate() - 30);
      const start30Str = start30.toISOString().split('T')[0];

      // KPI sources — Promise.allSettled to survive individual failures
      const [statsR, trend14R, alertsR, riskStatsR, pollutantsR] = await Promise.allSettled([
        caseApi.getStats(),
        caseApi.getTrend({ start_date: start14Str, end_date: endStr, group_by: 'day' }),
        alertApi.getAlerts(),
        riskApi.getStats(),
        envApi.getPollutants(7),
      ]);

      // Trend sources
      const [trend30R, districtsR, diagStatsR] = await Promise.allSettled([
        caseApi.getTrend({ start_date: start30Str, end_date: endStr, group_by: 'day' }),
        caseApi.getDistricts(),
        caseApi.getStats(), // reuse for top_diagnoses
      ]);

      if (cancelled) return;

      const newErrors: string[] = [];

      // --- Build KPI ---
      let totalCases = 0;
      if (statsR.status === 'fulfilled') {
        const s = statsR.value;
        totalCases = (s.total_outpatient || 0) + (s.total_inpatient || 0);
      } else {
        newErrors.push('累计病例数据加载失败');
      }

      let todayCases = 0;
      let changeRatio: number | null = null;
      if (trend14R.status === 'fulfilled') {
        const trend = trend14R.value.trend || [];
        if (trend.length > 0) {
          todayCases = trend[trend.length - 1].total;
        }
        changeRatio = computeChangeRatio(trend);
      } else {
        newErrors.push('今日病例数据加载失败');
      }

      let activeAlerts = 0;
      let alertList: Alert[] = [];
      if (alertsR.status === 'fulfilled') {
        alertList = alertsR.value.alerts || [];
        activeAlerts = alertList.length;
      } else {
        newErrors.push('预警数据加载失败');
      }

      let highRiskGrids = 0;
      if (riskStatsR.status === 'fulfilled') {
        highRiskGrids = riskStatsR.value.high_risk_count || 0;
      } else {
        newErrors.push('风险网格数据加载失败');
      }

      let avgAQI = 0;
      let pollutantData: PollutantPoint[] = [];
      if (pollutantsR.status === 'fulfilled') {
        pollutantData = pollutantsR.value.data || [];
        if (pollutantData.length > 0) {
          const sumAQI = pollutantData.reduce((s, p) => s + (p.AQI || 0), 0);
          avgAQI = Math.round(sumAQI / pollutantData.length);
        }
      } else {
        newErrors.push('AQI数据加载失败');
      }

      setKpi({ totalCases, todayCases, changeRatio, activeAlerts, highRiskGrids, avgAQI });
      setErrors(newErrors);

      // --- Merge case trend + AQI ---
      if (trend30R.status === 'fulfilled') {
        const trend30 = trend30R.value.trend || [];
        const aqiMap: Record<string, number> = {};
        if (pollutantsR.status === 'fulfilled') {
          for (const p of pollutantData) {
            aqiMap[p.date] = p.AQI || 0;
          }
        }
        // Only use data from the last 30 days for display
        const merged: MergedTrendItem[] = trend30.map((t) => ({
          date: t.date,
          cases: t.total,
          aqi: aqiMap[t.date] || 0,
        }));
        setMergedTrend(merged);
      } else if (!newErrors.includes('今日病例数据加载失败')) {
        newErrors.push('趋势数据加载失败');
      }

      // --- Top 5 Districts ---
      if (districtsR.status === 'fulfilled') {
        const districts = districtsR.value.districts || [];
        const sorted = [...districts].sort((a, b) => b.total - a.total);
        setTopDistricts(sorted.slice(0, 5));
      }

      // --- Top 5 Diagnoses ---
      if (diagStatsR.status === 'fulfilled') {
        const topDiag = diagStatsR.value.top_diagnoses || [];
        setTopDiagnoses(
          topDiag.slice(0, 5).map((d) => ({
            diagnosis: d.diagnosis,
            outpatient: d.outpatient,
            inpatient: d.inpatient,
            total: d.outpatient + d.inpatient,
          }))
        );
      }

      // --- Alert severity donut ---
      const p1 = alertList.filter((a) => a.priority === 'P1').length;
      const p2 = alertList.filter((a) => a.priority === 'P2').length;
      setAlertPie([
        { name: 'P1 紧急', value: p1, color: '#EF4444' },
        { name: 'P2 关注', value: p2, color: '#F59E0B' },
      ]);

      setIsLoading(false);
    };

    fetchAll();

    return () => {
      cancelled = true;
    };
  }, []);

  const changeTrend = useMemo(() => {
    if (kpi?.changeRatio == null) return undefined;
    if (kpi.changeRatio > 0) {
      return { direction: 'up' as const, value: `${kpi.changeRatio.toFixed(1)}%` };
    }
    if (kpi.changeRatio < 0) {
      return { direction: 'down' as const, value: `${Math.abs(kpi.changeRatio).toFixed(1)}%` };
    }
    return { direction: 'stable' as const, value: '0%' };
  }, [kpi?.changeRatio]);

  // --- Loading state ---
  if (isLoading) {
    return (
      <div className="flex items-center justify-center h-64">
        <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600" />
      </div>
    );
  }

  return (
    <div data-testid="page-overview" className="flex flex-col h-full overflow-auto">
      {/* Error banner */}
      {errors.length > 0 && (
        <div className="px-6 pt-4">
          <ErrorBanner
            error={errors.join('；')}
            onRetry={() => window.location.reload()}
            onDismiss={() => setErrors([])}
          />
        </div>
      )}

      <div className="p-6 space-y-6">
        {/* Page header */}
        <div>
          <h1 className="font-display text-[18px] font-semibold mb-1 flex items-center gap-2">
            <Activity className="w-5 h-5 text-primary" />
            综合概览
          </h1>
          <p className="text-[12px] text-gray-500">病例、环境与预警关键指标总览</p>
        </div>

        {/* Section 1: KPI Row */}
        <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-3">
          <StatCard
            icon={<Users className="w-4 h-4 text-blue-600" />}
            label="累计病例总数"
            value={kpi?.totalCases?.toLocaleString() ?? '--'}
          />
          <StatCard
            icon={<Activity className="w-4 h-4 text-green-600" />}
            label="今日病例"
            value={kpi?.todayCases?.toLocaleString() ?? '--'}
          />
          <StatCard
            icon={
              (changeTrend?.direction === 'up' && <TrendingUp className="w-4 h-4 text-red-500" />) ||
              (changeTrend?.direction === 'down' && <TrendingDown className="w-4 h-4 text-green-500" />) || (
                <Activity className="w-4 h-4 text-gray-400" />
              )
            }
            label="7日变化率"
            value={changeTrend ? changeTrend.value : '--'}
            trend={changeTrend}
          />
          <StatCard
            icon={<AlertTriangle className="w-4 h-4 text-orange-500" />}
            label="活跃预警数"
            value={kpi?.activeAlerts?.toLocaleString() ?? '--'}
            color={kpi && kpi.activeAlerts > 0 ? '#EF4444' : undefined}
          />
          <StatCard
            icon={<Building2 className="w-4 h-4 text-red-500" />}
            label="高风险网格"
            value={kpi?.highRiskGrids?.toLocaleString() ?? '--'}
          />
          <StatCard
            icon={<Droplets className="w-4 h-4 text-cyan-500" />}
            label="平均AQI"
            value={kpi?.avgAQI?.toLocaleString() ?? '--'}
          />
        </div>

        {/* Section 2: Case + AQI Mini Trend */}
        <div className="card p-4">
          <div className="text-[11px] font-medium text-gray-500 uppercase tracking-wide mb-4">
            近30日病例与AQI趋势
          </div>
          {mergedTrend.length > 0 ? (
            <ResponsiveContainer width="100%" height={200}>
              <LineChart data={mergedTrend} margin={{ top: 5, right: 10, left: 0, bottom: 5 }}>
                <CartesianGrid strokeDasharray="3 3" stroke="#E2E8F0" />
                <XAxis
                  dataKey="date"
                  tickFormatter={formatDateLabel}
                  tick={{ fontSize: 10, fill: '#64748B' }}
                  interval="preserveStartEnd"
                  axisLine={{ stroke: '#E2E8F0' }}
                />
                <YAxis
                  yAxisId="left"
                  tick={{ fontSize: 10, fill: '#64748B' }}
                  axisLine={{ stroke: '#E2E8F0' }}
                />
                <YAxis
                  yAxisId="right"
                  orientation="right"
                  tick={{ fontSize: 10, fill: '#F59E0B' }}
                  axisLine={{ stroke: '#E2E8F0' }}
                />
                <Tooltip
                  contentStyle={{
                    backgroundColor: '#FFFFFF',
                    border: '1px solid #E2E8F0',
                    borderRadius: '8px',
                    fontSize: '12px',
                  }}
                  labelStyle={{ color: '#1E293B', fontWeight: 600 }}
                />
                <Legend wrapperStyle={{ fontSize: '11px' }} />
                <Line
                  yAxisId="left"
                  type="monotone"
                  dataKey="cases"
                  name="病例数"
                  stroke="#3B82F6"
                  strokeWidth={2}
                  dot={false}
                  activeDot={{ r: 3 }}
                />
                <Line
                  yAxisId="right"
                  type="monotone"
                  dataKey="aqi"
                  name="AQI"
                  stroke="#F59E0B"
                  strokeWidth={2}
                  strokeDasharray="5 5"
                  dot={false}
                  activeDot={{ r: 3 }}
                />
              </LineChart>
            </ResponsiveContainer>
          ) : (
            <div className="text-center py-8 text-gray-400 text-sm">暂无数据</div>
          )}
        </div>

        {/* Section 3 + 4: Top Districts + Top Diagnoses side by side */}
        <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
          {/* Section 3: Top 5 Districts */}
          <div className="card p-4">
            <div className="text-[11px] font-medium text-gray-500 uppercase tracking-wide mb-4">
              Top 5 区县病例分布
            </div>
            {topDistricts.length > 0 ? (
              <ResponsiveContainer width="100%" height={220}>
                <BarChart
                  data={[...topDistricts].reverse()}
                  layout="vertical"
                  margin={{ top: 0, right: 10, left: 30, bottom: 0 }}
                >
                  <CartesianGrid strokeDasharray="3 3" stroke="#E2E8F0" horizontal={false} />
                  <XAxis type="number" tick={{ fontSize: 10, fill: '#64748B' }} />
                  <YAxis
                    type="category"
                    dataKey="district"
                    tick={{ fontSize: 11, fill: '#374151' }}
                    width={60}
                    axisLine={false}
                    tickLine={false}
                  />
                  <Tooltip
                    contentStyle={{
                      backgroundColor: '#FFFFFF',
                      border: '1px solid #E2E8F0',
                      borderRadius: '8px',
                      fontSize: '12px',
                    }}
                    formatter={(value: number) => [value.toLocaleString(), '病例数']}
                  />
                  <Bar dataKey="outpatient" stackId="a" fill="#3B82F6" name="门诊" barSize={20} />
                  <Bar dataKey="inpatient" stackId="a" fill="#EF4444" name="住院" barSize={20} />
                </BarChart>
              </ResponsiveContainer>
            ) : (
              <div className="text-center py-8 text-gray-400 text-sm">暂无数据</div>
            )}
          </div>

          {/* Section 4: Top 5 Diagnoses */}
          <div className="card p-4">
            <div className="text-[11px] font-medium text-gray-500 uppercase tracking-wide mb-4">
              Top 5 诊断分布
            </div>
            {topDiagnoses.length > 0 ? (
              <ResponsiveContainer width="100%" height={220}>
                <BarChart
                  data={[...topDiagnoses].reverse()}
                  layout="vertical"
                  margin={{ top: 0, right: 10, left: 60, bottom: 0 }}
                >
                  <CartesianGrid strokeDasharray="3 3" stroke="#E2E8F0" horizontal={false} />
                  <XAxis type="number" tick={{ fontSize: 10, fill: '#64748B' }} />
                  <YAxis
                    type="category"
                    dataKey="diagnosis"
                    tick={{ fontSize: 11, fill: '#374151' }}
                    width={100}
                    axisLine={false}
                    tickLine={false}
                  />
                  <Tooltip
                    contentStyle={{
                      backgroundColor: '#FFFFFF',
                      border: '1px solid #E2E8F0',
                      borderRadius: '8px',
                      fontSize: '12px',
                    }}
                    formatter={(value: number) => [value.toLocaleString(), '病例数']}
                  />
                  <Bar dataKey="outpatient" stackId="a" fill="#3B82F6" name="门诊" barSize={16} />
                  <Bar dataKey="inpatient" stackId="a" fill="#EF4444" name="住院" barSize={16} />
                </BarChart>
              </ResponsiveContainer>
            ) : (
              <div className="text-center py-8 text-gray-400 text-sm">暂无数据</div>
            )}
          </div>
        </div>

        {/* Section 5: Alert Severity Donut */}
        <div className="card p-4">
          <div className="text-[11px] font-medium text-gray-500 uppercase tracking-wide mb-4">
            预警严重度分布
          </div>
          {alertPie[0].value > 0 || alertPie[1].value > 0 ? (
            <div className="flex items-center justify-center">
              <ResponsiveContainer width="100%" height={240}>
                <PieChart>
                  <Pie
                    data={alertPie}
                    cx="50%"
                    cy="50%"
                    innerRadius={50}
                    outerRadius={80}
                    paddingAngle={4}
                    dataKey="value"
                    nameKey="name"
                  >
                    {alertPie.map((entry, idx) => (
                      <Cell key={idx} fill={entry.color} />
                    ))}
                  </Pie>
                  <Tooltip
                    contentStyle={{
                      backgroundColor: '#FFFFFF',
                      border: '1px solid #E2E8F0',
                      borderRadius: '8px',
                      fontSize: '12px',
                    }}
                    formatter={(value: number, name: string) => [value, name]}
                  />
                  <Legend
                    wrapperStyle={{ fontSize: '12px' }}
                    formatter={(value: string) => (
                      <span className="text-gray-700">{value}</span>
                    )}
                  />
                </PieChart>
              </ResponsiveContainer>
            </div>
          ) : (
            <div className="text-center py-8 text-gray-400 text-sm">暂无预警数据</div>
          )}
        </div>
      </div>
    </div>
  );
}
