import type { HistoryLocationRow, TrackPlaybackEvent, TrackPlaybackResponse } from '../../api/types';
import { downloadBlob } from './download';

export const TRACK_ADDRESS_SETTLE_MS = 650;

export type TrackAddressCoordinate = { longitude: number; latitude: number; key: string };

export function trackAddressCoordinate(longitude?: number, latitude?: number): TrackAddressCoordinate | undefined {
  if (!Number.isFinite(longitude) || !Number.isFinite(latitude)
    || Math.abs(longitude ?? 0) > 180 || Math.abs(latitude ?? 0) > 90
    || (longitude === 0 && latitude === 0)) return undefined;
  const roundedLongitude = Number(longitude!.toFixed(4));
  const roundedLatitude = Number(latitude!.toFixed(4));
  return {
    longitude: roundedLongitude,
    latitude: roundedLatitude,
    key: `${roundedLongitude.toFixed(4)},${roundedLatitude.toFixed(4)}`
  };
}

export function formatDuration(seconds: number) {
  const safe = Math.max(0, Math.floor(seconds || 0));
  const hours = Math.floor(safe / 3600);
  const minutes = Math.floor((safe % 3600) / 60);
  const remainder = safe % 60;
  return [hours, minutes, remainder].map((value) => String(value).padStart(2, '0')).join(':');
}

export function sampledEventIndex(event: TrackPlaybackEvent, sampledCount: number, originalCount: number) {
  if (sampledCount <= 1 || originalCount <= 1) return 0;
  if (Number.isInteger(event.sampledIndex) && event.sampledIndex >= 0) {
    return Math.min(sampledCount - 1, event.sampledIndex);
  }
  return Math.max(0, Math.min(sampledCount - 1, Math.round(event.index * (sampledCount - 1) / (originalCount - 1))));
}

export function trackPlaybackInterval(speed: number) {
  return Math.max(55, 300 / Math.max(0.5, speed));
}

export function buildTrackRailSelection(track?: TrackPlaybackResponse) {
  const pointCount = track?.points.length ?? 0;
  const stopIndexesByPoint: Array<number[] | undefined> = new Array(pointCount);
  const eventIndexesByPoint: Array<number[] | undefined> = new Array(pointCount);
  if (!track || pointCount === 0) return { stopIndexesByPoint, eventIndexesByPoint };

  track.stops.forEach((stop, stopIndex) => {
    for (let offset = -1; offset <= 1; offset += 1) {
      const pointIndex = stop.sampledIndex + offset;
      if (pointIndex < 0 || pointIndex >= pointCount) continue;
      (stopIndexesByPoint[pointIndex] ??= []).push(stopIndex);
    }
  });
  track.events.forEach((event, eventIndex) => {
    const pointIndex = sampledEventIndex(event, pointCount, track.summary.pointCount);
    (eventIndexesByPoint[pointIndex] ??= []).push(eventIndex);
  });
  return { stopIndexesByPoint, eventIndexesByPoint };
}

function csvCell(value: unknown) {
  const text = String(value ?? '');
  return /[",\n]/.test(text) ? `"${text.replace(/"/g, '""')}"` : text;
}

export function trackCsv(track: TrackPlaybackResponse) {
  const headers = ['VIN', '车牌', '协议', '设备时间', '服务时间', '经度', '纬度', '速度(km/h)', '总里程(km)'];
  const rows = track.points.map((point) => [point.vin, point.plate, point.protocol, point.deviceTime, point.serverTime, point.longitude, point.latitude, point.speedKmh, point.totalMileageKm]);
  return `\uFEFF${[headers, ...rows].map((row) => row.map(csvCell).join(',')).join('\n')}`;
}

export function downloadTrackCsv(track: TrackPlaybackResponse) {
  const blob = new Blob([trackCsv(track)], { type: 'text/csv;charset=utf-8' });
  downloadBlob(blob, `track-${track.plate || track.vin}-${track.summary.startTime.slice(0, 10) || 'latest'}.csv`);
}

export function validTrackPoints(points: HistoryLocationRow[]) {
  return points.filter((point) => Number.isFinite(point.longitude) && Number.isFinite(point.latitude) && point.longitude >= 73 && point.longitude <= 135 && point.latitude >= 18 && point.latitude <= 54);
}
