import { NextResponse } from "next/server";
import { z } from "zod";
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
import { findOneWithDecryption, findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
import { Attachment, AttachmentPartition } from "../../data/entities.js";
import { ensureDefaultPartitions, DEFAULT_ATTACHMENT_PARTITIONS, sanitizePartitionCode, isPartitionSettingsLocked } from "../../lib/partitions.js";
import { resolvePartitionEnvKey } from "../../lib/partitionEnv.js";
import { resolveDefaultAttachmentOcrEnabled } from "../../lib/ocrConfig.js";
import {
  attachmentsTag,
  partitionCreateSchema,
  partitionUpdateSchema,
  partitionResponseSchema,
  partitionListResponseSchema,
  attachmentErrorSchema
} from "../openapi.js";
const deleteSchema = z.object({
  id: z.string().uuid()
});
const DEFAULT_CODES = new Set(DEFAULT_ATTACHMENT_PARTITIONS.map((entry) => entry.code));
function isSuperAdmin(auth) {
  return auth?.isSuperAdmin === true;
}
function canManagePartition(auth, entry) {
  if (!auth?.tenantId) return false;
  if (entry.tenantId && entry.tenantId === auth.tenantId) return true;
  if (entry.tenantId == null && isSuperAdmin(auth)) return true;
  return false;
}
function partitionVisibilityFilter(auth) {
  if (isSuperAdmin(auth)) return {};
  return { $or: [{ tenantId: null }, { tenantId: auth?.tenantId ?? null }] };
}
function serializePartition(entry) {
  return {
    id: entry.id,
    code: entry.code,
    title: entry.title,
    description: entry.description ?? null,
    isPublic: entry.isPublic ?? false,
    requiresOcr: entry.requiresOcr ?? resolveDefaultAttachmentOcrEnabled(),
    ocrModel: entry.ocrModel ?? null,
    storageDriver: entry.storageDriver ?? "local",
    configJson: entry.configJson ?? null,
    createdAt: entry.createdAt instanceof Date ? entry.createdAt.toISOString() : null,
    updatedAt: entry.updatedAt instanceof Date ? entry.updatedAt.toISOString() : null,
    envKey: resolvePartitionEnvKey(entry.code)
  };
}
const metadata = {
  GET: { requireAuth: true, requireFeatures: ["attachments.manage"] },
  POST: { requireAuth: true, requireFeatures: ["attachments.manage"] },
  PUT: { requireAuth: true, requireFeatures: ["attachments.manage"] },
  DELETE: { requireAuth: true, requireFeatures: ["attachments.manage"] }
};
async function resolveEm() {
  const { resolve } = await createRequestContainer();
  return resolve("em");
}
async function GET(req) {
  const auth = await getAuthFromRequest(req);
  if (!auth?.sub || !auth.tenantId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }
  const em = await resolveEm();
  await ensureDefaultPartitions(em);
  const rows = await findWithDecryption(
    em,
    AttachmentPartition,
    partitionVisibilityFilter(auth),
    { orderBy: { createdAt: "asc" } },
    { tenantId: auth.tenantId, organizationId: auth.orgId ?? null }
  );
  return NextResponse.json({ items: rows.map((entry) => serializePartition(entry)) });
}
async function POST(req) {
  if (isPartitionSettingsLocked()) {
    return NextResponse.json(
      { error: "Attachment partitions are managed by the environment in demo/onboarding mode." },
      { status: 403 }
    );
  }
  const auth = await getAuthFromRequest(req);
  if (!auth?.sub || !auth.tenantId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }
  let json = null;
  try {
    json = await req.json();
  } catch {
    json = null;
  }
  const parsed = partitionCreateSchema.safeParse(json);
  if (!parsed.success) {
    return NextResponse.json({ error: "Invalid payload" }, { status: 400 });
  }
  const code = sanitizePartitionCode(parsed.data.code);
  if (!code) {
    return NextResponse.json({ error: "Partition code is required." }, { status: 400 });
  }
  const em = await resolveEm();
  await ensureDefaultPartitions(em);
  const exists = await findOneWithDecryption(
    em,
    AttachmentPartition,
    { code },
    void 0,
    { tenantId: auth.tenantId, organizationId: auth.orgId ?? null }
  );
  if (exists) {
    return NextResponse.json({ error: "Partition code already exists." }, { status: 409 });
  }
  const entry = em.create(AttachmentPartition, {
    code,
    title: parsed.data.title.trim(),
    description: parsed.data.description?.trim() ?? null,
    storageDriver: parsed.data.storageDriver ?? "local",
    configJson: parsed.data.configJson ?? null,
    isPublic: parsed.data.isPublic ?? false,
    requiresOcr: typeof parsed.data.requiresOcr === "boolean" ? parsed.data.requiresOcr : resolveDefaultAttachmentOcrEnabled(),
    ocrModel: parsed.data.ocrModel?.trim() || null,
    tenantId: auth.tenantId,
    organizationId: auth.orgId ?? null
  });
  await em.persist(entry).flush();
  return NextResponse.json({ item: serializePartition(entry) }, { status: 201 });
}
async function PUT(req) {
  if (isPartitionSettingsLocked()) {
    return NextResponse.json(
      { error: "Attachment partitions are managed by the environment in demo/onboarding mode." },
      { status: 403 }
    );
  }
  const auth = await getAuthFromRequest(req);
  if (!auth?.sub || !auth.tenantId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }
  let json = null;
  try {
    json = await req.json();
  } catch {
    json = null;
  }
  const parsed = partitionUpdateSchema.safeParse(json);
  if (!parsed.success) {
    return NextResponse.json({ error: "Invalid payload" }, { status: 400 });
  }
  const em = await resolveEm();
  const entry = await findOneWithDecryption(
    em,
    AttachmentPartition,
    { id: parsed.data.id },
    void 0,
    { tenantId: auth.tenantId, organizationId: auth.orgId ?? null }
  );
  if (!entry || !canManagePartition(auth, entry)) {
    return NextResponse.json({ error: "Partition not found" }, { status: 404 });
  }
  if (sanitizePartitionCode(parsed.data.code) !== entry.code) {
    return NextResponse.json({ error: "Partition code cannot be changed." }, { status: 400 });
  }
  entry.title = parsed.data.title.trim();
  entry.description = parsed.data.description?.trim() ?? null;
  entry.isPublic = parsed.data.isPublic ?? false;
  if (typeof parsed.data.requiresOcr === "boolean") {
    entry.requiresOcr = parsed.data.requiresOcr;
  }
  if (parsed.data.ocrModel !== void 0) {
    entry.ocrModel = parsed.data.ocrModel?.trim() || null;
  }
  if (parsed.data.storageDriver !== void 0) {
    entry.storageDriver = parsed.data.storageDriver;
  }
  if (parsed.data.configJson !== void 0) {
    entry.configJson = parsed.data.configJson ?? null;
  }
  await em.persist(entry).flush();
  return NextResponse.json({ item: serializePartition(entry) });
}
async function DELETE(req) {
  if (isPartitionSettingsLocked()) {
    return NextResponse.json(
      { error: "Attachment partitions are managed by the environment in demo/onboarding mode." },
      { status: 403 }
    );
  }
  const auth = await getAuthFromRequest(req);
  if (!auth?.sub || !auth.tenantId) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }
  const url = new URL(req.url);
  const id = url.searchParams.get("id");
  const parsed = deleteSchema.safeParse({ id });
  if (!parsed.success) {
    return NextResponse.json({ error: "Partition id is required" }, { status: 400 });
  }
  const em = await resolveEm();
  const entry = await findOneWithDecryption(
    em,
    AttachmentPartition,
    { id: parsed.data.id },
    void 0,
    { tenantId: auth.tenantId, organizationId: auth.orgId ?? null }
  );
  if (!entry || !canManagePartition(auth, entry)) {
    return NextResponse.json({ error: "Partition not found" }, { status: 404 });
  }
  if (DEFAULT_CODES.has(entry.code)) {
    return NextResponse.json({ error: "Default partitions cannot be removed." }, { status: 400 });
  }
  const usageFilter = { partitionCode: entry.code };
  if (entry.tenantId) usageFilter.tenantId = entry.tenantId;
  const usage = await em.count(Attachment, usageFilter);
  if (usage > 0) {
    return NextResponse.json({ error: "Partition is in use and cannot be removed." }, { status: 409 });
  }
  await em.remove(entry).flush();
  return NextResponse.json({ ok: true });
}
const openApi = {
  tag: attachmentsTag,
  summary: "Attachment partition management",
  methods: {
    GET: {
      summary: "List all attachment partitions",
      description: "Returns all configured attachment partitions with storage settings, OCR configuration, and access control settings.",
      responses: [
        { status: 200, description: "List of partitions", schema: partitionListResponseSchema }
      ],
      errors: [
        { status: 401, description: "Unauthorized", schema: attachmentErrorSchema }
      ]
    },
    POST: {
      summary: "Create new partition",
      description: "Creates a new attachment partition with specified storage and OCR settings. Requires unique partition code.",
      requestBody: {
        contentType: "application/json",
        schema: partitionCreateSchema
      },
      responses: [
        { status: 201, description: "Partition created successfully", schema: partitionResponseSchema }
      ],
      errors: [
        { status: 400, description: "Invalid payload or partition code", schema: attachmentErrorSchema },
        { status: 401, description: "Unauthorized", schema: attachmentErrorSchema },
        { status: 403, description: "Partitions locked in demo mode", schema: attachmentErrorSchema },
        { status: 409, description: "Partition code already exists", schema: attachmentErrorSchema }
      ]
    },
    PUT: {
      summary: "Update partition",
      description: "Updates an existing partition. Partition code cannot be changed. Title, description, OCR settings, and access control can be modified.",
      requestBody: {
        contentType: "application/json",
        schema: partitionUpdateSchema
      },
      responses: [
        { status: 200, description: "Partition updated successfully", schema: partitionResponseSchema }
      ],
      errors: [
        { status: 400, description: "Invalid payload or code change attempt", schema: attachmentErrorSchema },
        { status: 401, description: "Unauthorized", schema: attachmentErrorSchema },
        { status: 403, description: "Partitions locked in demo mode", schema: attachmentErrorSchema },
        { status: 404, description: "Partition not found", schema: attachmentErrorSchema }
      ]
    },
    DELETE: {
      summary: "Delete partition",
      description: "Deletes a partition. Default partitions cannot be deleted. Partitions with existing attachments cannot be deleted.",
      responses: [
        { status: 200, description: "Partition deleted successfully", schema: z.object({ ok: z.literal(true) }) }
      ],
      errors: [
        { status: 400, description: "Invalid ID or default partition deletion attempt", schema: attachmentErrorSchema },
        { status: 401, description: "Unauthorized", schema: attachmentErrorSchema },
        { status: 403, description: "Partitions locked in demo mode", schema: attachmentErrorSchema },
        { status: 404, description: "Partition not found", schema: attachmentErrorSchema },
        { status: 409, description: "Partition in use", schema: attachmentErrorSchema }
      ]
    }
  }
};
export {
  DELETE,
  GET,
  POST,
  PUT,
  metadata,
  openApi
};
//# sourceMappingURL=route.js.map
