import { prisma } from "@/core/prisma";

/**
 * Utilitaire de navigation dans une route logistique.
 * Types d'étapes : PRODUCTION (stationId) et TRANSPORT (destinationStationId).
 */

export interface ResolvedRoute {
    id: string;
    steps: ResolvedStep[];
}

export interface ResolvedStep {
    id: string;
    position: number;
    stepType: "PRODUCTION" | "TRANSPORT";
    stationId: string | null;
    destinationStationId: string | null;
    handlerMode: string | null;
    assignedRunnerId: string | null;
}

/**
 * Résout la route logistique par ID.
 * Permet de naviguer à partir du snapshot stocké sur l'order item.
 * Options :
 * - allowInactive : conserve les routes inactives pendant le cycle de vie de l'item
 */
export async function resolveRouteById(
    routeId: string,
    options?: { allowInactive?: boolean }
): Promise<ResolvedRoute | null> {
    const route = await prisma.logisticsRoute.findFirst({
        where: {
            id: routeId,
            ...(options?.allowInactive ? {} : { active: true })
        },
        include: {
            steps: { orderBy: { position: "asc" } },
        },
    });

    if (!route) return null;

    return {
        id: route.id,
        steps: route.steps.map((s) => ({
            id: s.id,
            position: s.position,
            stepType: s.stepType as ResolvedStep["stepType"],
            stationId: s.stationId,
            destinationStationId: s.destinationStationId,
            handlerMode: s.handlerMode,
            assignedRunnerId: s.assignedRunnerId,
        })),
    };
}

/**
 * Résout la route logistique pour un produit donné.
 * Priorité : product.logisticsRouteId > shop.defaultLogisticsRouteId > null
 */
export async function resolveRouteForProduct(
    productId: string,
    shopId: string
): Promise<ResolvedRoute | null> {
    const product = await prisma.product.findUnique({
        where: { id: productId },
        select: { logisticsRouteId: true },
    });

    let routeId = product?.logisticsRouteId ?? null;

    if (!routeId) {
        const shop = await prisma.shop.findUnique({
            where: { id: shopId },
            select: { defaultLogisticsRouteId: true },
        });
        routeId = shop?.defaultLogisticsRouteId ?? null;
    }

    if (!routeId) return null;

    return resolveRouteById(routeId);
}

/**
 * Trouve la première étape PRODUCTION dans une route.
 */
export function findFirstProductionStep(route: ResolvedRoute): ResolvedStep | null {
    return route.steps.find((s) => s.stepType === "PRODUCTION") ?? null;
}

/**
 * Trouve l'étape suivante après la position donnée.
 */
export function findNextStep(route: ResolvedRoute, currentPosition: number): ResolvedStep | null {
    return route.steps.find((s) => s.position > currentPosition) ?? null;
}

/**
 * Trouve la prochaine étape TRANSPORT après la position donnée.
 */
export function findNextTransport(route: ResolvedRoute, currentPosition: number): ResolvedStep | null {
    return route.steps.find((s) => s.position > currentPosition && s.stepType === "TRANSPORT") ?? null;
}

/**
 * Détermine ce qui se passe quand un runner "livre" un item.
 * On est à une étape TRANSPORT. On regarde l'étape suivante :
 * - PRODUCTION → l'item retourne en PENDING à la nouvelle station
 * - Rien après  → c'est la fin de la route → DELIVERED
 */
export function resolveDeliveryOutcome(
    route: ResolvedRoute,
    currentPosition: number
): { action: "next_production"; step: ResolvedStep } | { action: "delivered"; destinationStationId: string | null } {
    const currentStep = route.steps.find((s) => s.position === currentPosition);
    const nextStep = findNextStep(route, currentPosition);

    if (nextStep && nextStep.stepType === "PRODUCTION") {
        return { action: "next_production", step: nextStep };
    }

    // Pas de step suivante ou step suivante pas PRODUCTION → livraison finale
    // La destination est celle du TRANSPORT courant
    return {
        action: "delivered",
        destinationStationId: currentStep?.destinationStationId ?? null,
    };
}

/**
 * Données à écrire sur l'OrderItem pour positionner l'item à une étape donnée.
 */
export function stepUpdateData(route: ResolvedRoute, step: ResolvedStep) {
    return {
        logisticsRouteId: route.id,
        currentStepPosition: step.position,
        // Pour PRODUCTION : la station de production
        // Pour TRANSPORT : null (en transit)
        currentStepStationId: step.stationId ?? null,
    };
}
