import { NextResponse } from 'next/server';
import { z } from 'zod';

import { withAuth, withPermission } from '@/lib/api/helpers';
import { parseBody } from '@/lib/api/route-helpers';
import { errorResponse, ValidationError } from '@/lib/errors';
import { createReportTemplate, listReportTemplates } from '@/lib/services/report-templates.service';

const createBodySchema = z.object({
  // 'sales' + 'operational' don't go through /api/v1/reports/generate;
  // they're standalone report pages with their own routes. The config
  // for these kinds is a thin view-state snapshot (date range +
  // filters) that the report client applies on load. 'custom' is the
  // ad-hoc composer's saved config — entity + columns + filter.
  kind: z.enum([
    'dashboard',
    'clients',
    'berths',
    'interests',
    'sales',
    'operational',
    'financial',
    'marketing',
    'custom',
  ]),
  name: z.string().min(1).max(120),
  description: z.string().max(400).nullable().optional(),
  // Config is the raw discriminated-union payload; the
  // /api/v1/reports/generate route re-validates at use time, so we
  // accept it as `record` here without imposing the full union shape.
  config: z.record(z.string(), z.unknown()),
});

/**
 * GET  /api/v1/reports/templates?kind=clients
 *   List saved templates for the active port, optionally filtered to
 *   one kind. Used by the Export dialog's saved-templates dropdown.
 *
 * POST /api/v1/reports/templates
 *   Persist a template. The dialog calls this when the rep ticks
 *   "Save as template" while configuring an export.
 *
 * Both gated on `reports.export` - the same permission that lets
 * the rep generate reports also lets them save templates.
 */
export const GET = withAuth(
  withPermission('reports', 'export', async (req, ctx) => {
    try {
      const url = new URL(req.url);
      const kind = url.searchParams.get('kind') ?? undefined;
      const rows = await listReportTemplates(ctx.portId, kind ?? undefined);
      return NextResponse.json({ data: rows });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);

export const POST = withAuth(
  withPermission('reports', 'export', async (req, ctx) => {
    try {
      const body = await parseBody(req, createBodySchema);
      // Cross-validate that the config's discriminator matches the
      // outer `kind`. Without this, a rep could save a clients-kind
      // template with a dashboard config and confuse the rendering
      // path at use time.
      const configKind = (body.config as { kind?: unknown }).kind;
      if (configKind !== body.kind) {
        throw new ValidationError(`config.kind must equal "${body.kind}"`);
      }
      const row = await createReportTemplate({
        portId: ctx.portId,
        kind: body.kind,
        name: body.name,
        description: body.description ?? null,
        config: body.config,
        meta: {
          userId: ctx.userId,
          portId: ctx.portId,
          ipAddress: ctx.ipAddress,
          userAgent: ctx.userAgent,
        },
      });
      return NextResponse.json({ data: row });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);
