import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
import { NextResponse } from "next/server";

import { serializeGrade } from "@/features/grades/lib/serialize-grade";
import { gradeInputSchema, type GradeInput } from "@/features/grades/schemas/grade.schema";
import { createAuditTrailSafe } from "@/lib/audit-trail";
import { requireApiAccess } from "@/lib/authorization";
import { resolveMasterCode } from "@/lib/master-code";
import { prisma } from "@/lib/prisma";

function getGradePrefix(isMangkok: boolean) {
  return isMangkok ? "MGK" : "GRD";
}

function hasOverlap(items: GradeInput["buy_price_standards"]) {
  const normalized = items.map((item) => ({
    start: new Date(item.start_date).getTime(),
    end: item.end_date ? new Date(item.end_date).getTime() : Number.POSITIVE_INFINITY
  }));

  for (let i = 0; i < normalized.length; i += 1) {
    for (let j = i + 1; j < normalized.length; j += 1) {
      const a = normalized[i];
      const b = normalized[j];
      if (a.start <= b.end && b.start <= a.end) {
        return true;
      }
    }
  }

  return false;
}

function validatePriceStandards(parsed: GradeInput) {
  if (hasOverlap(parsed.buy_price_standards)) {
    return { buy_price_standards: ["Periode standar harga beli tidak boleh overlap"] };
  }

  if (hasOverlap(parsed.sell_price_standards)) {
    return { sell_price_standards: ["Periode standar harga jual tidak boleh overlap"] };
  }

  return null;
}

export async function GET(request: Request) {
  const auth = requireApiAccess(request);
  if (!auth.ok) return auth.response;

  const data = await prisma.grade.findMany({
    include: {
      buyPriceStandards: { orderBy: [{ startDate: "asc" }, { id: "asc" }] },
      sellPriceStandards: { orderBy: [{ startDate: "asc" }, { id: "asc" }] }
    },
    orderBy: [{ isMangkok: "desc" }, { createdAt: "desc" }]
  });

  return NextResponse.json({ data: data.map(serializeGrade) });
}

export async function POST(request: Request) {
  const auth = requireApiAccess(request);
  if (!auth.ok) return auth.response;

  const parsed = gradeInputSchema.safeParse(await request.json());
  if (!parsed.success) {
    return NextResponse.json(
      { message: "Validasi gagal", errors: parsed.error.flatten().fieldErrors },
      { status: 400 }
    );
  }

  const priceValidationError = validatePriceStandards(parsed.data);
  if (priceValidationError) {
    return NextResponse.json({ message: "Validasi gagal", errors: priceValidationError }, { status: 400 });
  }

  try {
    const prefix = getGradePrefix(parsed.data.is_mangkok);
    const resolvedCode = await resolveMasterCode({
      role: auth.user.role,
      prefix,
      requestedCode: parsed.data.code,
      countExisting: () => prisma.grade.count({ where: { code: { startsWith: prefix } } }),
      exists: async (code) => (await prisma.grade.count({ where: { code } })) > 0
    });

    if (!resolvedCode.ok) {
      return NextResponse.json(
        { message: "Validasi gagal", errors: { code: [resolvedCode.message] } },
        { status: 400 }
      );
    }

    const item = await prisma.grade.create({
      data: {
        code: resolvedCode.code,
        isMangkok: parsed.data.is_mangkok,
        name: parsed.data.name,
        description: parsed.data.description || null,
        status: parsed.data.status,
        buyPriceStandards: {
          create: parsed.data.buy_price_standards.map((standard) => ({
            startDate: new Date(standard.start_date),
            endDate: standard.end_date ? new Date(standard.end_date) : null,
            minPrice: standard.min_price,
            maxPrice: standard.max_price,
            notes: standard.notes || null
          }))
        },
        sellPriceStandards: {
          create: parsed.data.sell_price_standards.map((standard) => ({
            startDate: new Date(standard.start_date),
            endDate: standard.end_date ? new Date(standard.end_date) : null,
            minPrice: standard.min_price,
            maxPrice: standard.max_price,
            notes: standard.notes || null
          }))
        }
      },
      include: {
        buyPriceStandards: { orderBy: [{ startDate: "asc" }, { id: "asc" }] },
        sellPriceStandards: { orderBy: [{ startDate: "asc" }, { id: "asc" }] }
      }
    });

    await createAuditTrailSafe({
      userId: auth.user.id,
      action: "GRADE_CREATED",
      entityType: "GRADE",
      entityId: item.id,
      method: request.method,
      pathname: new URL(request.url).pathname,
      statusCode: 201,
      summary: `Grade ${item.code} dibuat`
    });

    return NextResponse.json({ data: serializeGrade(item) }, { status: 201 });
  } catch (error) {
    if (error instanceof PrismaClientKnownRequestError && error.code === "P2002") {
      return NextResponse.json(
        { message: "Validasi gagal", errors: { code: ["Kode grade sudah dipakai"] } },
        { status: 409 }
      );
    }
    throw error;
  }
}

