import { Request, Response } from "express";
import { z } from "zod";
import { asyncHandler } from "../../core/asyncHandler";
import { AppError } from "../../core/AppError";
import { OrderItemStatus } from "@prisma/client";
import { orderItemService } from "./orderItem.service";

const paramsSchema = z.object({
    id: z.string().uuid()
});

const bodySchema = z.object({
    status: z.nativeEnum(OrderItemStatus)
});

export const updateOrderItemStatus = asyncHandler(
    async (req: Request, res: Response) => {
        const { id } = paramsSchema.parse(req.params);
        const { status } = bodySchema.parse(req.body);
        const actorUserId = req.auth?.sub;

        const updated = await orderItemService.updateStatus(
            req.shop!.id,
            id,
            status,
            req.senderSocketId,
            actorUserId
        );

        res.json(updated);
    }
);

export const acknowledgeOrderItem = asyncHandler(
    async (req: Request, res: Response) => {
        const { id } = paramsSchema.parse(req.params);
        const userId = req.auth?.sub;

        if (!userId) {
            throw new AppError("Unauthorized", 401);
        }

        const updated = await orderItemService.acknowledgeItem(
            req.shop!.id,
            id,
            userId,
            req.senderSocketId
        );

        res.json(updated);
    }
);

export const markOrderItemReady = asyncHandler(
    async (req: Request, res: Response) => {
        const { id } = paramsSchema.parse(req.params);

        const updated = await orderItemService.updateStatus(
            req.shop!.id,
            id,
            OrderItemStatus.READY,
            req.senderSocketId
        );

        res.json(updated);
    }
);

const batchBodySchema = z.object({
    itemIds: z.array(z.string().uuid()).min(1).max(100),
    status: z.nativeEnum(OrderItemStatus)
});

const batchItemIdsSchema = z.object({
    itemIds: z.array(z.string().uuid()).min(1).max(100),
});

const customizationsBodySchema = z.object({
    recipeId: z.string().uuid().optional(),
    customizations: z.array(z.object({
        ingredientId: z.string().uuid(),
        action: z.enum(["ADDED", "REMOVED"]),
        quantity: z.number().int().min(1).optional().default(1),
    }))
});

export const setOrderItemCustomizations = asyncHandler(
    async (req: Request, res: Response) => {
        const { id } = paramsSchema.parse(req.params);
        const { recipeId, customizations } = customizationsBodySchema.parse(req.body);

        const updated = await orderItemService.setCustomizations(
            req.shop!.id,
            id,
            customizations,
            recipeId,
            req.senderSocketId
        );

        res.json(updated);
    }
);

export const batchUpdateOrderItemsStatus = asyncHandler(
    async (req: Request, res: Response) => {
        const { itemIds, status } = batchBodySchema.parse(req.body);
        const actorUserId = req.auth?.sub;

        const results = await orderItemService.batchUpdateStatus(
            req.shop!.id,
            itemIds,
            status,
            req.senderSocketId,
            actorUserId
        );

        res.json({ updated: results.length, items: results });
    }
);

export const batchAcknowledgeOrderItems = asyncHandler(
    async (req: Request, res: Response) => {
        const { itemIds } = batchItemIdsSchema.parse(req.body);
        const userId = req.auth?.sub;

        if (!userId) {
            throw new AppError("Unauthorized", 401);
        }

        const results = await orderItemService.batchAcknowledgeItems(
            req.shop!.id,
            itemIds,
            userId,
            req.senderSocketId,
        );

        res.json({ updated: results.length, items: results });
    }
);

export const batchMarkOrderItemsReady = asyncHandler(
    async (req: Request, res: Response) => {
        const { itemIds } = batchItemIdsSchema.parse(req.body);
        const actorUserId = req.auth?.sub;

        const results = await orderItemService.batchMarkReadyItems(
            req.shop!.id,
            itemIds,
            req.senderSocketId,
            actorUserId,
        );

        res.json({ updated: results.length, items: results });
    }
);

export const batchAdvanceOrderItemProductionSteps = asyncHandler(
    async (req: Request, res: Response) => {
        const { itemIds } = batchItemIdsSchema.parse(req.body);
        const actorUserId = req.auth?.sub;

        const results = await orderItemService.batchMovePreparingItemsStep(
            req.shop!.id,
            itemIds,
            "next",
            req.senderSocketId,
            actorUserId,
        );

        res.json({ updated: results.length, items: results });
    }
);

export const batchRevertOrderItemProductionSteps = asyncHandler(
    async (req: Request, res: Response) => {
        const { itemIds } = batchItemIdsSchema.parse(req.body);
        const actorUserId = req.auth?.sub;

        const results = await orderItemService.batchMovePreparingItemsStep(
            req.shop!.id,
            itemIds,
            "previous",
            req.senderSocketId,
            actorUserId,
        );

        res.json({ updated: results.length, items: results });
    }
);

/**
 * POST /order-items/:id/pick-up
 * Raccourci pour PICKED_UP — résout automatiquement la TransferRoute
 */
export const pickUpOrderItem = asyncHandler(
    async (req: Request, res: Response) => {
        const { id } = paramsSchema.parse(req.params);
        const actorUserId = req.auth?.sub;

        if (!actorUserId) {
            throw new AppError("Unauthorized", 401);
        }

        const updated = await orderItemService.updateStatus(
            req.shop!.id,
            id,
            OrderItemStatus.PICKED_UP,
            req.senderSocketId,
            actorUserId
        );

        res.json(updated);
    }
);

/**
 * POST /order-items/:id/deliver
 * Raccourci pour DELIVERED
 */
export const deliverOrderItem = asyncHandler(
    async (req: Request, res: Response) => {
        const { id } = paramsSchema.parse(req.params);
        const actorUserId = req.auth?.sub;

        const updated = await orderItemService.updateStatus(
            req.shop!.id,
            id,
            OrderItemStatus.DELIVERED,
            req.senderSocketId,
            actorUserId
        );

        res.json(updated);
    }
);

