import type { ProcessedTrack } from '../model/track.types';

type QueryTrackByMmsiParams = {
  mmsi: number;
  minutes: number;
  shipNameHint?: string;
  shipKindCodeHint?: string;
  nationalCodeHint?: string;
  isPermitted?: boolean;
};

export type QueryTrackByDateRangeParams = {
  mmsi: number;
  startTimeIso: string;
  endTimeIso: string;
  shipNameHint?: string;
  shipKindCodeHint?: string;
  nationalCodeHint?: string;
  isPermitted?: boolean;
};

type V2TrackResponse = {
  vesselId?: string;
  targetId?: string;
  sigSrcCd?: string;
  shipName?: string;
  shipKindCode?: string;
  nationalCode?: string;
  geometry?: [number, number][];
  timestamps?: Array<string | number>;
  speeds?: number[];
  totalDistance?: number;
  avgSpeed?: number;
  maxSpeed?: number;
  pointCount?: number;
  chnPrmShipInfo?: {
    name?: string;
    vesselType?: string;
    callsign?: string;
    imo?: number;
  };
};

function normalizeTimestampMs(value: string | number): number {
  if (typeof value === 'number') return value < 1e12 ? value * 1000 : value;
  if (/^\d{10,}$/.test(value)) {
    const asNum = Number(value);
    return asNum < 1e12 ? asNum * 1000 : asNum;
  }
  const parsed = new Date(value).getTime();
  return Number.isFinite(parsed) ? parsed : 0;
}

function toFiniteNumber(value: unknown): number | null {
  if (typeof value === 'number') return Number.isFinite(value) ? value : null;
  if (typeof value === 'string') {
    const parsed = Number(value.trim());
    return Number.isFinite(parsed) ? parsed : null;
  }
  return null;
}

function convertV2Tracks(rows: V2TrackResponse[]): ProcessedTrack[] {
  const out: ProcessedTrack[] = [];

  for (const row of rows) {
    if (!row.geometry || row.geometry.length === 0) continue;
    const timestamps = Array.isArray(row.timestamps) ? row.timestamps : [];
    const timestampsMs = timestamps.map((ts) => normalizeTimestampMs(ts));

    const sortedIndices = timestampsMs
      .map((_, idx) => idx)
      .sort((a, b) => timestampsMs[a] - timestampsMs[b]);

    const geometry: [number, number][] = [];
    const sortedTimes: number[] = [];
    const speeds: number[] = [];
    for (const idx of sortedIndices) {
      const coord = row.geometry?.[idx];
      if (!Array.isArray(coord) || coord.length !== 2) continue;
      const nLon = toFiniteNumber(coord[0]);
      const nLat = toFiniteNumber(coord[1]);
      if (nLon == null || nLat == null) continue;

      geometry.push([nLon, nLat]);
      sortedTimes.push(timestampsMs[idx]);
      speeds.push(toFiniteNumber(row.speeds?.[idx]) ?? 0);
    }

    if (geometry.length === 0) continue;

    const targetId = row.targetId || row.vesselId || '';
    const sigSrcCd = row.sigSrcCd || '000001';

    const chnName = row.chnPrmShipInfo?.name?.trim();

    out.push({
      vesselId: row.vesselId || `${sigSrcCd}_${targetId}`,
      targetId,
      sigSrcCd,
      shipName: chnName || (row.shipName || '').trim() || targetId,
      shipKindCode: row.shipKindCode || '000027',
      nationalCode: row.nationalCode || '',
      geometry,
      timestampsMs: sortedTimes,
      speeds,
      stats: {
        totalDistanceNm: row.totalDistance || 0,
        avgSpeed: row.avgSpeed || 0,
        maxSpeed: row.maxSpeed || 0,
        pointCount: row.pointCount || geometry.length,
      },
      chnPrmShipInfo: row.chnPrmShipInfo ? { ...row.chnPrmShipInfo } : undefined,
    });
  }

  return out;
}

async function fetchV2Tracks(
  startTimeIso: string,
  endTimeIso: string,
  mmsis: number[],
  hasPermitted: boolean,
): Promise<ProcessedTrack[]> {
  const base = (import.meta.env.VITE_TRACK_V2_BASE_URL || '/signal-batch').trim();

  const requestBody = {
    startTime: startTimeIso,
    endTime: endTimeIso,
    vessels: mmsis.map(String),
    includeChnPrmShip: hasPermitted,
  };

  const endpoint = `${base.replace(/\/$/, '')}/api/v2/tracks/vessels`;
  const res = await fetch(endpoint, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', accept: 'application/json' },
    body: JSON.stringify(requestBody),
  });

  if (!res.ok) {
    throw new Error(`Track API ${res.status}`);
  }

  const json = (await res.json()) as unknown;
  const rows = Array.isArray(json)
    ? (json as V2TrackResponse[])
    : Array.isArray((json as { data?: unknown }).data)
      ? ((json as { data: V2TrackResponse[] }).data)
      : [];

  return convertV2Tracks(rows);
}

export async function queryTrackByMmsi(params: QueryTrackByMmsiParams): Promise<ProcessedTrack[]> {
  const end = new Date();
  const start = new Date(end.getTime() - params.minutes * 60_000);
  return fetchV2Tracks(start.toISOString(), end.toISOString(), [params.mmsi], params.isPermitted ?? false);
}

export async function queryTrackByDateRange(params: QueryTrackByDateRangeParams): Promise<ProcessedTrack[]> {
  return fetchV2Tracks(params.startTimeIso, params.endTimeIso, [params.mmsi], params.isPermitted ?? false);
}

export type QueryMultiTrackParams = {
  mmsis: number[];
  startTimeIso: string;
  endTimeIso: string;
  hasPermitted: boolean;
};

export async function queryMultiTrack(params: QueryMultiTrackParams): Promise<ProcessedTrack[]> {
  return fetchV2Tracks(params.startTimeIso, params.endTimeIso, params.mmsis, params.hasPermitted);
}
