import { Fragment, useEffect, useState, useMemo, useCallback } from 'react';
import {
  BarChart,
  Bar,
  PieChart,
  Pie,
  Cell,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  ResponsiveContainer,
} from 'recharts';
import { Users, Activity } from 'lucide-react';
import { caseApi } from '@/services/api';
import { ErrorBanner } from '@/components/ErrorBanner';
import { LoadingState } from '@/components/ui';
import { TESTIDS } from '@/utils/testids';
import type { DemographicsResponse, AgeBin, AgeDiagnosisMatrixItem } from '@/types';

// --- Chart 3 helpers ---
const AGE_GROUPS = ['0-1', '1-3', '3-6', '6-12', '12-18'];

function buildHeatmapMatrix(data: AgeDiagnosisMatrixItem[]): {
  diagnoses: string[];
  matrix: number[][];
  totals: number[];
} {
  // Pivot: count per age_group x diagnosis
  const map: Record<string, Record<string, number>> = {};
  for (const ag of AGE_GROUPS) {
    map[ag] = {};
  }
  for (const item of data) {
    if (map[item.age_group] !== undefined) {
      map[item.age_group][item.diagnosis] = item.inpatient;
    }
  }

  // Collect all diagnoses and their total counts
  const diagTotals: Record<string, number> = {};
  for (const ag of AGE_GROUPS) {
    for (const [diag, count] of Object.entries(map[ag])) {
      diagTotals[diag] = (diagTotals[diag] || 0) + count;
    }
  }

  // Top 8 diagnoses by total count
  const top8 = Object.entries(diagTotals)
    .sort((a, b) => b[1] - a[1])
    .slice(0, 8)
    .map(([diag]) => diag);

  const matrix = AGE_GROUPS.map((ag) => top8.map((diag) => map[ag][diag] || 0));
  const totals = top8.map((diag) => diagTotals[diag]);

  return { diagnoses: top8, matrix, totals };
}

function getColorClass(value: number, maxValue: number): string {
  if (maxValue === 0) return 'bg-blue-50 text-gray-800';
  const ratio = value / maxValue;
  if (ratio === 0) return 'bg-blue-50 text-gray-800';
  if (ratio <= 0.125) return 'bg-blue-100 text-gray-800';
  if (ratio <= 0.25) return 'bg-blue-200 text-gray-800';
  if (ratio <= 0.375) return 'bg-blue-300 text-gray-800';
  if (ratio <= 0.5) return 'bg-blue-400 text-white';
  if (ratio <= 0.625) return 'bg-blue-500 text-white';
  if (ratio <= 0.75) return 'bg-blue-600 text-white';
  if (ratio <= 0.875) return 'bg-blue-700 text-white';
  return 'bg-blue-800 text-white';
}

export function DemographicAnalysis() {
  const [data, setData] = useState<DemographicsResponse | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const fetchData = useCallback(async () => {
    setIsLoading(true);
    setError(null);
    try {
      const result = await caseApi.getDemographics();
      setData(result);
    } catch (err) {
      setError(err instanceof Error ? err.message : '数据加载失败');
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    let cancelled = false;
    const run = async () => {
      setIsLoading(true);
      setError(null);
      try {
        const result = await caseApi.getDemographics();
        if (!cancelled) setData(result);
      } catch (err) {
        if (!cancelled) setError(err instanceof Error ? err.message : '数据加载失败');
      } finally {
        if (!cancelled) setIsLoading(false);
      }
    };
    run();
    return () => {
      cancelled = true;
    };
  }, []);

  // --- Derived data ---
  // 防御性归一化：后端返回意外形状（缺字段/类型不符）时降级为空，避免 .map 抛错
  // 冒泡到根 ErrorBoundary 把整页白屏（与 DiseaseAnalysis/EnvironmentalHealth 的处理一致）。
  const ageData: AgeBin[] = useMemo(() => {
    const bins = Array.isArray(data?.age_distribution) ? data!.age_distribution : [];
    return bins.map((d) => ({
      age_bin: d.age_bin,
      outpatient: d.outpatient,
      inpatient: d.inpatient,
    }));
  }, [data]);

  const genderData = useMemo(() => {
    if (!data) return [];
    const male = data.gender_split?.male?.inpatient ?? 0;
    const female = data.gender_split?.female?.inpatient ?? 0;
    return [
      { name: '男性', value: male, color: '#3B82F6' },
      { name: '女性', value: female, color: '#EC4899' },
    ];
  }, [data]);

  const genderTotal = useMemo(() => {
    return genderData.reduce((s, d) => s + d.value, 0);
  }, [genderData]);

  const heatmapData = useMemo(() => {
    const matrix = Array.isArray(data?.age_diagnosis_matrix) ? data!.age_diagnosis_matrix : [];
    return buildHeatmapMatrix(matrix);
  }, [data]);

  const heatmapMax = useMemo(() => {
    let max = 0;
    for (const row of heatmapData.matrix) {
      for (const v of row) {
        if (v > max) max = v;
      }
    }
    return max;
  }, [heatmapData]);

  // --- Loading state ---
  if (isLoading) {
    return <LoadingState testid={TESTIDS.pageLoading} />;
  }

  const isEmpty =
    !data ||
    (ageData.length === 0 &&
      genderData.length === 0 &&
      heatmapData.matrix.length === 0);

  return (
    <div data-testid="page-demographics" className="flex flex-col h-full overflow-auto">
      {error && (
        <div className="px-6 pt-4">
          <ErrorBanner
            error={error}
            onRetry={fetchData}
            onDismiss={() => setError(null)}
          />
        </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">
            <Users className="w-5 h-5 text-primary" />
            人群分析
          </h1>
          <p className="text-[12px] text-gray-500">住院患者年龄、性别与诊断分布分析</p>
        </div>

        {isEmpty ? (
          <div className="card p-8 text-center text-gray-400 text-sm">
            <Activity className="w-8 h-8 mx-auto mb-3 opacity-30" />
            暂无人口统计数据
          </div>
        ) : (
          <>
            {/* Chart 1: Age Distribution Histogram */}
            <div className="card p-4">
              <div className="text-[11px] font-medium text-gray-500 uppercase tracking-wide mb-1">
                年龄分布
              </div>
              <p className="text-[11px] text-gray-400 mb-4">
                仅住院数据（门诊数据无人口统计信息）
              </p>
              {ageData.length > 0 ? (
                <ResponsiveContainer width="100%" height={300}>
                  <BarChart
                    data={ageData}
                    margin={{ top: 5, right: 10, left: 0, bottom: 5 }}
                  >
                    <CartesianGrid strokeDasharray="3 3" stroke="#E2E8F0" />
                    <XAxis
                      dataKey="age_bin"
                      tick={{ fontSize: 11, fill: '#64748B' }}
                      axisLine={{ stroke: '#E2E8F0' }}
                      label={{ value: '年龄（岁）', position: 'insideBottom', offset: -5, fontSize: 11, fill: '#64748B' }}
                    />
                    <YAxis
                      tick={{ fontSize: 11, fill: '#64748B' }}
                      axisLine={{ stroke: '#E2E8F0' }}
                    />
                    <Tooltip
                      contentStyle={{
                        backgroundColor: '#FFFFFF',
                        border: '1px solid #E2E8F0',
                        borderRadius: '8px',
                        fontSize: '12px',
                      }}
                      formatter={(value: number) => [value.toLocaleString(), '住院病例']}
                      labelFormatter={(label: number) => `${label} 岁`}
                    />
                    <Bar dataKey="inpatient" fill="#3B82F6" name="住院" barSize={28} radius={[3, 3, 0, 0]} />
                  </BarChart>
                </ResponsiveContainer>
              ) : (
                <div className="text-center py-8 text-gray-400 text-sm">暂无数据</div>
              )}
            </div>

            {/* Chart 2: Gender Distribution Donut */}
            <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
              <div className="card p-4">
                <div className="text-[11px] font-medium text-gray-500 uppercase tracking-wide mb-4">
                  性别分布
                </div>
                {genderData.length > 0 && genderTotal > 0 ? (
                  <div className="relative">
                    <ResponsiveContainer width="100%" height={280}>
                      <PieChart>
                        <Pie
                          data={genderData}
                          cx="50%"
                          cy="50%"
                          innerRadius={55}
                          outerRadius={90}
                          paddingAngle={3}
                          dataKey="value"
                          nameKey="name"
                        >
                          {genderData.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.toLocaleString()} (${((value / genderTotal) * 100).toFixed(1)}%)`,
                            name,
                          ]}
                        />
                      </PieChart>
                    </ResponsiveContainer>
                    {/* Center label */}
                    <div className="absolute inset-0 flex items-center justify-center pointer-events-none">
                      <div className="text-center">
                        <div className="text-[24px] font-semibold text-gray-800">
                          {genderTotal.toLocaleString()}
                        </div>
                        <div className="text-[11px] text-gray-500">总计</div>
                      </div>
                    </div>
                    {/* Legend below */}
                    <div className="flex justify-center gap-6 mt-2">
                      {genderData.map((d) => (
                        <div key={d.name} className="flex items-center gap-2 text-[13px] text-gray-700">
                          <span
                            className="w-3 h-3 rounded-full inline-block"
                            style={{ backgroundColor: d.color }}
                          />
                          {d.name}: {d.value.toLocaleString()} ({((d.value / genderTotal) * 100).toFixed(1)}%)
                        </div>
                      ))}
                    </div>
                  </div>
                ) : (
                  <div className="text-center py-8 text-gray-400 text-sm">暂无数据</div>
                )}
              </div>

              {/* Placeholder for future chart or spacing */}
              <div className="hidden lg:block" />
            </div>

            {/* Chart 3: Age x Diagnosis Heatmap */}
            <div className="card p-4">
              <div className="text-[11px] font-medium text-gray-500 uppercase tracking-wide mb-1">
                年龄 × 诊断热力图
              </div>
              <p className="text-[11px] text-gray-400 mb-4">
                仅住院数据 — 显示各年龄段最常见的8种诊断
              </p>
              {heatmapData.matrix.length > 0 && heatmapData.diagnoses.length > 0 ? (
                <div className="overflow-x-auto">
                  <div
                    className="grid gap-px bg-gray-200 border border-gray-200 rounded-lg overflow-hidden"
                    style={{
                      gridTemplateColumns: `80px repeat(${heatmapData.diagnoses.length}, minmax(60px, 1fr))`,
                    }}
                  >
                    {/* Header row */}
                    <div className="bg-gray-100 px-2 py-2 text-[11px] font-medium text-gray-600">
                      年龄
                    </div>
                    {heatmapData.diagnoses.map((diag) => (
                      <div
                        key={diag}
                        className="bg-gray-100 px-2 py-2 text-[11px] font-medium text-gray-600 text-center"
                        title={diag}
                      >
                        {diag.length > 6 ? `${diag.slice(0, 6)}…` : diag}
                      </div>
                    ))}

                    {/* Data rows */}
                    {AGE_GROUPS.map((ag, rowIdx) => (
                      <Fragment key={ag}>
                        <div
                          key={`label-${ag}`}
                          className="bg-white px-2 py-2 text-[12px] text-gray-700 font-medium flex items-center"
                        >
                          {ag}
                        </div>
                        {heatmapData.matrix[rowIdx].map((value, colIdx) => (
                          <div
                            key={`${ag}-${colIdx}`}
                            className={`${getColorClass(value, heatmapMax)} px-2 py-2 text-center text-[12px] font-medium transition-colors cursor-default`}
                            title={`${ag}岁 | ${heatmapData.diagnoses[colIdx]}: ${value} 例`}
                          >
                            {value > 0 ? value.toLocaleString() : '-'}
                          </div>
                        ))}
                      </Fragment>
                    ))}
                  </div>
                </div>
              ) : (
                <div className="text-center py-8 text-gray-400 text-sm">暂无数据</div>
              )}
            </div>
          </>
        )}
      </div>
    </div>
  );
}
