/**
 * Project-level encrypted secret scratchpad.
 * Closes BETA_LAUNCH_PLAN P6.D2.
 *
 * GET  /api/projects/[projectId]/secrets        — list key names only (never values)
 * POST /api/projects/[projectId]/secrets        — set/update a secret { key, value }
 *
 * Values are encrypted at-rest with AES-256-GCM via the existing
 * `lib/auth/secret-box.ts` (same envelope used for workspace API keys and
 * Gitea bot PATs). The plaintext value is NEVER returned by the list route.
 * Use a dedicated GET /secrets/[key] route (below) if you need to surface
 * it to the AI.
 *
 * Table created lazily on first write.
 */
import { NextResponse } from "next/server";
import { query } from "@/lib/db-postgres";
import { withTenantProject } from "@/lib/server/api-handler";
import { encryptSecret } from "@/lib/auth/secret-box";
import { log } from "@/lib/server/logger";

let tableReady = false;
async function ensureTable() {
  if (tableReady) return;
  await query(`
    CREATE TABLE IF NOT EXISTS fs_project_secrets (
      project_id   TEXT NOT NULL,
      key          TEXT NOT NULL,
      value_enc    TEXT NOT NULL,   -- AES-256-GCM encrypted, base64
      created_at   TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      updated_at   TIMESTAMPTZ NOT NULL DEFAULT NOW(),
      PRIMARY KEY (project_id, key)
    )
  `);
  await query(
    `CREATE INDEX IF NOT EXISTS fs_project_secrets_project_idx ON fs_project_secrets (project_id)`,
  );
  tableReady = true;
}

/** GET — returns key names only, never values. */
export const GET = withTenantProject(
  async (_req, _ctx, { project }) => {
    await ensureTable();
    const rows = await query<{ key: string; updated_at: string }>(
      `SELECT key, updated_at FROM fs_project_secrets
       WHERE project_id = $1 ORDER BY key`,
      [project.id],
    );
    return NextResponse.json({ secrets: rows });
  },
);

/** POST — upsert a secret. Body: { key: string, value: string } */
export const POST = withTenantProject(
  async (req, _ctx, { project }) => {
    const body = await req.json().catch(() => ({})) as {
      key?: string;
      value?: string;
    };
    if (!body.key || typeof body.key !== "string") {
      return NextResponse.json({ error: "key is required" }, { status: 400 });
    }
    if (typeof body.value !== "string") {
      return NextResponse.json({ error: "value is required" }, { status: 400 });
    }
    if (body.key.length > 200) {
      return NextResponse.json(
        { error: "key must be ≤200 chars" },
        { status: 400 },
      );
    }

    await ensureTable();
    const valueEnc = encryptSecret(body.value);
    await query(
      `INSERT INTO fs_project_secrets (project_id, key, value_enc)
       VALUES ($1, $2, $3)
       ON CONFLICT (project_id, key) DO UPDATE SET
         value_enc  = EXCLUDED.value_enc,
         updated_at = NOW()`,
      [project.id, body.key.trim(), valueEnc],
    );
    log.info("project secret upserted", {
      route: "api.projects.secrets.post",
      projectId: project.id,
      key: body.key,
    });
    return NextResponse.json({ ok: true, key: body.key });
  },
);
