export const dynamic = 'force-dynamic';
export const maxDuration = 300;

import { NextRequest, NextResponse } from 'next/server';
import { prisma } from '@/lib/db';
import { requireDFAuth } from '@/lib/dark-factory/auth-guard';
import { runStandalonePipeline, StandalonePipelineRequest } from '@/lib/dark-factory/agents/standalone-pipeline';

/**
 * POST — Bridge: converts an approved intake into a StandalonePipelineRequest
 * and fires code generation. Requires gate === 'deliverables_approved'.
 *
 * Assembles a structured, engineering-grade prompt from:
 *   - Problem statement
 *   - Entities + fields + relationships
 *   - Deliverables list + acceptance criteria
 *   - Visual context (ERD/flow summaries)
 *   - Constraints & integrations
 */
export async function POST(req: NextRequest, { params }: { params: { id: string } }) {
  const authResult = await requireDFAuth();
  if (!authResult.authorized) return authResult.response;

  const intake = await prisma.dfIntake.findUnique({
    where: { id: params.id },
    include: {
      entities: { orderBy: { sortOrder: 'asc' } },
      visuals: { orderBy: { sortOrder: 'asc' } },
      deliverables: { orderBy: { sortOrder: 'asc' } },
      acceptanceCriteria: { orderBy: { sortOrder: 'asc' } },
    },
  });

  if (!intake) return NextResponse.json({ error: 'Intake not found' }, { status: 404 });
  if (intake.gate !== 'deliverables_approved') {
    return NextResponse.json(
      { error: `Intake must be in deliverables_approved state to generate code. Current: ${intake.gate}` },
      { status: 400 }
    );
  }

  // ── Assemble structured prompt ──────────────────────────────────

  const sections: string[] = [];

  // Cast JSON arrays safely
  const targetUsers = Array.isArray(intake.targetUsers) ? intake.targetUsers as string[] : [];
  const coreWorkflows = Array.isArray(intake.coreWorkflows) ? intake.coreWorkflows as string[] : [];
  const constraintsList = Array.isArray(intake.constraints) ? intake.constraints as string[] : [];
  const integrationsList = Array.isArray(intake.integrations) ? intake.integrations as string[] : [];

  // 1. Problem Statement
  sections.push(`## Project Brief\n\n**${intake.title}**\nDomain: ${intake.businessDomain}\n\n${intake.problemStatement}`);

  // 2. Target Users & Workflows
  if (targetUsers.length > 0) {
    sections.push(`## Target Users\n${targetUsers.map(u => `- ${u}`).join('\n')}`);
  }
  if (coreWorkflows.length > 0) {
    sections.push(`## Core Workflows\n${coreWorkflows.map(w => `- ${w}`).join('\n')}`);
  }

  // 3. Data Model (entities)
  if (intake.entities.length > 0) {
    const entityLines = intake.entities.map(e => {
      const fields = Array.isArray(e.fields)
        ? (e.fields as Array<{ name: string; type: string }>).map(f => `    ${f.name}: ${f.type}`).join('\n')
        : '';
      const rels = Array.isArray(e.relationships)
        ? (e.relationships as Array<{ target: string; type: string }>).map(r => `    → ${r.target} (${r.type})`).join('\n')
        : '';
      return `### ${e.name}${e.isCore ? ' (core)' : ''}${e.description ? `\n${e.description}` : ''}\n${fields}${rels ? `\n  Relationships:\n${rels}` : ''}`;
    }).join('\n\n');
    sections.push(`## Data Model\n\n${entityLines}`);
  }

  // 4. Visual context summaries (ERD/flows already approved)
  const visualSummaries = intake.visuals
    .filter(v => v.status === 'approved' || v.status === 'draft')
    .map(v => `### ${v.title} (${v.type})\n\`\`\`mermaid\n${v.content}\n\`\`\``)
    .join('\n\n');
  if (visualSummaries) {
    sections.push(`## Approved Visual Architecture\n\n${visualSummaries}`);
  }

  // 5. Deliverables checklist
  if (intake.deliverables.length > 0) {
    const delLines = intake.deliverables.map((d, i) => {
      return `${i + 1}. **${d.name}** (${d.type})${d.description ? ` — ${d.description}` : ''}${d.acceptanceCriteria ? `\n   Acceptance: ${d.acceptanceCriteria}` : ''}`;
    }).join('\n');
    sections.push(`## Required Deliverables\n\nGenerate ALL of the following:\n${delLines}`);
  }

  // 6. Acceptance Criteria
  if (intake.acceptanceCriteria.length > 0) {
    const grouped = { must: [] as string[], should: [] as string[], nice_to_have: [] as string[] };
    intake.acceptanceCriteria.forEach(c => {
      const bucket = grouped[c.priority as keyof typeof grouped] || grouped.nice_to_have;
      bucket.push(c.description);
    });
    const acLines: string[] = [];
    if (grouped.must.length) acLines.push(`**MUST:**\n${grouped.must.map(d => `- ${d}`).join('\n')}`);
    if (grouped.should.length) acLines.push(`**SHOULD:**\n${grouped.should.map(d => `- ${d}`).join('\n')}`);
    if (grouped.nice_to_have.length) acLines.push(`**NICE TO HAVE:**\n${grouped.nice_to_have.map(d => `- ${d}`).join('\n')}`);
    sections.push(`## Acceptance Criteria\n\n${acLines.join('\n\n')}`);
  }

  // 7. Constraints & Integrations
  if (constraintsList.length > 0) {
    sections.push(`## Constraints\n${constraintsList.map(c => `- ${c}`).join('\n')}`);
  }
  if (integrationsList.length > 0) {
    sections.push(`## Required Integrations\n${integrationsList.map(ig => `- ${ig}`).join('\n')}`);
  }

  // 8. Budget/timeline context (informational)
  if (intake.budget || intake.timeline) {
    sections.push(`## Context\n${intake.budget ? `Budget: ${intake.budget}` : ''}${intake.budget && intake.timeline ? ' | ' : ''}${intake.timeline ? `Timeline: ${intake.timeline}` : ''}`);
  }

  const assembledPrompt = sections.join('\n\n---\n\n');

  // ── Update gate and fire pipeline ─────────────────────────────

  await prisma.dfIntake.update({
    where: { id: params.id },
    data: { gate: 'code_generating', generationRequestId: null },
  });

  await prisma.dfRevisionLog.create({
    data: {
      intakeId: params.id,
      gate: 'deliverables_approved',
      action: 'code_generation_started',
      changedBy: authResult.userId || 'system',
      reason: `Assembled ${sections.length}-section prompt from ${intake.entities.length} entities, ${intake.deliverables.length} deliverables, ${intake.acceptanceCriteria.length} acceptance criteria`,
    },
  });

  // Create a GenerationRequest record to track the pipeline
  const dbRequest = await prisma.generationRequest.create({
    data: {
      prompt: assembledPrompt,
      priority: 'normal',
      requestedBy: 'intake-pipeline',
      status: 'pending',
    },
  });

  // Link generation request to intake for traceability
  await prisma.dfIntake.update({
    where: { id: params.id },
    data: { generationRequestId: dbRequest.id },
  });

  const pipelineRequest: StandalonePipelineRequest = {
    prompt: assembledPrompt,
    language: intake.targetLanguage || 'typescript-react',
    database: intake.targetDatabase || 'postgresql',
  };

  // Fire in background
  runPipelineInBackground(dbRequest.id, params.id, pipelineRequest);

  return NextResponse.json({
    success: true,
    taskId: dbRequest.id,
    intakeId: params.id,
    gate: 'code_generating',
    promptSections: sections.length,
    promptLength: assembledPrompt.length,
    message: 'Code generation started. Pipeline is running. Poll /api/dark-factory/status/{taskId} for progress.',
  });
}

async function runPipelineInBackground(requestId: string, intakeId: string, pipelineRequest: StandalonePipelineRequest) {
  try {
    console.log(`[DF Intake→Generate] Starting pipeline for intake ${intakeId}, request ${requestId}`);
    const result = await runStandalonePipeline(pipelineRequest);

    const requestStatus = result.status === 'failed' ? 'failed'
      : result.status === 'needs_human_review' ? 'needs_review'
      : 'completed';

    await prisma.generationRequest.update({
      where: { id: requestId },
      data: { status: requestStatus },
    });

    // Update intake gate to complete (or leave at code_generating if failed)
    const newGate = result.status === 'failed' ? 'deliverables_approved' : 'complete';
    await prisma.dfIntake.update({
      where: { id: intakeId },
      data: { gate: newGate },
    });

    // M4: Link deliverables to generated artifacts by matching type/name patterns
    if (result.status !== 'failed' && result.taskId && result.artifacts.length > 0) {
      try {
        const deliverables = await prisma.dfDeliverable.findMany({ where: { intakeId } });
        const artifacts = await prisma.generatedArtifact.findMany({
          where: { taskId: result.taskId },
        });
        // Best-effort matching: update deliverable status to 'generated'
        for (const del of deliverables) {
          const matchedArtifact = artifacts.find(a => {
            const pathLower = a.path.toLowerCase();
            const nameLower = del.name.toLowerCase().replace(/\s+/g, '-');
            return pathLower.includes(nameLower) || pathLower.includes(del.type);
          });
          await prisma.dfDeliverable.update({
            where: { id: del.id },
            data: {
              status: matchedArtifact ? 'generated' : 'planned',
            },
          });
        }
      } catch (linkError) {
        console.warn('[DF Intake→Generate] Deliverable→artifact linking failed:', linkError);
      }
    }

    await prisma.dfRevisionLog.create({
      data: {
        intakeId,
        gate: 'code_generating',
        action: result.status === 'failed' ? 'code_generation_failed' : 'code_generation_complete',
        changedBy: 'system',
        reason: `Pipeline ${result.status}. Task: ${result.taskId}. Artifacts: ${result.artifacts.length}. Review: ${result.qualityReport?.reviewScore ?? 'N/A'}%, Tests: ${result.qualityReport?.testAccuracy ?? 'N/A'}%`,
      },
    });

    console.log(`[DF Intake→Generate] Pipeline completed for intake ${intakeId}: ${result.status}`);
  } catch (error) {
    console.error(`[DF Intake→Generate] Pipeline failed for intake ${intakeId}:`, error);
    await prisma.generationRequest.update({
      where: { id: requestId },
      data: { status: 'failed' },
    }).catch(() => {});

    // Revert gate so they can retry
    await prisma.dfIntake.update({
      where: { id: intakeId },
      data: { gate: 'deliverables_approved' },
    }).catch(() => {});

    await prisma.dfRevisionLog.create({
      data: {
        intakeId,
        gate: 'code_generating',
        action: 'code_generation_failed',
        changedBy: 'system',
        reason: `Pipeline error: ${error instanceof Error ? error.message : 'Unknown'}`,
      },
    }).catch(() => {});
  }
}