import { NextResponse } from 'next/server';

import { withAuth, withPermission } from '@/lib/api/helpers';
import { createAuditLog } from '@/lib/audit';
import { errorResponse, NotFoundError } from '@/lib/errors';
import { registryFor } from '@/lib/settings/registry';
import { getSetting } from '@/lib/settings/resolver';

/**
 * POST /api/v1/admin/settings/:key/reveal
 *
 * Returns the decrypted cleartext for an encrypted / sensitive setting.
 * Used by the eye-toggle on encrypted fields in the registry-driven admin
 * form so the operator can verify what they saved earlier.
 *
 * Gated on `admin.manage_settings` (the same permission required to write
 * the value - so this never widens an existing trust boundary). Every
 * reveal is audit-logged with the request id so a super-admin can trace
 * who looked at what and when.
 *
 * Refuses to reveal values resolved from `env` or `default` - those would
 * leak server-process secrets via the API.
 */
export const POST = withAuth(
  withPermission('admin', 'manage_settings', async (_req, ctx, params) => {
    try {
      const key = params.key!;
      const entry = registryFor(key);
      if (!entry) throw new NotFoundError(`Unknown setting: ${key}`);
      if (!entry.encrypted && !entry.sensitive) {
        // Non-sensitive values are already returned in the resolved-list
        // endpoint, so a dedicated reveal isn't needed (and could be
        // misused to bypass observability).
        return NextResponse.json({ data: { revealed: false, value: null } }, { status: 200 });
      }

      // Resolve through the standard chain so the user sees exactly what
      // the runtime would. The resolver decrypts on the way out.
      const value = await getSetting<string>(key, ctx.portId);

      void createAuditLog({
        userId: ctx.userId,
        portId: ctx.portId,
        action: 'view',
        entityType: 'setting',
        entityId: key,
        metadata: { settingKey: key, op: 'reveal' },
        ipAddress: ctx.ipAddress,
        userAgent: ctx.userAgent,
      });

      return NextResponse.json({ data: { revealed: true, value: value ?? null } });
    } catch (error) {
      return errorResponse(error);
    }
  }),
);
