import { NextRequest, NextResponse } from "next/server";
import prisma from "@/app/prisma";
import Fuse from 'fuse.js';
import { Site } from "@/app/types";
import { z } from "zod/v4";

const schema = z.object({
    currentPage: z.string().optional(),
    itemPerPage: z.string().optional(),
    search: z.string().optional(),
});

export async function GET(request: NextRequest) {
    const { searchParams } = request.nextUrl;
    const currentPage = Number(schema.parse({ currentPage: searchParams.get("currentPage") }).currentPage) || 1;
    const itemPerPage = Number(schema.parse({ itemPerPage: searchParams.get("itemPerPage") }).itemPerPage) || 10;
    const search = schema.parse({ search: searchParams.get("search") }).search || "";

    try {
        if (!search) {
            const skip = (currentPage - 1) * itemPerPage;
            const take = itemPerPage;

            const sites = await prisma.site.findMany({
                skip,
                take,
                orderBy: {
                    name: 'asc',
                },
                include: {
                    networks: {
                        orderBy: {
                            name: 'asc',
                        },
                    },
                },
            });

            const total = await prisma.site.count();
            return NextResponse.json({ sites, total, currentPage, itemPerPage }, { status: 200 });
        }

        const allSites = await prisma.site.findMany({
            include: {
                networks: {
                    orderBy: {
                        name: 'asc',
                    },
                },
            },
        });

        const fuseOptions = {
            includeScore: true,
            threshold: 0.4,
            keys: ['name', 'description', 'networks.name']
        };

        const fuse = new Fuse(allSites, fuseOptions);
        const searchResults = fuse.search(search);

        const filteredSites = searchResults.map(result => {
            const item = result.item;
            return {
                ...item,
                id: String(item.id),
                networks: item.networks?.map(network => ({
                    ...network,
                    id: String(network.id),
                    siteId: String(network.siteId)
                })) || []
            } as unknown as Site;
        });
        const total = filteredSites.length;

        const startIndex = (currentPage - 1) * itemPerPage;
        const endIndex = startIndex + itemPerPage;
        const paginatedSites = filteredSites.slice(startIndex, endIndex);

        return NextResponse.json({ 
            sites: paginatedSites, 
            total, 
            currentPage, 
            itemPerPage 
        }, { status: 200 });
    } catch (error: any) {
        if(error instanceof z.ZodError) {
            return NextResponse.json({ error: error.issues[0].message }, { status: 400 });
        }
        return NextResponse.json({ error: "Internal Server Error" }, { status: 500 });
    }
}
