import React, { useCallback, useEffect, useState } from 'react';
import { DatePicker, Button, Modal } from 'antd';
import { Download } from 'lucide-react';
import dayjs, { type Dayjs } from 'dayjs';
import {
  Bar,
  BarChart,
  CartesianGrid,
  Legend,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from 'recharts';
import { toast } from 'sonner';
import {
  materialStatisticsApi,
  toStatArray,
  type CabinetStatRow,
  type MaterialsTypeCountRow,
} from '../../../api/material/statistics';
import { downloadBlob } from '../materialListUtils';
import { MaterialPageRoot } from '../MaterialPageLayout';
import {
  chartMinWidth,
  formatDateTimeRangeFromRangePicker,
  getDefaultDateRange,
  STAT_BLUE,
  STAT_GREEN,
  STAT_ORANGE,
} from '../materialStatisticsRangeUtils';

function ChartFrame({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <div className="overflow-hidden rounded-lg border border-gray-200 bg-white p-2 shadow-sm">
      <h3 className="mb-1 text-center text-sm font-medium text-gray-800">{title}</h3>
      {/* Recharts ResponsiveContainer 需要父级有确定像素高度，避免 flex h-full 链得到 0 高度导致整块空白 */}
      {children}
    </div>
  );
}

function ScrollBarHost({ categories: n, children }: { categories: number; children: React.ReactNode }) {
  return (
    <div className="w-full overflow-x-auto">
      <div className="h-[380px] w-full" style={{ minWidth: chartMinWidth(n) }}>
        {children}
      </div>
    </div>
  );
}

export default function MaterialBaseDataStatisticsPage() {
  const [[startD, endD], setRange] = useState<[Dayjs, Dayjs]>(() => {
    const [a, b] = getDefaultDateRange();
    return [dayjs(a), dayjs(b)];
  });
  const [q, setQ] = useState(() => formatDateTimeRangeFromRangePicker(startD, endD));
  const [ex, setEx] = useState(false);

  const syncQ = useCallback((a: Dayjs, b: Dayjs) => {
    setQ(formatDateTimeRangeFromRangePicker(a, b));
  }, []);

  useEffect(() => {
    syncQ(startD, endD);
  }, [startD, endD, syncQ]);

  const onExport = () => {
    Modal.confirm({
      title: '确认导出',
      content: '是否导出当前统计区间下的基础数据表？',
      onOk: async () => {
        setEx(true);
        try {
          const blob = await materialStatisticsApi.exportBaseData({ startTime: q.startTime, endTime: q.endTime });
          downloadBlob(blob as Blob, '基础数据.xls');
          toast.success('已开始下载');
        } catch (e: any) {
          toast.error(e?.message || '导出失败');
        } finally {
          setEx(false);
        }
      },
    });
  };

  return (
    <MaterialPageRoot>
      <div className="mb-4 flex flex-wrap items-center gap-3">
        <span className="text-sm text-gray-700">统计区间：</span>
        <DatePicker.RangePicker
          value={[startD, endD]}
          showTime
          onChange={(vals) => {
            if (vals?.[0] && vals[1]) {
              setRange([vals[0], vals[1]]);
            }
          }}
        />
        <Button type="default" icon={<Download className="h-4 w-4" />} loading={ex} onClick={onExport} className="border-amber-500 text-amber-600">
          导出数据表
        </Button>
      </div>
      <div className="grid grid-cols-1 gap-6 lg:grid-cols-2 lg:gap-8">
        <OpenCountPanel q={q} />
        <AnomalyPanel q={q} />
        <SpecialityPanel q={q} />
        <ChangePanel q={q} />
      </div>
    </MaterialPageRoot>
  );
}

function OpenCountPanel({ q }: { q: { startTime: string; endTime: string } }) {
  const params = { startTime: q.startTime, endTime: q.endTime };
  const [rows, setRows] = useState<CabinetStatRow[]>([]);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    let ok = true;
    setLoading(true);
    materialStatisticsApi
      .getCabinetStatistics(params)
      .then((res) => {
        if (ok) setRows(toStatArray(res as CabinetStatRow[]));
      })
      .catch((e) => {
        console.error(e);
        if (ok) {
          setRows([]);
          toast.error('加载物资柜开关次数失败');
        }
      })
      .finally(() => {
        if (ok) setLoading(false);
      });
    return () => {
      ok = false;
    };
  }, [params.startTime, params.endTime]);
  const data = rows.map((r) => ({
    name: r.cabinetName || '-',
    开关次数: r.openCount ?? 0,
  }));
  return (
    <ChartFrame title="物资柜开关次数">
      {loading ? (
        <div className="flex min-h-[380px] items-center justify-center text-sm text-gray-500">加载中…</div>
      ) : data.length === 0 ? (
        <div className="flex min-h-[380px] items-center justify-center text-sm text-gray-500">暂无数据</div>
      ) : (
        <ScrollBarHost categories={data.length}>
          <ResponsiveContainer width="100%" height={380}>
            <BarChart data={data} margin={{ top: 8, right: 8, left: 4, bottom: 8 }}>
              <CartesianGrid strokeDasharray="3 3" className="stroke-gray-200" />
              <XAxis dataKey="name" tick={{ fontSize: 11 }} />
              <YAxis tick={{ fontSize: 11 }} name="次数" label={{ value: '次数', angle: -90, position: 'insideLeft' }} />
              <Tooltip />
              <Legend />
              <Bar dataKey="开关次数" fill={STAT_BLUE} maxBarSize={36} name="开关次数" />
            </BarChart>
          </ResponsiveContainer>
        </ScrollBarHost>
      )}
    </ChartFrame>
  );
}

function AnomalyPanel({ q }: { q: { startTime: string; endTime: string } }) {
  const params = { startTime: q.startTime, endTime: q.endTime };
  const [rows, setRows] = useState<CabinetStatRow[]>([]);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    let ok = true;
    setLoading(true);
    materialStatisticsApi
      .getCabinetStatistics(params)
      .then((res) => {
        if (ok) setRows(toStatArray(res as CabinetStatRow[]));
      })
      .catch((e) => {
        console.error(e);
        if (ok) {
          setRows([]);
          toast.error('加载物资柜异常统计失败');
        }
      })
      .finally(() => {
        if (ok) setLoading(false);
      });
    return () => {
      ok = false;
    };
  }, [params.startTime, params.endTime]);
  const data = rows.map((r) => ({
    name: r.cabinetName || '-',
    物资错放: r.misplaceCount ?? 0,
    超时未关: r.openTimeoutCount ?? 0,
  }));
  return (
    <ChartFrame title="物资柜异常统计">
      {loading ? (
        <div className="flex min-h-[380px] items-center justify-center text-sm text-gray-500">加载中…</div>
      ) : data.length === 0 ? (
        <div className="flex min-h-[380px] items-center justify-center text-sm text-gray-500">暂无数据</div>
      ) : (
        <ScrollBarHost categories={data.length}>
          <ResponsiveContainer width="100%" height={380}>
            <BarChart data={data} margin={{ top: 8, right: 8, left: 4, bottom: 8 }}>
              <CartesianGrid strokeDasharray="3 3" className="stroke-gray-200" />
              <XAxis dataKey="name" tick={{ fontSize: 11 }} />
              <YAxis tick={{ fontSize: 11 }} name="次数" label={{ value: '次数', angle: -90, position: 'insideLeft' }} />
              <Tooltip />
              <Legend />
              <Bar dataKey="物资错放" stackId="a" fill={STAT_BLUE} name="物资错放" maxBarSize={40} />
              <Bar dataKey="超时未关" stackId="a" fill={STAT_GREEN} name="超时未关" maxBarSize={40} />
            </BarChart>
          </ResponsiveContainer>
        </ScrollBarHost>
      )}
    </ChartFrame>
  );
}

function SpecialityPanel({ q }: { q: { startTime: string; endTime: string } }) {
  const params = { startTime: q.startTime, endTime: q.endTime };
  const [rows, setRows] = useState<MaterialsTypeCountRow[]>([]);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    let ok = true;
    setLoading(true);
    materialStatisticsApi
      .getMaterialsStatusStatistics(params)
      .then((res) => {
        if (ok) setRows(toStatArray(res as MaterialsTypeCountRow[]));
      })
      .catch((e) => {
        console.error(e);
        if (ok) {
          setRows([]);
          toast.error('加载特殊状态物资统计失败');
        }
      })
      .finally(() => {
        if (ok) setLoading(false);
      });
    return () => {
      ok = false;
    };
  }, [params.startTime, params.endTime]);
  const data = rows.map((r) => ({
    name: r.materialsTypeName || '-',
    即将过期: r.willExpireCount ?? 0,
    已过期: r.expiredCount ?? 0,
    损坏数: r.badCount ?? 0,
  }));
  return (
    <ChartFrame title="特殊状态物资统计(当前时刻)">
      {loading ? (
        <div className="flex min-h-[380px] items-center justify-center text-sm text-gray-500">加载中…</div>
      ) : data.length === 0 ? (
        <div className="flex min-h-[380px] items-center justify-center text-sm text-gray-500">暂无数据</div>
      ) : (
        <ScrollBarHost categories={data.length}>
          <ResponsiveContainer width="100%" height={380}>
            <BarChart data={data} margin={{ top: 8, right: 8, left: 4, bottom: 8 }}>
              <CartesianGrid strokeDasharray="3 3" className="stroke-gray-200" />
              <XAxis dataKey="name" tick={{ fontSize: 11 }} />
              <YAxis tick={{ fontSize: 11 }} label={{ value: '个', angle: -90, position: 'insideLeft' }} />
              <Tooltip />
              <Legend />
              <Bar dataKey="即将过期" stackId="a" fill={STAT_BLUE} name="即将过期" maxBarSize={32} />
              <Bar dataKey="已过期" stackId="a" fill={STAT_GREEN} name="已过期" maxBarSize={32} />
              <Bar dataKey="损坏数" stackId="a" fill={STAT_ORANGE} name="损坏数" maxBarSize={32} />
            </BarChart>
          </ResponsiveContainer>
        </ScrollBarHost>
      )}
    </ChartFrame>
  );
}

function ChangePanel({ q }: { q: { startTime: string; endTime: string } }) {
  const params = { startTime: q.startTime, endTime: q.endTime };
  const [rows, setRows] = useState<MaterialsTypeCountRow[]>([]);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    let ok = true;
    setLoading(true);
    materialStatisticsApi
      .getMaterialsChangeStatistics(params)
      .then((res) => {
        if (ok) setRows(toStatArray(res as MaterialsTypeCountRow[]));
      })
      .catch((e) => {
        console.error(e);
        if (ok) {
          setRows([]);
          toast.error('加载物资更换统计失败');
        }
      })
      .finally(() => {
        if (ok) setLoading(false);
      });
    return () => {
      ok = false;
    };
  }, [params.startTime, params.endTime]);
  const data = rows.map((r) => ({
    name: r.materialsTypeName || '-',
    正常更换次数: r.allCount ?? 0,
    过期更换次数: r.expireCount ?? 0,
    损坏更换次数: r.badCount ?? 0,
  }));
  return (
    <ChartFrame title="物资更换统计">
      {loading ? (
        <div className="flex min-h-[380px] items-center justify-center text-sm text-gray-500">加载中…</div>
      ) : data.length === 0 ? (
        <div className="flex min-h-[380px] items-center justify-center text-sm text-gray-500">暂无数据</div>
      ) : (
        <ScrollBarHost categories={data.length}>
          <ResponsiveContainer width="100%" height={380}>
            <BarChart data={data} margin={{ top: 8, right: 8, left: 4, bottom: 8 }}>
              <CartesianGrid strokeDasharray="3 3" className="stroke-gray-200" />
              <XAxis dataKey="name" tick={{ fontSize: 11 }} />
              <YAxis tick={{ fontSize: 11 }} label={{ value: '次数', angle: -90, position: 'insideLeft' }} />
              <Tooltip />
              <Legend />
              <Bar dataKey="正常更换次数" stackId="a" fill={STAT_BLUE} name="正常更换次数" maxBarSize={32} />
              <Bar dataKey="过期更换次数" stackId="a" fill={STAT_GREEN} name="过期更换次数" maxBarSize={32} />
              <Bar dataKey="损坏更换次数" stackId="a" fill={STAT_ORANGE} name="损坏更换次数" maxBarSize={32} />
            </BarChart>
          </ResponsiveContainer>
        </ScrollBarHost>
      )}
    </ChartFrame>
  );
}
