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 DayLoanStatRow,
  type MaterialsLoanStatRow,
} 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 dayLabel(d: DayLoanStatRow) {
  return d.day || d.date || '-';
}

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>
      {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 MaterialClaimReturnStatisticsPage() {
  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.exportClaimAndReturn({
            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">
        <DailyPanel q={q} />
        <LendingPanel q={q} />
        <CollectionPanel q={q} />
        <ReturnPanel q={q} />
      </div>
    </MaterialPageRoot>
  );
}

function DailyPanel({ q }: { q: { startTime: string; endTime: string } }) {
  const params = { startTime: q.startTime, endTime: q.endTime };
  const [rows, setRows] = useState<DayLoanStatRow[]>([]);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    let ok = true;
    setLoading(true);
    materialStatisticsApi
      .getDayLoanStatistics(params)
      .then((res) => {
        if (!ok) return;
        const list = toStatArray(res as DayLoanStatRow[]);
        const sorted = [...list].sort((a, b) => {
          const da = new Date((a.day || a.date || '') as string).getTime();
          const db = new Date((b.day || b.date || '') as string).getTime();
          return da - db;
        });
        setRows(sorted);
      })
      .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: dayLabel(r),
    累计领取次数: r.allCount ?? 0,
    累计正常归还次数: r.returnCount ?? 0,
    累计超时归还次数: r.timeoutCount ?? 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} name="累计领取次数" maxBarSize={28} />
              <Bar dataKey="累计正常归还次数" fill={STAT_GREEN} name="累计正常归还次数" maxBarSize={28} />
              <Bar dataKey="累计超时归还次数" fill={STAT_ORANGE} name="累计超时归还次数" maxBarSize={28} />
            </BarChart>
          </ResponsiveContainer>
        </ScrollBarHost>
      )}
    </ChartFrame>
  );
}

function LendingPanel({ q }: { q: { startTime: string; endTime: string } }) {
  const params = { startTime: q.startTime, endTime: q.endTime };
  const [rows, setRows] = useState<MaterialsLoanStatRow[]>([]);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    let ok = true;
    setLoading(true);
    materialStatisticsApi
      .getMaterialsLoanStatistics(params)
      .then((res) => {
        if (ok) setRows(toStatArray(res as MaterialsLoanStatRow[]));
      })
      .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) => {
    const sec = r.averageTime ?? 0;
    const hours = parseFloat((sec / 3600).toFixed(2));
    return { name: r.materialsTypeName || '-', 平均借出时长: hours };
  });
  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="平均借出时长" fill={STAT_BLUE} name="平均借出时长(小时)" maxBarSize={32} />
            </BarChart>
          </ResponsiveContainer>
        </ScrollBarHost>
      )}
    </ChartFrame>
  );
}

function CollectionPanel({ q }: { q: { startTime: string; endTime: string } }) {
  const params = { startTime: q.startTime, endTime: q.endTime };
  const [rows, setRows] = useState<MaterialsLoanStatRow[]>([]);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    let ok = true;
    setLoading(true);
    materialStatisticsApi
      .getMaterialsLoanStatistics(params)
      .then((res) => {
        if (ok) setRows(toStatArray(res as MaterialsLoanStatRow[]));
      })
      .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 }));
  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} name="领取次数" maxBarSize={36} />
            </BarChart>
          </ResponsiveContainer>
        </ScrollBarHost>
      )}
    </ChartFrame>
  );
}

function ReturnPanel({ q }: { q: { startTime: string; endTime: string } }) {
  const params = { startTime: q.startTime, endTime: q.endTime };
  const [rows, setRows] = useState<MaterialsLoanStatRow[]>([]);
  const [loading, setLoading] = useState(true);
  useEffect(() => {
    let ok = true;
    setLoading(true);
    materialStatisticsApi
      .getMaterialsLoanStatistics(params)
      .then((res) => {
        if (ok) setRows(toStatArray(res as MaterialsLoanStatRow[]));
      })
      .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.returnCount ?? 0,
    超时归还次数: r.timeoutCount ?? 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={36} />
              <Bar dataKey="超时归还次数" stackId="a" fill={STAT_GREEN} name="超时归还次数" maxBarSize={36} />
            </BarChart>
          </ResponsiveContainer>
        </ScrollBarHost>
      )}
    </ChartFrame>
  );
}
