import { NextResponse } from "next/server";
import { z } from "zod";
import { CrudHttpError, isCrudHttpError } from "@open-mercato/shared/lib/crud/errors";
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
import { resolveOrganizationScopeForRequest } from "@open-mercato/core/modules/directory/utils/organizationScope";
import { resolveTranslations } from "@open-mercato/shared/lib/i18n/server";
import { findOneWithDecryption, findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
import { isOrganizationReadAccessAllowed } from "@open-mercato/core/modules/directory/utils/organizationScopeGuard";
import { CustomerDeal, CustomerDealPersonLink } from "../../../../data/entities.js";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("customers");
const paramsSchema = z.object({
  id: z.string().uuid()
});
const querySchema = z.object({
  page: z.coerce.number().min(1).default(1),
  pageSize: z.coerce.number().min(1).max(100).default(20),
  search: z.string().optional(),
  sort: z.enum(["label-asc", "label-desc", "name-asc", "name-desc", "recent"]).default("label-asc")
});
function normalizeSort(sort) {
  if (sort === "name-asc") return "label-asc";
  if (sort === "name-desc") return "label-desc";
  return sort;
}
function matchesSearch(item, query) {
  const normalized = query.trim().toLowerCase();
  if (!normalized.length) return true;
  return [item.label, item.subtitle].filter((value) => typeof value === "string" && value.length > 0).some((value) => value.toLowerCase().includes(normalized));
}
function sortItems(items, sort) {
  if (sort === "recent") {
    return [...items].sort((left, right) => {
      const compare = new Date(right.linkedAt).getTime() - new Date(left.linkedAt).getTime();
      if (compare !== 0) return compare;
      return left.label.localeCompare(right.label, void 0, { sensitivity: "base" });
    });
  }
  return [...items].sort((left, right) => {
    const compare = left.label.localeCompare(right.label, void 0, { sensitivity: "base" });
    return sort === "label-asc" ? compare : -compare;
  });
}
const metadata = {
  GET: { requireAuth: true, requireFeatures: ["customers.deals.view"] }
};
async function GET(req, ctx) {
  const { translate } = await resolveTranslations();
  try {
    const { id } = paramsSchema.parse({ id: ctx.params?.id });
    const auth = await getAuthFromRequest(req);
    if (!auth?.tenantId) throw new CrudHttpError(401, { error: "Unauthorized" });
    const url = new URL(req.url);
    const query = querySchema.parse({
      page: url.searchParams.get("page") ?? void 0,
      pageSize: url.searchParams.get("pageSize") ?? void 0,
      search: url.searchParams.get("search") ?? void 0,
      sort: url.searchParams.get("sort") ?? void 0
    });
    const container = await createRequestContainer();
    const scope = await resolveOrganizationScopeForRequest({ container, auth, request: req });
    const em = container.resolve("em").fork();
    const decryptionScope = {
      tenantId: auth.tenantId,
      organizationId: scope?.selectedId ?? auth.orgId ?? null
    };
    const deal = await findOneWithDecryption(
      em,
      CustomerDeal,
      { id, tenantId: auth.tenantId, deletedAt: null },
      {},
      decryptionScope
    );
    if (!deal) {
      throw new CrudHttpError(404, { error: translate("customers.errors.deal_not_found", "Deal not found") });
    }
    if (!isOrganizationReadAccessAllowed({ scope, auth, organizationId: deal.organizationId })) {
      throw new CrudHttpError(403, { error: translate("customers.errors.access_denied", "Access denied") });
    }
    const entityScope = { tenantId: deal.tenantId, organizationId: deal.organizationId };
    const links = await findWithDecryption(
      em,
      CustomerDealPersonLink,
      { deal: deal.id },
      { populate: ["person"] },
      entityScope
    );
    const items = links.map((link) => {
      const person = link.person;
      if (!person?.id) return null;
      return {
        id: person.id,
        label: person.displayName ?? person.primaryEmail ?? person.id,
        subtitle: person.primaryEmail ?? person.primaryPhone ?? null,
        kind: "person",
        linkedAt: link.createdAt.toISOString()
      };
    }).filter((item) => item !== null);
    const filtered = query.search?.trim().length ? items.filter((item) => matchesSearch(item, query.search ?? "")) : items;
    const sorted = sortItems(filtered, normalizeSort(query.sort));
    const total = sorted.length;
    const totalPages = Math.max(1, Math.ceil(total / query.pageSize));
    const page = Math.min(query.page, totalPages);
    const start = (page - 1) * query.pageSize;
    return NextResponse.json({
      items: sorted.slice(start, start + query.pageSize),
      total,
      page,
      pageSize: query.pageSize,
      totalPages
    });
  } catch (error) {
    if (isCrudHttpError(error)) {
      return NextResponse.json(error.body, { status: error.status });
    }
    logger.error("customers.deals.people.GET", { err: error });
    return NextResponse.json({ error: translate("customers.errors.deal_people_load_failed", "Failed to load linked people") }, { status: 500 });
  }
}
const openApi = {
  tag: "Customers",
  methods: {
    GET: {
      summary: "List linked people for a deal",
      query: querySchema,
      responses: [
        {
          status: 200,
          description: "Paginated linked people",
          schema: z.object({
            items: z.array(
              z.object({
                id: z.string().uuid(),
                label: z.string(),
                subtitle: z.string().nullable(),
                kind: z.literal("person"),
                linkedAt: z.string()
              })
            ),
            total: z.number().int().nonnegative(),
            page: z.number().int().min(1),
            pageSize: z.number().int().min(1),
            totalPages: z.number().int().min(1)
          })
        }
      ]
    }
  }
};
export {
  GET,
  metadata,
  openApi
};
//# sourceMappingURL=route.js.map
