/**
 * Backfill endpoint: per-Vibn-project Coolify isolation.
 *
 * For each Vibn project in the caller's workspace, this:
 *   1. Mints a dedicated `vibn-{ws}-{slug}` Coolify project (idempotent).
 *   2. Records the project's existing linked Coolify resource (coolifyAppUuid
 *      / coolifyServiceUuid) in fs_project_resources.
 *
 * After backfill, `apps_list { projectId }` will only surface the user's
 * actually-owned resources for that project, even when multiple projects
 * legacy-share a single Coolify project.
 *
 * Safe to re-run; everything is idempotent.
 */

import { NextResponse } from 'next/server';
import { query } from '@/lib/db-postgres';
import { requireWorkspacePrincipal } from '@/lib/auth/workspace-auth';
import { getOrCreateProvisionedWorkspace, type VibnWorkspace } from '@/lib/workspaces';
import {
  ensureProjectCoolifyProject,
  ensureProjectResourcesTable,
  linkResourceToProject,
  type ResourceType,
} from '@/lib/projects';

interface ProjectRow {
  id: string;
  slug: string;
  data: any;
}

interface BackfillReport {
  projectId: string;
  projectName: string;
  beforeCoolifyProjectUuid: string | null;
  afterCoolifyProjectUuid: string | null;
  linkedResources: Array<{ uuid: string; type: ResourceType }>;
  warnings: string[];
}

export async function POST(request: Request) {
  // Three accepted auth modes:
  //   1. NextAuth session (browser)
  //   2. Bearer vibn_sk_... workspace API key (matches /api/mcp)
  //   3. Bearer <NEXTAUTH_SECRET> + ?email=<owner> (ops bootstrap so the
  //      maintainer can curl the backfill from a workstation without
  //      needing a session cookie or pre-minted API key)
  let ws: VibnWorkspace | null = null;

  const authHeader = request.headers.get('authorization') ?? '';
  const bearer = authHeader.toLowerCase().startsWith('bearer ')
    ? authHeader.slice(7).trim()
    : '';
  const opsSecret = process.env.NEXTAUTH_SECRET;
  const url = new URL(request.url);
  const opsEmail = url.searchParams.get('email');

  if (bearer && opsSecret && bearer === opsSecret && opsEmail) {
    const users = await query<{ id: string }>(
      `SELECT id FROM fs_users WHERE data->>'email' = $1 LIMIT 1`,
      [opsEmail],
    );
    if (users.length === 0) {
      return NextResponse.json({ error: `No fs_users row for ${opsEmail}` }, { status: 404 });
    }
    ws = await getOrCreateProvisionedWorkspace({
      userId: users[0].id,
      email: opsEmail,
      displayName: opsEmail,
    });
  } else {
    const principal = await requireWorkspacePrincipal(request);
    if (principal instanceof NextResponse) return principal;
    ws = principal.workspace;
  }

  if (!ws) {
    return NextResponse.json({ error: 'Workspace not provisioned' }, { status: 503 });
  }

  await ensureProjectResourcesTable();

  const projects = await query<ProjectRow>(
    `SELECT id, slug, data
       FROM fs_projects
      WHERE vibn_workspace_id = $1 OR workspace = $2
      ORDER BY created_at ASC`,
    [ws.id, ws.slug],
  );

  const reports: BackfillReport[] = [];

  for (const p of projects) {
    const data = p.data || {};
    const projectName = data.productName || data.name || data.title || p.slug;
    const before = (data.coolifyProjectUuid as string) || null;
    const warnings: string[] = [];

    let after = before;
    try {
      // ensureProjectCoolifyProject is a no-op when already set.
      const ensured = await ensureProjectCoolifyProject(p.id, ws, {
        projectSlug: p.slug,
        projectName,
      });
      if (ensured) after = ensured;
    } catch (err: any) {
      warnings.push(`coolify provision failed: ${err?.message ?? err}`);
    }

    // Record any pre-existing single-resource link.
    const linked: Array<{ uuid: string; type: ResourceType }> = [];
    const candidate: Array<[string | undefined, ResourceType]> = [
      [data.coolifyServiceUuid, 'service'],
      [data.coolifyAppUuid, 'application'],
      [data.coolifyDatabaseUuid, 'database'],
    ];
    for (const [uuid, type] of candidate) {
      if (typeof uuid === 'string' && uuid.length > 0) {
        try {
          await linkResourceToProject(p.id, ws.slug, uuid, type);
          linked.push({ uuid, type });
        } catch (err: any) {
          warnings.push(`link ${type}=${uuid} failed: ${err?.message ?? err}`);
        }
      }
    }

    reports.push({
      projectId: p.id,
      projectName,
      beforeCoolifyProjectUuid: before,
      afterCoolifyProjectUuid: after,
      linkedResources: linked,
      warnings,
    });
  }

  return NextResponse.json({
    workspace: ws.slug,
    processed: reports.length,
    reports,
  });
}
