/**
 * Vendor-attributed SLA (2026-06-02) — single-vendor detail / edit / delete.
 *
 *   GET    /api/vendors/[id]   detail + computed SLA summary (30-day window)
 *   PUT    /api/vendors/[id]   edit (ADMIN/EDITOR)
 *   DELETE /api/vendors/[id]   soft-delete (ADMIN/EDITOR)
 *
 * GET supports ?windowDays=N to override the default 30-day rolling window.
 */
import { NextRequest, NextResponse } from 'next/server';
import { getServerSession } from 'next-auth/next';
import { authOptions } from '@/lib/auth';
import { prisma } from '@/lib/prisma';
import { parseJsonBounded, BodyTooLargeError, BodyParseError } from '@/lib/api-helpers/parse-json';
import { updateVendorSchema } from '@/lib/validations/vendor.schema';
import { computeVendorSla } from '@/lib/services/sla/vendor-sla.service';

const ROLES_WRITE = ['ADMIN', 'EDITOR'];

function parseWindowMinutes(req: NextRequest): number {
    const days = parseInt(new URL(req.url).searchParams.get('windowDays') || '30', 10);
    const clamped = Number.isFinite(days) && days > 0 ? Math.min(days, 365) : 30;
    return clamped * 24 * 60;
}

export async function GET(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
    const session = await getServerSession(authOptions);
    if (!session?.user?.id) {
        return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }

    const { id } = await params;
    const vendorId = parseInt(id, 10);
    if (!Number.isFinite(vendorId) || vendorId <= 0) {
        return NextResponse.json({ error: 'Invalid vendor id' }, { status: 400 });
    }

    const vendor = await prisma.vendor.findFirst({
        where: { id: vendorId, deletedAt: null },
        include: {
            monitors: {
                where: { deletedAt: null },
                select: { id: true, name: true, type: true, region: true },
                orderBy: { name: 'asc' },
            },
        },
    });
    if (!vendor) {
        return NextResponse.json({ error: 'Vendor not found' }, { status: 404 });
    }

    const summary = await computeVendorSla(vendorId, parseWindowMinutes(req));

    return NextResponse.json({ success: true, vendor, summary });
}

export async function PUT(req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
    const session = await getServerSession(authOptions);
    if (!session?.user?.id) {
        return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }
    const role = (session.user as { role?: string }).role;
    if (!role || !ROLES_WRITE.includes(role)) {
        return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
    }

    const { id } = await params;
    const vendorId = parseInt(id, 10);
    if (!Number.isFinite(vendorId) || vendorId <= 0) {
        return NextResponse.json({ error: 'Invalid vendor id' }, { status: 400 });
    }

    try {
        const raw = await parseJsonBounded<unknown>(req, { maxBytes: 64 * 1024 });
        const parsed = updateVendorSchema.safeParse(raw);
        if (!parsed.success) {
            return NextResponse.json(
                { error: 'Invalid vendor', details: parsed.error.flatten() },
                { status: 400 },
            );
        }

        const existing = await prisma.vendor.findFirst({ where: { id: vendorId, deletedAt: null }, select: { id: true } });
        if (!existing) {
            return NextResponse.json({ error: 'Vendor not found' }, { status: 404 });
        }

        const updated = await prisma.vendor.update({
            where: { id: vendorId },
            data: {
                ...parsed.data,
                updatedById: parseInt(session.user.id),
            },
        });

        return NextResponse.json({ success: true, vendor: updated });
    } catch (error: unknown) {
        if (error instanceof BodyTooLargeError) {
            return NextResponse.json({ error: error.message }, { status: 413 });
        }
        if (error instanceof BodyParseError) {
            return NextResponse.json({ error: error.message }, { status: 400 });
        }
        console.error('Vendor update failed:', error);
        return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
    }
}

export async function DELETE(_req: NextRequest, { params }: { params: Promise<{ id: string }> }) {
    const session = await getServerSession(authOptions);
    if (!session?.user?.id) {
        return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
    }
    const role = (session.user as { role?: string }).role;
    if (!role || !ROLES_WRITE.includes(role)) {
        return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
    }

    const { id } = await params;
    const vendorId = parseInt(id, 10);
    if (!Number.isFinite(vendorId) || vendorId <= 0) {
        return NextResponse.json({ error: 'Invalid vendor id' }, { status: 400 });
    }

    const existing = await prisma.vendor.findFirst({ where: { id: vendorId, deletedAt: null }, select: { id: true } });
    if (!existing) {
        return NextResponse.json({ error: 'Vendor not found' }, { status: 404 });
    }

    // Soft-delete the vendor and unlink its monitors so the FK doesn't dangle.
    await prisma.$transaction([
        prisma.monitor.updateMany({ where: { vendorId }, data: { vendorId: null } }),
        prisma.vendor.update({
            where: { id: vendorId },
            data: { deletedAt: new Date(), deletedById: parseInt(session.user.id) },
        }),
    ]);

    return NextResponse.json({ success: true });
}
