/**
 * Per-user settings for an installed connector.
 *
 * GET  → masked settings + schema + installed flag
 * POST → save settings (preserves stored secrets if client returns
 *        the bullet placeholder unchanged)
 *
 * Secrets (fields with type === 'secret') are encrypted at rest by
 * lib/connectors/registry.ts (AES-256-GCM via lib/crypto.ts) and
 * masked here so the plaintext never crosses the wire on GET.
 */

import { NextResponse } from 'next/server';
import {
  getConnector,
  getInstalledConnector,
  setConnectorConfig,
} from '@/lib/connectors/registry';
import type { ConnectorFieldSchema } from '@/lib/connectors/types';

function settingsSchemaFor(id: string): Record<string, ConnectorFieldSchema> {
  const def = getConnector(id);
  if (!def) return {};
  const merged: Record<string, ConnectorFieldSchema> = {};
  if (def.settings) Object.assign(merged, def.settings);
  // 1:N suites: union of each entry's settings
  for (const entry of def.connectors || []) {
    if (entry.settings) Object.assign(merged, entry.settings);
  }
  return merged;
}

function defaultsFor(id: string): Record<string, any> {
  const schema = settingsSchemaFor(id);
  const out: Record<string, any> = {};
  for (const [k, v] of Object.entries(schema)) {
    if (v.default !== undefined) out[k] = v.default;
  }
  return out;
}

const SECRET_MASK = '••••••••';

function isSecretField(schema: ConnectorFieldSchema | undefined): boolean {
  if (!schema) return false;
  return schema.type === 'secret' || (schema.type as string) === 'password';
}

function maskSecrets(settings: Record<string, any>, schema: Record<string, ConnectorFieldSchema>): Record<string, any> {
  const out: Record<string, any> = { ...settings };
  for (const [k, v] of Object.entries(schema)) {
    if (isSecretField(v) && typeof out[k] === 'string' && out[k]) {
      out[k] = SECRET_MASK;
    }
  }
  return out;
}

function restoreSecrets(
  incoming: Record<string, any>,
  existing: Record<string, any>,
  schema: Record<string, ConnectorFieldSchema>,
): Record<string, any> {
  const out: Record<string, any> = { ...incoming };
  for (const [k, v] of Object.entries(schema)) {
    if (isSecretField(v) && out[k] === SECRET_MASK) {
      if (typeof existing[k] === 'string') out[k] = existing[k];
      else delete out[k];
    }
  }
  return out;
}

export async function GET(req: Request, { params }: { params: Promise<{ id: string }> }) {
  const { id } = await params;
  const def = getConnector(id);
  if (!def) return NextResponse.json({ error: 'connector not found' }, { status: 404 });
  const inst = getInstalledConnector(id);
  const stored = inst?.config || {};
  const schema = settingsSchemaFor(id);
  const merged = { ...defaultsFor(id), ...stored };
  return NextResponse.json({
    settings: maskSecrets(merged, schema),
    schema,
    installed: !!inst,
  });
}

export async function POST(req: Request, { params }: { params: Promise<{ id: string }> }) {
  const { id } = await params;
  const def = getConnector(id);
  if (!def) return NextResponse.json({ error: 'connector not found' }, { status: 404 });

  const body = await req.json().catch(() => ({}));
  const settings = body?.settings ?? body;
  if (typeof settings !== 'object' || settings === null) {
    return NextResponse.json({ error: 'settings must be an object' }, { status: 400 });
  }

  const existing = getInstalledConnector(id);
  const schema = settingsSchemaFor(id);
  const merged = restoreSecrets(settings, existing?.config || {}, schema);
  const ok = setConnectorConfig(id, merged);
  if (!ok) return NextResponse.json({ error: 'failed to persist settings' }, { status: 500 });
  return NextResponse.json({ ok: true, settings: maskSecrets(merged, schema) });
}
