import { GpsUpdateDtoValidator } from "../../dtos/index.js";
import { CalculateEtaUseCase, type EtaResult } from "./calculate-eta.use-case.js";
import {
  EvaluateNotificationUseCase,
  type EvaluatedNotification,
} from "./evaluate-notification.use-case.js";
import { routes } from "../../../data/mocks/routes.mock.js";
import { CustomError } from "../../errors/custom.error.js";
import type { RouteStateRepository } from "../../repositories/route-state.repository.js";
import type {
  InboxNotification,
  NotificationInboxRepository,
} from "../../repositories/notification-inbox.repository.js";

export interface ProcessGpsUpdateResponse {
  message: string;
  truck: { truckId: number; routeId: string; status: string };
  eta: EtaResult;
  notifications: EvaluatedNotification[];
}

export class ProcessGpsUpdateUseCase {
  constructor(
    private readonly calculateEta: CalculateEtaUseCase,
    private readonly evaluateNotification: EvaluateNotificationUseCase,
    private readonly routeState: RouteStateRepository,
    private readonly inbox: NotificationInboxRepository,
  ) {}

  async execute(data: unknown): Promise<ProcessGpsUpdateResponse> {
    const dto = GpsUpdateDtoValidator.validate(data);

    const route = routes.find((r) => r.routeId === dto.routeId);
    if (!route) {
      throw CustomError.notFound(`Route ${dto.routeId} not found`);
    }

    const eta = this.calculateEta.execute(dto);
    const notifications = await this.evaluateNotification.execute(dto);

    // 1) Guardar el estado actual de la ruta
    await this.routeState.set({
      routeId: route.routeId,
      currentPositionId: dto.positionId ?? 0,
      eta,
      status: dto.status,
      updatedAt: dto.timestamp ?? new Date().toISOString(),
    });

    // 2) Empujar cada notificación al buzón del usuario destinatario
    for (const n of notifications) {
      const item: InboxNotification = {
        id: `${n.userId}-${route.routeId}-${n.type}-${Date.now()}`,
        userId: n.userId,
        type: n.type,
        title: n.title,
        body: n.body,
        createdAt: new Date().toISOString(),
      };
      await this.inbox.addForUser(item);
    }

    return {
      message: "GPS update processed",
      truck: {
        truckId: route.truckId,
        routeId: route.routeId,
        status: dto.status,
      },
      eta,
      notifications,
    };
  }
}
