import { Button, Card, Select, Space, Table, Tag, Toast, Typography } from '@douyinfe/semi-ui';
import { useEffect, useMemo, useState } from 'react';
import { api } from '../api/client';
import type { DailyMileageRow, MileageStatistics, MileageTrendPoint } from '../api/types';
import { PageHeader } from '../components/PageHeader';

const DAY = 86_400_000;

type MileageFilters = {
  keyword: string;
  protocol: string;
  dateFrom: string;
  dateTo: string;
};

type MileageProps = {
  initialVin: string;
  initialProtocol?: string;
  initialFilters?: Record<string, string>;
  onFiltersChange?: (filters: Record<string, string>) => void;
  onOpenVehicle: (vin: string, protocol?: string) => void;
  onOpenHistory?: (filters: Record<string, string>) => void;
  onOpenRaw?: (filters: Record<string, string>) => void;
};

function localDate(value = new Date()) {
  const offset = value.getTimezoneOffset() * 60_000;
  return new Date(value.getTime() - offset).toISOString().slice(0, 10);
}

function defaultWindow(days = 30) {
  const end = new Date();
  return {
    dateFrom: localDate(new Date(end.getTime() - (days - 1) * DAY)),
    dateTo: localDate(end)
  };
}

function initialMileageFilters(initialVin: string, initialProtocol = '', initialFilters: Record<string, string> = {}): MileageFilters {
  const defaults = defaultWindow();
  return {
    keyword: initialFilters.keyword ?? initialVin,
    protocol: initialFilters.protocol ?? initialProtocol,
    dateFrom: initialFilters.dateFrom ?? defaults.dateFrom,
    dateTo: initialFilters.dateTo ?? defaults.dateTo
  };
}

function queryParams(filters: MileageFilters, pageSize?: number, offset?: number) {
  const params = new URLSearchParams({ dateFrom: filters.dateFrom, dateTo: filters.dateTo });
  if (filters.keyword.trim()) params.set('keyword', filters.keyword.trim());
  if (filters.protocol) params.set('protocol', filters.protocol);
  if (pageSize != null) params.set('limit', String(pageSize));
  if (offset != null) params.set('offset', String(offset));
  return params;
}

function sharedFilters(filters: MileageFilters): Record<string, string> {
  return Object.fromEntries(Object.entries(filters).filter(([, value]) => value.trim()));
}

function formatKm(value?: number) {
  if (value == null || !Number.isFinite(value)) return '—';
  return new Intl.NumberFormat('zh-CN', { maximumFractionDigits: 1 }).format(value);
}

function MileageTrendChart({ points }: { points: MileageTrendPoint[] }) {
  if (!points.length) {
    return <div className="vp-mileage-report-empty">当前日期范围没有里程数据</div>;
  }

  const width = 960;
  const height = 280;
  const left = 62;
  const right = 22;
  const top = 18;
  const bottom = 42;
  const max = Math.max(...points.map((point) => point.mileageKm), 1);
  const x = (index: number) => left + (width - left - right) * (points.length === 1 ? 0.5 : index / (points.length - 1));
  const y = (value: number) => top + (height - top - bottom) * (1 - value / max);
  const path = points.map((point, index) => `${index === 0 ? 'M' : 'L'}${x(index).toFixed(1)},${y(point.mileageKm).toFixed(1)}`).join(' ');
  const labelIndexes = Array.from(new Set([0, Math.floor((points.length - 1) / 2), points.length - 1]));

  return (
    <div className="vp-mileage-report-chart-wrap">
      <svg viewBox={`0 0 ${width} ${height}`} role="img" aria-label="每日里程趋势图">
        <defs>
          <linearGradient id="mileage-area" x1="0" x2="0" y1="0" y2="1">
            <stop offset="0%" stopColor="#3370ff" stopOpacity="0.28" />
            <stop offset="100%" stopColor="#3370ff" stopOpacity="0.02" />
          </linearGradient>
        </defs>
        {[0, 0.5, 1].map((ratio) => (
          <g key={ratio}>
            <line className="vp-mileage-report-grid-line" x1={left} x2={width - right} y1={y(max * ratio)} y2={y(max * ratio)} />
            <text className="vp-mileage-report-axis-text" x={left - 10} y={y(max * ratio) + 4} textAnchor="end">
              {ratio === 0 ? '0' : formatKm(max * ratio)}
            </text>
          </g>
        ))}
        <path className="vp-mileage-report-area" d={`${path} L${x(points.length - 1)},${y(0)} L${x(0)},${y(0)} Z`} />
        <path className="vp-mileage-report-line" d={path} />
        {points.length <= 45 ? points.map((point, index) => (
          <circle key={point.date} className="vp-mileage-report-point" cx={x(index)} cy={y(point.mileageKm)} r="3.5">
            <title>{point.date}：{formatKm(point.mileageKm)} km，{point.vehicles} 辆</title>
          </circle>
        )) : null}
        {labelIndexes.map((index) => (
          <text
            key={index}
            className="vp-mileage-report-axis-text"
            x={x(index)}
            y={height - 12}
            textAnchor={index === 0 ? 'start' : index === points.length - 1 ? 'end' : 'middle'}
          >
            {points[index].date}
          </text>
        ))}
      </svg>
    </div>
  );
}

export function Mileage({
  initialVin,
  initialProtocol,
  initialFilters = {},
  onFiltersChange
}: MileageProps) {
  const initial = useMemo(
    () => initialMileageFilters(initialVin, initialProtocol, initialFilters),
    [initialVin, initialProtocol, JSON.stringify(initialFilters)]
  );
  const [draft, setDraft] = useState<MileageFilters>(initial);
  const [filters, setFilters] = useState<MileageFilters>(initial);
  const [statistics, setStatistics] = useState<MileageStatistics>();
  const [rows, setRows] = useState<DailyMileageRow[]>([]);
  const [loading, setLoading] = useState(true);
  const [pagination, setPagination] = useState({ currentPage: 1, pageSize: 20, total: 0 });

  const load = async (nextFilters: MileageFilters, page = 1, pageSize = pagination.pageSize) => {
    setLoading(true);
    try {
      const [stats, detail] = await Promise.all([
        api.mileageStatistics(queryParams(nextFilters)),
        api.dailyMileage(queryParams(nextFilters, pageSize, (page - 1) * pageSize))
      ]);
      setStatistics(stats);
      setRows(detail.items ?? []);
      setPagination({ currentPage: page, pageSize, total: detail.total ?? 0 });
    } catch (error) {
      Toast.error(error instanceof Error ? error.message : '里程数据加载失败');
      setStatistics(undefined);
      setRows([]);
      setPagination((current) => ({ ...current, currentPage: page, pageSize, total: 0 }));
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    setDraft(initial);
    setFilters(initial);
    void load(initial, 1, pagination.pageSize);
  }, [initial]);

  const applyFilters = (next: MileageFilters) => {
    if (!next.dateFrom || !next.dateTo) {
      Toast.warning('请选择完整的日期范围');
      return;
    }
    if (next.dateFrom > next.dateTo) {
      Toast.warning('开始日期不能晚于结束日期');
      return;
    }
    const days = Math.floor((new Date(next.dateTo).getTime() - new Date(next.dateFrom).getTime()) / DAY) + 1;
    if (days > 366) {
      Toast.warning('单次最多查询 366 个自然日');
      return;
    }
    const normalized = { ...next, keyword: next.keyword.trim() };
    setDraft(normalized);
    setFilters(normalized);
    onFiltersChange?.(sharedFilters(normalized));
    void load(normalized, 1, pagination.pageSize);
  };

  const setQuickRange = (days: number) => {
    const range = defaultWindow(days);
    applyFilters({ ...draft, ...range });
  };

  const summaryItems = [
    { label: '区间总里程', value: `${formatKm(statistics?.periodMileageKm)} km`, note: '按车辆和自然日归并' },
    { label: '统计车辆', value: statistics ? `${(statistics.vehicleCount ?? 0).toLocaleString()} 辆` : '—', note: `${statistics?.recordCount ?? 0} 个有效车辆日` },
    { label: '单车平均', value: `${formatKm(statistics?.averageMileagePerVin)} km`, note: '区间总里程 / 车辆数' },
    { label: '车日均里程', value: `${formatKm(statistics?.averageDailyMileageKm)} km`, note: '有效车辆日平均' }
  ];

  return (
    <div className="vp-page vp-mileage-report">
      <PageHeader
        title="车辆里程统计"
        description="选择车辆和日期范围，查看每日里程趋势与明细列表"
      />

      <Card bordered className="vp-mileage-report-filter-card" bodyStyle={{ padding: 0 }}>
        <form className="vp-mileage-report-filter" onSubmit={(event) => { event.preventDefault(); applyFilters(draft); }}>
          <label className="vp-mileage-report-vehicle-field">
            <span>车辆</span>
            <input
              value={draft.keyword}
              onChange={(event) => setDraft((current) => ({ ...current, keyword: event.target.value }))}
              placeholder="输入车牌或 VIN，留空查询全部车辆"
            />
          </label>
          <label>
            <span>开始日期</span>
            <input type="date" value={draft.dateFrom} max={draft.dateTo} onChange={(event) => setDraft((current) => ({ ...current, dateFrom: event.target.value }))} />
          </label>
          <label>
            <span>结束日期</span>
            <input type="date" value={draft.dateTo} min={draft.dateFrom} onChange={(event) => setDraft((current) => ({ ...current, dateTo: event.target.value }))} />
          </label>
          <label>
            <span>数据来源</span>
            <Select
              value={draft.protocol}
              placeholder="全部来源"
              onChange={(value) => setDraft((current) => ({ ...current, protocol: String(value ?? '') }))}
              style={{ width: '100%' }}
            >
              <Select.Option value="">全部来源</Select.Option>
              <Select.Option value="GB32960">GB32960</Select.Option>
              <Select.Option value="JT808">JT808</Select.Option>
              <Select.Option value="YUTONG_MQTT">YUTONG_MQTT</Select.Option>
            </Select>
          </label>
          <Button htmlType="submit" theme="solid" type="primary" loading={loading}>查询</Button>
          <div className="vp-mileage-report-quick-ranges">
            <button type="button" onClick={() => setQuickRange(7)}>近 7 天</button>
            <button type="button" onClick={() => setQuickRange(30)}>近 30 天</button>
            <button type="button" onClick={() => setQuickRange(90)}>近 90 天</button>
          </div>
        </form>
      </Card>

      <section className="vp-mileage-report-kpis" aria-label="里程统计摘要">
        {summaryItems.map((item, index) => (
          <article key={item.label} className={index === 0 ? 'is-primary' : ''}>
            <span>{item.label}</span>
            <strong>{item.value}</strong>
            <small>{item.note}</small>
          </article>
        ))}
      </section>

      <Card
        bordered
        loading={loading}
        className="vp-mileage-report-chart-card"
        title={(
          <div className="vp-mileage-report-card-title">
            <div><strong>每日里程趋势</strong><span>{filters.dateFrom} 至 {filters.dateTo}</span></div>
            <Tag color="blue">{statistics?.trend?.length ?? 0} 个有效自然日</Tag>
          </div>
        )}
      >
        <MileageTrendChart points={statistics?.trend ?? []} />
      </Card>

      <Card
        bordered
        className="vp-mileage-report-table-card"
        title={(
          <div className="vp-mileage-report-card-title">
            <div><strong>里程明细</strong><span>按日期倒序展示每辆车的日里程</span></div>
            <Typography.Text type="tertiary">共 {pagination.total.toLocaleString()} 条</Typography.Text>
          </div>
        )}
      >
        <Table
          rowKey={(row) => row ? `${row.vin}-${row.date}-${row.source}` : 'mileage-row'}
          loading={loading}
          dataSource={rows}
          scroll={{ x: 900 }}
          pagination={{
            currentPage: pagination.currentPage,
            pageSize: pagination.pageSize,
            total: pagination.total,
            showSizeChanger: true,
            onPageChange: (page) => void load(filters, page, pagination.pageSize),
            onPageSizeChange: (pageSize) => void load(filters, 1, pageSize)
          }}
          empty={<div className="vp-mileage-report-empty">当前日期范围没有里程明细</div>}
          columns={[
            { title: '日期', dataIndex: 'date', width: 120 },
            { title: '车辆', width: 220, render: (_value, row: DailyMileageRow) => <div className="vp-mileage-report-vehicle"><strong>{row.plate || '未绑定车牌'}</strong><span>{row.vin}</span></div> },
            { title: '起始里程 (km)', dataIndex: 'startMileageKm', width: 140, render: (value: number) => formatKm(value) },
            { title: '结束里程 (km)', dataIndex: 'endMileageKm', width: 140, render: (value: number) => formatKm(value) },
            { title: '日里程 (km)', dataIndex: 'dailyMileageKm', width: 130, render: (value: number) => <strong className="vp-mileage-report-daily-value">{formatKm(value)}</strong> },
            { title: '来源', dataIndex: 'source', width: 120, render: (value: string) => <Tag color="blue">{value || '未知'}</Tag> }
          ]}
        />
      </Card>

      <footer className="vp-mileage-report-footnote">
        <span>趋势按车辆和自然日去重汇总</span>
        <span>更新时间：{statistics?.asOf || '—'}</span>
        <span>日期范围最多 366 天</span>
      </footer>
    </div>
  );
}
