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

import { requireSuperAdmin, withAuth, withPermission } from '@/lib/api/helpers';
import { parseBody } from '@/lib/api/route-helpers';
import { errorResponse, ValidationError } from '@/lib/errors';
import { getPublicOcrConfig, saveOcrConfig, OCR_MODELS } from '@/lib/services/ocr-config.service';

const saveSchema = z.object({
  /** When 'global', requires super_admin and stores at port_id=null. */
  scope: z.enum(['port', 'global']),
  provider: z.enum(['openai', 'claude']),
  model: z.string().min(1),
  apiKey: z.string().optional(),
  clearApiKey: z.boolean().optional(),
  useGlobal: z.boolean().optional(),
  aiEnabled: z.boolean().optional(),
  manualEntry: z.boolean().optional(),
});

// Only role tiers that hold `admin.manage_settings` (director / super_admin)
// may read or write the OCR config: the apiKey is stored encrypted but is
// passed straight into the receipt-scan handler, so a swapped key would
// exfiltrate every subsequent receipt image to whatever endpoint that key
// authenticates with.
export const GET = withAuth(
  withPermission('admin', 'manage_settings', async (req, ctx) => {
    try {
      const url = new URL(req.url);
      const scope = url.searchParams.get('scope') ?? 'port';
      if (scope === 'global') {
        requireSuperAdmin(ctx, 'admin.ocr-settings.read.global');
      }
      const config = await getPublicOcrConfig(scope === 'global' ? null : ctx.portId);
      return NextResponse.json({ data: config, models: OCR_MODELS });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);

export const PUT = withAuth(
  withPermission('admin', 'manage_settings', async (req, ctx) => {
    try {
      const body = await parseBody(req, saveSchema);
      if (body.scope === 'global') {
        requireSuperAdmin(ctx, 'admin.ocr-settings.write.global');
      }
      const validModels = OCR_MODELS[body.provider];
      if (!validModels.includes(body.model)) {
        throw new ValidationError(`Invalid model for provider ${body.provider}`);
      }
      await saveOcrConfig(
        body.scope === 'global' ? null : ctx.portId,
        {
          provider: body.provider,
          model: body.model,
          apiKey: body.apiKey,
          clearApiKey: body.clearApiKey,
          useGlobal: body.useGlobal,
          aiEnabled: body.aiEnabled,
          manualEntry: body.manualEntry,
        },
        ctx.userId,
      );
      return new NextResponse(null, { status: 204 });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);
