import { CustomError } from "../../errors/custom.error.js";
import { routes } from "../../../data/mocks/routes.mock.js";
import { GpsUpdateDto } from "../../dtos/tracking/gps-update.dto.js";

export interface EtaResult {
  etaMinutes: number;
  arrivalWindow: { from: string; to: string };
  message: string;
}

// El destino real (cuando el camión está en tu colonia) es positionId=5,
// donde speed=0. positionId=4 es el "punto de alerta de proximidad" (~12 min antes).
const ARRIVAL_POSITION_ID = 5;
const WINDOW_MARGIN_MIN = 5;

export class CalculateEtaUseCase {
  execute(gps: GpsUpdateDto): EtaResult {
    const route = routes.find((r) => r.routeId === gps.routeId);
    if (!route) {
      throw CustomError.notFound(`Route ${gps.routeId} not found`);
    }

    if (gps.status === "FALLA") {
      return {
        etaMinutes: -1,
        arrivalWindow: { from: "--:--", to: "--:--" },
        message:
          "La ruta presenta una falla mecánica. La recolección puede retrasarse.",
      };
    }

    const target = route.positions.find(
      (p) => p.positionId === ARRIVAL_POSITION_ID,
    );
    if (!target) {
      throw CustomError.internalServer(
        `Route ${route.routeId} has no arrival position`,
      );
    }

    const nowMs = new Date(gps.timestamp ?? new Date().toISOString()).getTime();
    const targetMs = new Date(target.timestamp).getTime();
    const etaMinutes = Math.round((targetMs - nowMs) / 60000);

    const fromDate = new Date(targetMs - WINDOW_MARGIN_MIN * 60000);
    const toDate = new Date(targetMs + WINDOW_MARGIN_MIN * 60000);
    const arrivalWindow = {
      from: this.toHHMM(fromDate),
      to: this.toHHMM(toDate),
    };

    let message: string;
    if (etaMinutes < 0) {
      message = `El camión ya pasó por tu zona (aprox. ${arrivalWindow.from} - ${arrivalWindow.to}).`;
    } else if (etaMinutes === 0) {
      message = "El camión ya está en tu zona. Saca tus residuos ahora.";
    } else if (etaMinutes <= 15) {
      message = `Llega en aproximadamente ${etaMinutes} minutos.`;
    } else {
      message = `El camión llegará a tu zona entre las ${arrivalWindow.from} y ${arrivalWindow.to}.`;
    }

    return { etaMinutes, arrivalWindow, message };
  }

  private toHHMM(date: Date): string {
    const hh = String(date.getUTCHours()).padStart(2, "0");
    const mm = String(date.getUTCMinutes()).padStart(2, "0");
    return `${hh}:${mm}`;
  }
}