/**
 * Reserved Slots API — Generate and list reserved registration slots.
 *
 * POST — Generate reserved slots for a company + month
 * GET  — List reserved slots (with claimed/unclaimed status)
 */

import { NextRequest, NextResponse } from "next/server";
import type { Prisma } from "@prisma/client";
import { prisma } from "@/core/storage/prisma";
import { getAuthSession } from "@/core/auth";
import {
  generateReservedSlots,
  countReservedSlots,
} from "@/modules/registratura/services/reserved-slots-service";
import { logAuditEvent } from "@/modules/registratura/services/audit-service";
import type { RegistryEntry } from "@/modules/registratura/types";
import type { CompanyId } from "@/core/auth/types";

const NAMESPACE = "registratura";
const STORAGE_PREFIX = "entry:";

// ── Auth (same as main route) ──

interface Actor {
  id: string;
  name: string;
}

async function authenticateRequest(req: NextRequest): Promise<Actor | null> {
  const session = await getAuthSession();
  if (session?.user) {
    const u = session.user as { id?: string; name?: string | null; email?: string | null };
    return {
      id: u.id ?? u.email ?? "unknown",
      name: u.name ?? u.email ?? "unknown",
    };
  }

  const apiKey = process.env.REGISTRY_API_KEY;
  if (apiKey) {
    const auth = req.headers.get("authorization");
    if (auth === `Bearer ${apiKey}`) {
      return { id: "api-key", name: "ERP Integration" };
    }
  }

  return null;
}

// ── Helpers ──

async function loadAllEntries(): Promise<RegistryEntry[]> {
  const rows = await prisma.keyValueStore.findMany({
    where: { namespace: NAMESPACE },
    select: { key: true, value: true },
  });
  const entries: RegistryEntry[] = [];
  for (const row of rows) {
    if (row.key.startsWith(STORAGE_PREFIX) && row.value) {
      entries.push(row.value as unknown as RegistryEntry);
    }
  }
  return entries;
}

// ── POST — Generate reserved slots ──

export async function POST(req: NextRequest) {
  const actor = await authenticateRequest(req);
  if (!actor) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  try {
    const body = await req.json();
    const { company, year, month } = body as {
      company: CompanyId;
      year: number;
      month: number; // 0-indexed
    };

    if (!company || year == null || month == null) {
      return NextResponse.json(
        { error: "Missing required fields: company, year, month" },
        { status: 400 },
      );
    }

    if (month < 0 || month > 11) {
      return NextResponse.json(
        { error: "Month must be 0-11 (0-indexed)" },
        { status: 400 },
      );
    }

    // Check if slots already exist for this company+month
    const allEntries = await loadAllEntries();
    const existing = countReservedSlots(allEntries, company, year, month);
    if (existing >= 2) {
      return NextResponse.json(
        { error: "Reserved slots already exist for this month", existingCount: existing },
        { status: 409 },
      );
    }

    // Generate slots
    const slots = await generateReservedSlots(
      company,
      year,
      month,
      actor.id,
      actor.name,
    );

    // Save to KeyValueStore
    for (const slot of slots) {
      await prisma.keyValueStore.upsert({
        where: {
          namespace_key: {
            namespace: NAMESPACE,
            key: `${STORAGE_PREFIX}${slot.id}`,
          },
        },
        update: { value: slot as unknown as Prisma.InputJsonValue },
        create: {
          namespace: NAMESPACE,
          key: `${STORAGE_PREFIX}${slot.id}`,
          value: slot as unknown as Prisma.InputJsonValue,
        },
      });

      await logAuditEvent({
        entryId: slot.id,
        entryNumber: slot.number,
        action: "reserved_created",
        actor: actor.id,
        actorName: actor.name,
        company,
        detail: { date: slot.date, month, year },
      });
    }

    return NextResponse.json({ success: true, slots }, { status: 201 });
  } catch (err) {
    const message = err instanceof Error ? err.message : "Internal error";
    return NextResponse.json({ error: message }, { status: 500 });
  }
}

// ── GET — List reserved slots ──

export async function GET(req: NextRequest) {
  const actor = await authenticateRequest(req);
  if (!actor) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const url = new URL(req.url);
  const company = url.searchParams.get("company");
  const year = url.searchParams.get("year");
  const month = url.searchParams.get("month");

  const allEntries = await loadAllEntries();
  let reserved = allEntries.filter((e) => e.isReserved === true);

  if (company) reserved = reserved.filter((e) => e.company === company);
  if (year) {
    const yr = parseInt(year, 10);
    reserved = reserved.filter((e) => new Date(e.date).getFullYear() === yr);
  }
  if (month) {
    const m = parseInt(month, 10);
    reserved = reserved.filter((e) => new Date(e.date).getMonth() === m);
  }

  reserved.sort((a, b) => a.date.localeCompare(b.date));

  return NextResponse.json({ success: true, slots: reserved, total: reserved.length });
}
