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 { sql } from "kysely";
import { Attachment, AttachmentPartition } from "../../data/entities.js";
import { buildAttachmentImageUrl, slugifyAttachmentFileName } from "../../lib/imageUrls.js";
import { readAttachmentMetadata } from "../../lib/metadata.js";
import { applyAssignmentEnrichments, resolveAssignmentEnrichments } from "../../lib/assignmentDetails.js";
import { buildIlikeTerm } from "@open-mercato/shared/lib/db/buildIlikeTerm";
import { ensureDefaultPartitions } from "../../lib/partitions.js";
import {
  attachmentsTag,
  attachmentListQuerySchema as openApiListQuerySchema,
  attachmentListResponseSchema,
  attachmentErrorSchema
} from "../openapi.js";
const listQuerySchema = z.object({
  page: z.coerce.number().min(1).default(1),
  pageSize: z.coerce.number().min(1).max(100).default(25),
  search: z.string().optional(),
  partition: z.string().optional(),
  tags: z.string().optional(),
  sortField: z.enum(["fileName", "fileSize", "createdAt"]).optional(),
  sortDir: z.enum(["asc", "desc"]).optional()
});
const metadata = {
  GET: { requireAuth: true, requireFeatures: ["attachments.view"] }
};
function buildTagFilter(raw) {
  if (!raw) return [];
  return raw.split(",").map((tag) => tag.trim()).filter((tag) => tag.length > 0);
}
function formatDateValue(value) {
  const toDate = () => {
    if (value instanceof Date) return value;
    if (typeof value === "string") {
      const parsed = new Date(value);
      if (!Number.isNaN(parsed.getTime())) return parsed;
    }
    const fallback = new Date(value);
    if (!Number.isNaN(fallback.getTime())) return fallback;
    return /* @__PURE__ */ new Date();
  };
  return toDate().toISOString();
}
async function GET(req) {
  const auth = await getAuthFromRequest(req);
  if (!auth || !auth.tenantId || !auth.orgId && !auth.isSuperAdmin) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }
  const url = new URL(req.url);
  const parsed = listQuerySchema.safeParse(Object.fromEntries(url.searchParams.entries()));
  if (!parsed.success) {
    return NextResponse.json({ error: "Invalid query" }, { status: 400 });
  }
  const { page, pageSize, search, partition, tags, sortField, sortDir } = parsed.data;
  const tagList = buildTagFilter(tags);
  const offset = (page - 1) * pageSize;
  const { resolve } = await createRequestContainer();
  const em = resolve("em");
  await ensureDefaultPartitions(em);
  let queryEngine = null;
  try {
    queryEngine = resolve("queryEngine");
  } catch {
    queryEngine = null;
  }
  const qb = em.createQueryBuilder(Attachment, "a");
  const baseFilter = { tenantId: auth.tenantId };
  if (auth.orgId) {
    baseFilter.organizationId = auth.orgId;
  }
  qb.where(baseFilter);
  if (search && search.trim().length > 0) {
    qb.andWhere({ fileName: { $ilike: buildIlikeTerm(search.trim()) } });
  }
  if (partition && partition.trim().length > 0) {
    qb.andWhere({ partitionCode: partition.trim() });
  }
  if (tagList.length > 0) {
    qb.andWhere(`coalesce(a.storage_metadata->'tags', '[]'::jsonb) @> ?::jsonb`, [JSON.stringify(tagList)]);
  }
  const countQb = qb.clone();
  const orderMap = {
    fileName: "a.file_name",
    fileSize: "a.file_size",
    createdAt: "a.created_at"
  };
  const orderColumn = orderMap[sortField ?? "createdAt"] ?? "a.created_at";
  qb.orderBy({ [orderColumn]: sortDir === "asc" ? "asc" : "desc" });
  qb.limit(pageSize).offset(offset);
  const partitionsPromise = em.find(
    AttachmentPartition,
    {},
    { orderBy: { title: "asc" }, fields: ["code", "title", "description"] }
  );
  const [records, total, partitions] = await Promise.all([qb.getResultList(), countQb.getCount("a.id", true), partitionsPromise]);
  const partitionTitleByCode = partitions.reduce((acc, entry) => {
    if (entry.code) acc[entry.code] = entry.title ?? entry.code;
    return acc;
  }, {});
  const items = records.map((record) => {
    const metadata2 = readAttachmentMetadata(record.storageMetadata);
    const fileName = record.fileName || "";
    const isImage = typeof record.mimeType === "string" && record.mimeType.toLowerCase().startsWith("image/");
    const thumbnailUrl = isImage ? buildAttachmentImageUrl(record.id, {
      width: 200,
      height: 200,
      slug: slugifyAttachmentFileName(fileName)
    }) : void 0;
    return {
      id: record.id,
      fileName,
      fileSize: record.fileSize,
      mimeType: record.mimeType,
      partitionCode: record.partitionCode,
      partitionTitle: partitionTitleByCode[record.partitionCode] ?? null,
      url: record.url,
      createdAt: formatDateValue(record.createdAt),
      tags: metadata2.tags ?? [],
      assignments: metadata2.assignments ?? [],
      thumbnailUrl,
      content: record.content && record.content.trim() ? record.content : null
    };
  });
  const allAssignments = items.flatMap((item) => item.assignments ?? []);
  const enrichments = await resolveAssignmentEnrichments(allAssignments, {
    queryEngine,
    tenantId: auth.tenantId,
    organizationId: auth.orgId
  });
  const enrichedItems = enrichments.size ? items.map((item) => ({
    ...item,
    assignments: applyAssignmentEnrichments(item.assignments ?? [], enrichments)
  })) : items;
  const totalPages = Math.max(1, Math.ceil(Number(total) / pageSize));
  const db = em.getKysely();
  let tagQuery = db.selectFrom("attachments").select(sql`distinct jsonb_array_elements_text(coalesce(storage_metadata->'tags', '[]'::jsonb))`.as("tag")).where("tenant_id", "=", auth.tenantId);
  if (auth.orgId) {
    tagQuery = tagQuery.where("organization_id", "=", auth.orgId);
  }
  const tagRows = await tagQuery.orderBy("tag", "asc").execute();
  const availableTags = tagRows.map((row) => typeof row.tag === "string" ? row.tag.trim() : "").filter((tag) => tag.length > 0);
  return NextResponse.json({
    items: enrichedItems,
    page,
    pageSize,
    total,
    totalPages,
    availableTags,
    partitions: partitions.map((entry) => ({
      code: entry.code,
      title: entry.title,
      description: entry.description ?? null,
      isPublic: entry.isPublic ?? false
    }))
  });
}
const openApi = {
  tag: attachmentsTag,
  summary: "Attachment library management",
  methods: {
    GET: {
      summary: "List attachments",
      description: "Returns paginated list of attachments with optional filtering by search term, partition, and tags. Includes available tags and partitions.",
      query: openApiListQuerySchema,
      responses: [
        { status: 200, description: "Attachments list with pagination and metadata", schema: attachmentListResponseSchema }
      ],
      errors: [
        { status: 400, description: "Invalid query parameters", schema: attachmentErrorSchema },
        { status: 401, description: "Unauthorized", schema: attachmentErrorSchema }
      ]
    }
  }
};
export {
  GET,
  metadata,
  openApi
};
//# sourceMappingURL=route.js.map
