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 { escapeLikePattern } from "@open-mercato/shared/lib/db/escapeLikePattern";
import { ProgressJob } from "../../data/entities.js";
import { createProgressJobSchema, listProgressJobsSchema } from "../../data/validators.js";
import {
  createProgressCrudOpenApi,
  createPagedListResponseSchema
} from "../openapi.js";
import { createLogger } from "@open-mercato/shared/lib/logger";
const logger = createLogger("progress").child({ component: "jobs" });
const routeMetadata = {
  GET: { requireAuth: true, requireFeatures: ["progress.view"] },
  POST: { requireAuth: true, requireFeatures: ["progress.create"] }
};
const metadata = routeMetadata;
const listQuerySchema = listProgressJobsSchema;
const toRow = (job) => ({
  id: String(job.id),
  jobType: String(job.jobType),
  name: String(job.name),
  description: job.description ?? null,
  status: job.status,
  progressPercent: job.progressPercent,
  processedCount: job.processedCount,
  totalCount: job.totalCount ?? null,
  etaSeconds: job.etaSeconds ?? null,
  cancellable: !!job.cancellable,
  startedAt: job.startedAt ? job.startedAt.toISOString() : null,
  finishedAt: job.finishedAt ? job.finishedAt.toISOString() : null,
  errorMessage: job.errorMessage ?? null,
  createdAt: job.createdAt ? job.createdAt.toISOString() : null,
  tenantId: String(job.tenantId),
  organizationId: job.organizationId ? String(job.organizationId) : null
});
async function GET(req) {
  const auth = await getAuthFromRequest(req);
  if (!auth || !auth.tenantId) {
    return NextResponse.json({ items: [], total: 0, page: 1, pageSize: 20, totalPages: 1 }, { status: 401 });
  }
  const url = new URL(req.url);
  const parsed = listQuerySchema.safeParse({
    status: url.searchParams.get("status") ?? void 0,
    jobType: url.searchParams.get("jobType") ?? void 0,
    parentJobId: url.searchParams.get("parentJobId") ?? void 0,
    includeCompleted: url.searchParams.get("includeCompleted") ?? void 0,
    completedSince: url.searchParams.get("completedSince") ?? void 0,
    page: url.searchParams.get("page") ?? void 0,
    pageSize: url.searchParams.get("pageSize") ?? void 0,
    search: url.searchParams.get("search") ?? void 0,
    sortField: url.searchParams.get("sortField") ?? void 0,
    sortDir: url.searchParams.get("sortDir") ?? void 0
  });
  if (!parsed.success) {
    return NextResponse.json({ items: [], total: 0, page: 1, pageSize: 20, totalPages: 1 }, { status: 400 });
  }
  const container = await createRequestContainer();
  const em = container.resolve("em");
  const { status, jobType, parentJobId, includeCompleted, completedSince, page, pageSize, search, sortField, sortDir } = parsed.data;
  const filter = {
    tenantId: auth.tenantId
  };
  if (auth.orgId) {
    filter.organizationId = auth.orgId;
  }
  if (status) {
    const statusValues = status.split(",");
    filter.status = statusValues.length > 1 ? { $in: statusValues } : status;
  } else if (includeCompleted !== "true") {
    filter.status = { $in: ["pending", "running"] };
  }
  if (jobType) filter.jobType = jobType;
  if (parentJobId) filter.parentJobId = parentJobId;
  if (completedSince) filter.finishedAt = { $gte: new Date(completedSince) };
  if (search) {
    const escaped = escapeLikePattern(search);
    filter.$or = [
      { name: { $ilike: `%${escaped}%` } },
      { jobType: { $ilike: `%${escaped}%` } }
    ];
  }
  const fieldMap = {
    createdAt: "createdAt",
    startedAt: "startedAt",
    finishedAt: "finishedAt"
  };
  const orderBy = {};
  if (sortField) {
    const mapped = fieldMap[sortField] || "createdAt";
    orderBy[mapped] = sortDir === "asc" ? "ASC" : "DESC";
  } else {
    orderBy.createdAt = "DESC";
  }
  const [rows, total] = await em.findAndCount(ProgressJob, filter, {
    orderBy,
    limit: pageSize,
    offset: (page - 1) * pageSize
  });
  const items = rows.map(toRow);
  const totalPages = Math.max(1, Math.ceil(total / pageSize));
  return NextResponse.json({ items, total, page, pageSize, totalPages });
}
async function POST(req) {
  try {
    const auth = await getAuthFromRequest(req);
    if (!auth || !auth.tenantId) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }
    const body = await req.json();
    const parsed = createProgressJobSchema.safeParse(body);
    if (!parsed.success) {
      return NextResponse.json({ error: "Invalid input", details: parsed.error.flatten() }, { status: 400 });
    }
    const container = await createRequestContainer();
    const progressService = container.resolve("progressService");
    const job = await progressService.createJob(parsed.data, {
      tenantId: auth.tenantId,
      organizationId: auth.orgId,
      userId: auth.sub
    });
    return NextResponse.json({ id: job.id }, { status: 201 });
  } catch (error) {
    const message = error instanceof Error ? error.message : String(error);
    const stack = error instanceof Error ? error.stack : void 0;
    logger.error("Unhandled error creating progress job", { message, stack });
    return NextResponse.json(
      { error: "Failed to create progress job." },
      { status: 500 }
    );
  }
}
const jobListItemSchema = z.object({
  id: z.string().uuid(),
  jobType: z.string(),
  name: z.string(),
  description: z.string().nullable(),
  status: z.string(),
  progressPercent: z.number(),
  processedCount: z.number(),
  totalCount: z.number().nullable(),
  etaSeconds: z.number().nullable(),
  cancellable: z.boolean(),
  startedAt: z.string().nullable(),
  finishedAt: z.string().nullable(),
  errorMessage: z.string().nullable(),
  createdAt: z.string().nullable(),
  tenantId: z.string().uuid(),
  organizationId: z.string().uuid().nullable()
});
const openApi = createProgressCrudOpenApi({
  resourceName: "ProgressJob",
  pluralName: "ProgressJobs",
  querySchema: listQuerySchema,
  listResponseSchema: createPagedListResponseSchema(jobListItemSchema),
  create: {
    schema: createProgressJobSchema,
    description: "Creates a new progress job for tracking a long-running operation."
  }
});
export {
  GET,
  POST,
  metadata,
  openApi
};
//# sourceMappingURL=route.js.map
