import { Button, Card, Form, Select, SideSheet, Space, Table, Tabs, Toast, Typography } from '@douyinfe/semi-ui';
import { IconRefresh, IconSearch } from '@douyinfe/semi-icons';
import { useEffect, useMemo, useState } from 'react';
import { api } from '../api/client';
import type { HistoryLocationRow, Page, RawFrameRow } from '../api/types';
import { PageHeader } from '../components/PageHeader';

type HistoryFilters = {
  vin?: string;
  protocol?: string;
  dateFrom?: string;
  dateTo?: string;
  fields?: string;
  includeFields?: boolean;
};

const defaultFilters: HistoryFilters = {
  vin: 'LB9A32A24R0LS1426',
  includeFields: false
};

const defaultPage = { items: [], total: 0, limit: 10, offset: 0 };

function canOpenVehicle(vin?: string) {
  const value = vin?.trim();
  return Boolean(value && value !== 'unknown');
}

export function History({ onOpenVehicle }: { onOpenVehicle: (vin: string) => void }) {
  const [filters, setFilters] = useState<HistoryFilters>(defaultFilters);
  const [locations, setLocations] = useState<Page<HistoryLocationRow>>(defaultPage);
  const [rawFrames, setRawFrames] = useState<Page<RawFrameRow>>(defaultPage);
  const [selectedRaw, setSelectedRaw] = useState<RawFrameRow | null>(null);
  const [loadingLocations, setLoadingLocations] = useState(false);
  const [loadingRaw, setLoadingRaw] = useState(false);
  const [locationPagination, setLocationPagination] = useState({ currentPage: 1, pageSize: 10 });
  const [rawPagination, setRawPagination] = useState({ currentPage: 1, pageSize: 10 });

  const buildParams = (nextFilters: HistoryFilters, limit: number, offset: number, raw: boolean) => {
    const params = new URLSearchParams({ limit: String(limit), offset: String(offset) });
    if (nextFilters.vin?.trim()) params.set('vin', nextFilters.vin.trim());
    if (nextFilters.protocol?.trim()) params.set('protocol', nextFilters.protocol.trim());
    if (nextFilters.dateFrom?.trim()) params.set('dateFrom', nextFilters.dateFrom.trim());
    if (nextFilters.dateTo?.trim()) params.set('dateTo', nextFilters.dateTo.trim());
    if (raw && nextFilters.includeFields) params.set('includeFields', 'true');
    if (raw && nextFilters.fields?.trim()) params.set('fields', nextFilters.fields.trim());
    return params;
  };

  const loadLocations = (nextFilters = filters, page = locationPagination.currentPage, pageSize = locationPagination.pageSize) => {
    setLoadingLocations(true);
    api.historyLocations(buildParams(nextFilters, pageSize, (page - 1) * pageSize, false))
      .then((nextPage) => {
        setLocations(nextPage);
        setLocationPagination({ currentPage: page, pageSize });
      })
      .catch((error: Error) => Toast.error(error.message))
      .finally(() => setLoadingLocations(false));
  };

  const loadRawFrames = (nextFilters = filters, page = rawPagination.currentPage, pageSize = rawPagination.pageSize) => {
    setLoadingRaw(true);
    api.rawFrames(buildParams(nextFilters, pageSize, (page - 1) * pageSize, true))
      .then((nextPage) => {
        setRawFrames(nextPage);
        setRawPagination({ currentPage: page, pageSize });
      })
      .catch((error: Error) => Toast.error(error.message))
      .finally(() => setLoadingRaw(false));
  };

  const submit = (values: Record<string, unknown>) => {
    const nextFilters: HistoryFilters = {
      vin: String(values.vin ?? ''),
      protocol: String(values.protocol ?? ''),
      dateFrom: String(values.dateFrom ?? ''),
      dateTo: String(values.dateTo ?? ''),
      fields: String(values.fields ?? ''),
      includeFields: Boolean(values.includeFields)
    };
    setFilters(nextFilters);
    loadLocations(nextFilters, 1, locationPagination.pageSize);
    loadRawFrames(nextFilters, 1, rawPagination.pageSize);
  };

  const reset = () => {
    setFilters(defaultFilters);
    loadLocations(defaultFilters, 1, locationPagination.pageSize);
    loadRawFrames(defaultFilters, 1, rawPagination.pageSize);
  };

  useEffect(() => {
    loadLocations(defaultFilters, 1, locationPagination.pageSize);
    loadRawFrames(defaultFilters, 1, rawPagination.pageSize);
  }, []);

  const rawFieldCount = useMemo(() => Object.keys(selectedRaw?.parsedFields ?? {}).length, [selectedRaw]);

  return (
    <div className="vp-page">
      <PageHeader title="历史查询" description="按车辆查询位置历史和 RAW 帧历史，协议作为来源过滤和诊断维度" />
      <Card bordered>
        <Form initValues={filters} layout="horizontal" onSubmit={(values) => submit(values)}>
          <Form.Input field="vin" label="VIN" placeholder="输入 VIN" style={{ width: 260 }} />
          <Form.Select field="protocol" label="协议" placeholder="全部协议" style={{ width: 190 }}>
            <Select.Option value="GB32960">GB32960</Select.Option>
            <Select.Option value="JT808">JT808</Select.Option>
            <Select.Option value="YUTONG_MQTT">YUTONG_MQTT</Select.Option>
          </Form.Select>
          <Form.Input field="dateFrom" label="开始时间" placeholder="2026-07-03 00:00:00" style={{ width: 210 }} />
          <Form.Input field="dateTo" label="结束时间" placeholder="2026-07-03 23:59:59" style={{ width: 210 }} />
          <Form.Checkbox field="includeFields" noLabel>
            返回解析字段
          </Form.Checkbox>
          <Form.TextArea
            field="fields"
            label="字段裁剪"
            placeholder="可选，逗号分隔，如 jt808.header.phone,jt808.location.longitude"
            autosize={{ minRows: 1, maxRows: 3 }}
            style={{ width: 420 }}
          />
          <Space align="start">
            <Button icon={<IconSearch />} htmlType="submit" theme="solid" type="primary">查询</Button>
            <Button icon={<IconRefresh />} onClick={reset}>重置</Button>
          </Space>
        </Form>
      </Card>
      <Card bordered style={{ marginTop: 16 }}>
        <Tabs>
          <Tabs.TabPane tab="位置历史" itemKey="location">
            <Table
              rowKey="deviceTime"
              dataSource={locations.items}
              loading={loadingLocations}
              pagination={{
                currentPage: locationPagination.currentPage,
                pageSize: locationPagination.pageSize,
                total: locations.total,
                showSizeChanger: true,
                onPageChange: (page) => loadLocations(filters, page, locationPagination.pageSize),
                onPageSizeChange: (pageSize) => loadLocations(filters, 1, pageSize)
              }}
              columns={[
                { title: 'VIN', dataIndex: 'vin', width: 190 },
                { title: '协议', dataIndex: 'protocol', width: 120 },
                { title: '经度', dataIndex: 'longitude', width: 120 },
                { title: '纬度', dataIndex: 'latitude', width: 120 },
                { title: '速度 km/h', dataIndex: 'speedKmh', width: 120 },
                { title: '总里程 km', dataIndex: 'totalMileageKm', width: 130 },
                { title: '设备时间', dataIndex: 'deviceTime', width: 190 },
                { title: '入库时间', dataIndex: 'serverTime', width: 190 },
                {
                  title: '操作',
                  width: 110,
                  render: (_: unknown, row: HistoryLocationRow) => (
                    <Button disabled={!canOpenVehicle(row.vin)} onClick={() => onOpenVehicle(row.vin)}>车辆服务</Button>
                  )
                }
              ]}
            />
          </Tabs.TabPane>
          <Tabs.TabPane tab="RAW 帧" itemKey="raw">
            <Table
              rowKey="id"
              dataSource={rawFrames.items}
              loading={loadingRaw}
              pagination={{
                currentPage: rawPagination.currentPage,
                pageSize: rawPagination.pageSize,
                total: rawFrames.total,
                showSizeChanger: true,
                onPageChange: (page) => loadRawFrames(filters, page, rawPagination.pageSize),
                onPageSizeChange: (pageSize) => loadRawFrames(filters, 1, pageSize)
              }}
              columns={[
                { title: 'ID', dataIndex: 'id', width: 260 },
                { title: 'VIN', dataIndex: 'vin', width: 190 },
                { title: '车牌', dataIndex: 'plate', width: 120 },
                { title: '协议', dataIndex: 'protocol', width: 120 },
                { title: '帧类型', dataIndex: 'frameType', width: 190 },
                { title: '大小 B', dataIndex: 'rawSizeBytes', width: 100 },
                { title: '设备时间', dataIndex: 'deviceTime', width: 190 },
                { title: '入库时间', dataIndex: 'serverTime', width: 190 },
                {
                  title: '操作',
                  width: 200,
                  render: (_: unknown, row: RawFrameRow) => (
                    <Space>
                      <Button onClick={() => setSelectedRaw(row)}>字段</Button>
                      <Button disabled={!canOpenVehicle(row.vin)} onClick={() => onOpenVehicle(row.vin)}>车辆服务</Button>
                    </Space>
                  )
                }
              ]}
            />
          </Tabs.TabPane>
        </Tabs>
      </Card>
      <SideSheet title="RAW 解析字段" visible={Boolean(selectedRaw)} onCancel={() => setSelectedRaw(null)} width={720}>
        <Space vertical align="start" spacing={12} style={{ width: '100%' }}>
          <Typography.Text type="tertiary">
            {selectedRaw?.protocol ?? '-'} / {selectedRaw?.plate || selectedRaw?.vin || '-'} / {rawFieldCount} 个字段
          </Typography.Text>
          {rawFieldCount === 0 ? (
            <Typography.Text type="secondary">当前查询未返回解析字段，请勾选“返回解析字段”或配置字段裁剪后重新查询。</Typography.Text>
          ) : null}
        </Space>
        <pre className="vp-json">{JSON.stringify(selectedRaw?.parsedFields ?? {}, null, 2)}</pre>
      </SideSheet>
    </div>
  );
}
