/**
 * @fileoverview Quest management endpoints for Aurora API.
 * Provides CRUD operations for game quests.
 */

import type { RouteContext, RouteModule } from "./types";
import { jsonResponse, errorResponse, parseIdFromPath, withErrorHandling } from "./utils";
import { CreateQuestSchema, UpdateQuestSchema } from "@shared/modules/quest/quest.types";

/**
 * Quest routes handler.
 * 
 * Endpoints:
 * - GET /api/quests - List all quests
 * - POST /api/quests - Create a new quest
 * - PUT /api/quests/:id - Update an existing quest
 * - DELETE /api/quests/:id - Delete a quest
 */
async function handler(ctx: RouteContext): Promise<Response | null> {
    const { pathname, method, req } = ctx;

    // Only handle requests to /api/quests*
    if (!pathname.startsWith("/api/quests")) {
        return null;
    }

    const { questService } = await import("@shared/modules/quest/quest.service");

    /**
     * @route GET /api/quests
     * @description Returns all quests in the system.
     * @response 200 - `{ success: true, data: Quest[] }`
     * @response 500 - Error fetching quests
     * 
     * @example
     * // Response
     * {
     *   "success": true,
     *   "data": [
     *     {
     *       "id": 1,
     *       "name": "Daily Login",
     *       "description": "Login once to claim",
     *       "triggerEvent": "login",
     *       "requirements": { "target": 1 },
     *       "rewards": { "xp": 50, "balance": 100 }
     *     }
     *   ]
     * }
     */
    if (pathname === "/api/quests" && method === "GET") {
        return withErrorHandling(async () => {
            const quests = await questService.getAllQuests();
            return jsonResponse({
                success: true,
                data: quests.map(q => ({
                    id: q.id,
                    name: q.name,
                    description: q.description,
                    triggerEvent: q.triggerEvent,
                    requirements: q.requirements,
                    rewards: q.rewards,
                })),
            });
        }, "fetch quests");
    }

    /**
     * @route POST /api/quests
     * @description Creates a new quest.
     * 
     * @body {
     *   name: string,
     *   description?: string,
     *   triggerEvent: string,
     *   target: number,
     *   xpReward: number,
     *   balanceReward: number
     * }
     * @response 200 - `{ success: true, quest: Quest }`
     * @response 400 - Validation error
     * @response 500 - Error creating quest
     * 
     * @example
     * // Request
     * POST /api/quests
     * {
     *   "name": "Win 5 Battles",
     *   "description": "Defeat 5 enemies in combat",
     *   "triggerEvent": "battle_win",
     *   "target": 5,
     *   "xpReward": 200,
     *   "balanceReward": 500
     * }
     */
    if (pathname === "/api/quests" && method === "POST") {
        return withErrorHandling(async () => {
            const rawData = await req.json();
            const parseResult = CreateQuestSchema.safeParse(rawData);

            if (!parseResult.success) {
                return Response.json({
                    error: "Invalid payload",
                    issues: parseResult.error.issues.map(i => ({ path: i.path, message: i.message }))
                }, { status: 400 });
            }

            const data = parseResult.data;
            const result = await questService.createQuest({
                name: data.name,
                description: data.description || "",
                triggerEvent: data.triggerEvent,
                requirements: { target: data.target },
                rewards: {
                    xp: data.xpReward,
                    balance: data.balanceReward
                }
            });

            return jsonResponse({ success: true, quest: result[0] });
        }, "create quest");
    }

    /**
     * @route PUT /api/quests/:id
     * @description Updates an existing quest by ID.
     * 
     * @param id - Quest ID (numeric)
     * @body Partial quest fields to update
     * @response 200 - `{ success: true, quest: Quest }`
     * @response 400 - Invalid quest ID or validation error
     * @response 404 - Quest not found
     * @response 500 - Error updating quest
     */
    if (pathname.match(/^\/api\/quests\/\d+$/) && method === "PUT") {
        const id = parseIdFromPath(pathname);
        if (!id) {
            return errorResponse("Invalid quest ID", 400);
        }

        return withErrorHandling(async () => {
            const rawData = await req.json();
            const parseResult = UpdateQuestSchema.safeParse(rawData);

            if (!parseResult.success) {
                return Response.json({
                    error: "Invalid payload",
                    issues: parseResult.error.issues.map(i => ({ path: i.path, message: i.message }))
                }, { status: 400 });
            }

            const data = parseResult.data;
            const result = await questService.updateQuest(id, {
                ...(data.name !== undefined && { name: data.name }),
                ...(data.description !== undefined && { description: data.description }),
                ...(data.triggerEvent !== undefined && { triggerEvent: data.triggerEvent }),
                ...(data.target !== undefined && { requirements: { target: data.target } }),
                ...((data.xpReward !== undefined || data.balanceReward !== undefined) && {
                    rewards: {
                        xp: data.xpReward ?? 0,
                        balance: data.balanceReward ?? 0
                    }
                })
            });

            if (!result || result.length === 0) {
                return errorResponse("Quest not found", 404);
            }

            return jsonResponse({ success: true, quest: result[0] });
        }, "update quest");
    }

    /**
     * @route DELETE /api/quests/:id
     * @description Deletes a quest by ID.
     * 
     * @param id - Quest ID (numeric)
     * @response 200 - `{ success: true, deleted: number }`
     * @response 400 - Invalid quest ID
     * @response 404 - Quest not found
     * @response 500 - Error deleting quest
     */
    if (pathname.match(/^\/api\/quests\/\d+$/) && method === "DELETE") {
        const id = parseIdFromPath(pathname);
        if (!id) {
            return errorResponse("Invalid quest ID", 400);
        }

        return withErrorHandling(async () => {
            const result = await questService.deleteQuest(id);

            if (!result || result.length === 0) {
                return errorResponse("Quest not found", 404);
            }

            return jsonResponse({ success: true, deleted: (result[0] as { id: number }).id });
        }, "delete quest");
    }

    return null;
}

export const questsRoutes: RouteModule = {
    name: "quests",
    handler
};
