/**
 * Theme C (P1-4) — maintenance-window CRUD.
 *
 * GET    /api/maintenance-windows                  list active+future
 * GET    /api/maintenance-windows?monitorId=N      filter
 * POST   /api/maintenance-windows                  create
 * DELETE /api/maintenance-windows?id=N             soft-delete
 *
 * Scope: ADMIN + EDITOR may write; everyone may read.
 */
import { NextResponse } from 'next/server';
import { getServerSession } from 'next-auth/next';
import { authOptions } from '@/lib/auth';
import { prisma } from '@/lib/prisma';
import { invalidateMaintenanceWindowsCache } from '@/lib/services/maintenance-window';
import {
    parseJsonBounded,
    BodyTooLargeError,
    BodyParseError,
} from '@/lib/api-helpers/parse-json';

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

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

    const { searchParams } = new URL(req.url);
    const monitorIdParam = searchParams.get('monitorId');
    const monitorId = monitorIdParam ? parseInt(monitorIdParam, 10) : undefined;

    const windows = await prisma.maintenanceWindow.findMany({
        where: {
            deletedAt: null,
            // Show future + currently-active, plus all recurring.
            OR: [
                { endsAt: { gte: new Date() } },
                { recurrence: { not: null } },
            ],
            ...(monitorId !== undefined
                ? { OR: [{ monitorId: null }, { monitorId }] }
                : {}),
        },
        orderBy: { startsAt: 'asc' },
        include: {
            monitor: { select: { id: true, name: true } },
            createdBy: { select: { id: true, name: true, email: true } },
        },
    });

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

export async function POST(req: Request) {
    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 });
    }

    try {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const body = await parseJsonBounded<any>(req, { maxBytes: 64 * 1024 });
        const monitorId =
            typeof body.monitorId === 'number' ? body.monitorId : null;
        const startsAt = body.startsAt ? new Date(body.startsAt) : null;
        const endsAt = body.endsAt ? new Date(body.endsAt) : null;
        const reason = typeof body.reason === 'string' ? body.reason.trim() : '';
        const recurrence =
            typeof body.recurrence === 'string' && body.recurrence.trim()
                ? body.recurrence.trim().toUpperCase()
                : null;

        if (!startsAt || !endsAt || !Number.isFinite(startsAt.getTime()) || !Number.isFinite(endsAt.getTime())) {
            return NextResponse.json(
                { error: 'startsAt and endsAt are required ISO timestamps' },
                { status: 400 }
            );
        }
        if (endsAt.getTime() <= startsAt.getTime()) {
            return NextResponse.json(
                { error: 'endsAt must be after startsAt' },
                { status: 400 }
            );
        }
        if (!reason) {
            return NextResponse.json({ error: 'reason is required' }, { status: 400 });
        }
        if (recurrence && !/^([A-Z]{3})(,[A-Z]{3})*$/.test(recurrence)) {
            return NextResponse.json(
                { error: 'recurrence must be comma-separated day tokens (e.g. "MON,WED,FRI")' },
                { status: 400 }
            );
        }

        const created = await prisma.maintenanceWindow.create({
            data: {
                monitorId,
                startsAt,
                endsAt,
                reason,
                recurrence,
                createdById: parseInt(session.user.id),
            },
        });

        // AUDIT-2 #16.13: drop the worker's cached window set so the
        // engine picks this new window up on the next check instead
        // of waiting for the 10s TTL to expire.
        invalidateMaintenanceWindowsCache();

        return NextResponse.json({ success: true, window: created }, { status: 201 });
    } 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('Maintenance window create failed:', error);
        return NextResponse.json({ error: 'Internal Server Error' }, { status: 500 });
    }
}

export async function DELETE(req: Request) {
    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 { searchParams } = new URL(req.url);
    const id = parseInt(searchParams.get('id') || '0', 10);
    if (!Number.isFinite(id) || id <= 0) {
        return NextResponse.json({ error: 'id required' }, { status: 400 });
    }

    await prisma.maintenanceWindow.update({
        where: { id },
        data: {
            deletedAt: new Date(),
            deletedById: parseInt(session.user.id),
        },
    });

    invalidateMaintenanceWindowsCache();

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