
import { getServerSession } from "next-auth";
import { authOptions } from "@/app/api/auth/[...nextauth]/auth-options";
import { UserRole } from "@prisma/client";
import { NextRequest, NextResponse } from "next/server";
import db from "@/lib/db";
import { DeleteFileById, UploadFIle } from "@/utils/backblaze";
import { getLogger } from "@/utils/logger";


const logger = getLogger("/api/admin/variants/[variantsId]");

export const DELETE = async (req: NextRequest, { params }: { params: { variantsId: string } }) => {
    try {
        const session = await getServerSession(authOptions);
        if (!session || session.user.role !== UserRole.ADMIN) {
            return new NextResponse("Forbidden", { status: 403 });
        }

        const variantsId = params.variantsId;

        const attachments = await db.attachments.findMany({
            where: {
                variant_id: parseInt(variantsId as string),
            }
        })

        for (let i = 0; i < attachments.length; i++) {
            const deleteRes = await DeleteFileById(attachments[i].file_id as string, attachments[i].file_name, process.env.BACKBLAZE_PUBLIC_BUCKET_ID ?? "")

        }

        await db.attachments.deleteMany({
            where: {
                variant_id: parseInt(variantsId as string),
            }
        })

        const deleteVariant = await db.productVariant.delete({
            where: {
                id: parseInt(variantsId as string),
            }
        })


        return NextResponse.json({ mssg: 'Variant deleted successfully' }, { status: 200 });
    } catch (error: any) {

        logger.error(`Failed to delete a variant ${params.variantsId}`, {
            error: error?.config?.data ?? error?.message ?? "Unknown error"
        });

        return new NextResponse("Internal Server Error", { status: 500 });
    }
}

export const GET = async (req: NextRequest, { params }: { params: { variantsId: string } }) => {
    try {
        const session = await getServerSession(authOptions);
        if (!session || session.user.role !== UserRole.ADMIN) {
            return new NextResponse("Forbidden", { status: 403 });
        }

        const variantsId = params.variantsId;

        const variant = await db.productVariant.findUnique({
            where: {
                id: parseInt(variantsId as string),
            },
            include: {
                variant_images: true,
            }
        })

        return NextResponse.json({ mssg: variant }, { status: 200 });
    }
    catch (error: any) {
        logger.error(`Failed to fetch a variant of id ${params.variantsId}`, {
            error: error?.config?.data ?? error?.message ?? "Unknown error"
        });
        return new NextResponse("Internal Server Error", { status: 500 });
    }
}

export const PUT = async (req: NextRequest, { params }: { params: { variantsId: string } }) => {
    try {
        const session = await getServerSession(authOptions);
        if (!session || session.user.role !== UserRole.ADMIN) {
            return new NextResponse("Forbidden", { status: 403 });
        }

        const variantsId = params.variantsId;

        const formData = await req.formData()
        const name = formData.get("name")
        const onSell = formData.get("onSell") === "true" ? true : false
        const productId = formData.get("productId")
        const regular_price = formData.get("regular_price")
        const purchase_cost = formData.get("purchase_cost")
        const special_price = formData.get("special_price")
        const quantity = formData.get("quantity")
        const imagesCount = formData.get("imagesCount")
        const wareHouseInfo = formData.get("wareHouseInfo")
        const deleteImagesCount = formData.get("deleteImagesCount")
        const specifications = formData.get("specifications")
        const deleteImages = []

        for (let i = 0; i < parseInt(deleteImagesCount as string); i++) {
            const deleteImage = formData.get(`deleteImages_${i}`)
            deleteImages.push(deleteImage)
        }

        const attachments = await db.attachments.findMany({
            where: {
                id: {
                    in: deleteImages.map((image) => parseInt(image as string))
                }
            }
        })

        // console.log(attachments)

        for (let i = 0; i < attachments.length; i++) {
            const deleteRes = await DeleteFileById(attachments[i].file_id as string, attachments[i].file_name, process.env.BACKBLAZE_PUBLIC_BUCKET_ID ?? "")
        }

        await db.attachments.deleteMany({
            where: {
                id: {
                    in: deleteImages.map((image) => parseInt(image as string))
                }
            }
        })


        const images = []

        for (let i = 0; i < parseInt(imagesCount as string); i++) {
            const image = formData.get(`images_${i}`)
            images.push(image)
        }
        const images2 = []

        for (let i = 0; i < images.length; i++) {
            const image = images[i] as File
            const fileName = image.name
            const fileType = image.type
            const fileContent = await image.arrayBuffer()
            const response = await UploadFIle(fileName, fileType, fileContent, process.env.BACKBLAZE_PUBLIC_BUCKET_ID ?? "")

            const imageUrl = response.fileUrl
            const fileId = response.fileId

            images2.push({
                imageUrl: imageUrl,
                fileId: fileId,
                fileName: fileName,
                fileType: fileType,
                fileContent: fileContent,
                uniqueFileName: response.UniqueFileName,
            })
        }

        const variant0 = await db.productVariant.findUnique({
            where: {
                id: parseInt(variantsId as string),
            },
            include: {
                product: {
                    include: {
                        category: true,
                    }
                }
            }

        })

        const variant = await db.productVariant.update({
            where: {
                id: parseInt(variantsId as string),
            },
            data: {
                product: { connect: { id: parseInt(productId as string) } },
                name: name as string,
                on_sell: onSell,
                regular_price: parseFloat(regular_price as string),
                purchase_cost: parseFloat(purchase_cost as string),
                special_price: parseFloat(special_price as string),
                quantity: parseInt(quantity as string),
                wareHouseInfo: wareHouseInfo as string,
                specs: specifications ? JSON.parse(specifications as string) : [],
                sku: generateSKU(variant0?.product_id as number, variant0?.product.category.name as string, parseInt(variantsId as string)),
                variant_images: {
                    create: images2.map((image) => ({
                        original_name: image.fileName,
                        file_name: image.uniqueFileName ?? "",
                        file_url: image.imageUrl ?? "",
                        file_id: image.fileId ?? "",
                        file_type: image.fileType,
                    }))
                },
            }
        })


        return NextResponse.json({ mssg: variant }, { status: 200 });
    }
    catch (error: any) {
        logger.error(`Failed to update a variant of id ${params.variantsId}`, {
            error: error?.config?.data ?? error?.message ?? "Unknown error"
        }); return new NextResponse("Internal Server Error", { status: 500 });
    }
}


function generateSKU(pid: number, category: string, vid: number) {
    return `${pid}-${category}-${vid}`
}


function generateUUIDWithTime() {
    const now = Date.now(); // milliseconds since Unix epoch
    const timePart = now.toString(16); // convert to hex for compactness

    const randomPart = 'xxxxxxxxxxxx'.replace(/[x]/g, function () {
        return (Math.random() * 16 | 0).toString(16);
    });

    return `${timePart}-${randomPart}`;
}