import { NextRequest, NextResponse } from 'next/server';
import { z } from 'zod';
import { getAllSettings, updateSettings } from '@/lib/db/repositories';
import { withAuth } from '@/core/auth';
import { listCatalogueKeys, setSecret, setPlain } from '@/core/settings/repo';
import { isSecretKey, SETTINGS_CATALOGUE } from '@/core/settings/keys';

export const runtime = 'nodejs';
export const dynamic = 'force-dynamic';

const PromptPatchSchema = z.object({
  systemPromptGenerate: z.string().min(50).optional(),
  systemPromptSuggest: z.string().min(50).optional(),
  systemPromptImage: z.string().min(20).optional(),
});

const CataloguePatchSchema = z.object({
  /** Map of catalogue-key → new value. Secrets are encrypted; empty string clears. */
  values: z.record(z.string(), z.string()),
});

/**
 * GET /api/settings
 *  - default:           legacy shape `{ systemPromptGenerate, … }` for backwards-compat callers
 *  - ?view=catalogue    new shape `{ entries: [{ key, kind, hasValue, description }, …] }`
 *                       used by the Settings UI to render input fields without ever
 *                       exposing the stored secret values.
 */
export const GET = withAuth(async (req: NextRequest, _ctx) => {
  if (req.nextUrl.searchParams.get('view') === 'catalogue') {
    return NextResponse.json({ entries: listCatalogueKeys() });
  }
  return NextResponse.json(getAllSettings());
});

/**
 * PATCH /api/settings
 *  - body `{ systemPromptGenerate?, systemPromptSuggest?, systemPromptImage? }` → legacy prompt update
 *  - body `{ values: { [key]: stringValue } }` → catalogue update (handles secrets via encryption)
 */
export const PATCH = withAuth(async (req: NextRequest, _ctx) => {
  const body = await req.json();

  // Catalogue path: writes secrets via setSecret() (encrypts) and plain via setPlain().
  if ('values' in body) {
    const parsed = CataloguePatchSchema.safeParse(body);
    if (!parsed.success) {
      return NextResponse.json(
        {
          error: 'Invalid settings',
          issues: parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`),
        },
        { status: 400 },
      );
    }
    const knownKeys = Object.keys(SETTINGS_CATALOGUE);
    const unknown = Object.keys(parsed.data.values).filter((k) => !knownKeys.includes(k));
    if (unknown.length > 0) {
      return NextResponse.json(
        { error: `Unknown settings keys: ${unknown.join(', ')}` },
        { status: 400 },
      );
    }
    for (const [key, value] of Object.entries(parsed.data.values)) {
      if (isSecretKey(key)) setSecret(key, value);
      else setPlain(key, value);
    }
    return NextResponse.json({ ok: true, entries: listCatalogueKeys() });
  }

  // Legacy prompt path.
  const parsed = PromptPatchSchema.safeParse(body);
  if (!parsed.success) {
    return NextResponse.json(
      {
        error: 'Invalid settings',
        issues: parsed.error.issues.map((i) => `${i.path.join('.')}: ${i.message}`),
      },
      { status: 400 },
    );
  }
  return NextResponse.json(updateSettings(parsed.data));
});
