import { NextResponse } from "next/server";
import { authSession } from "@/lib/auth/session-server";
import { query, queryOne } from "@/lib/db-postgres";
import { callVibnChat } from "@/lib/ai/vibn-chat-model";

// Generate a complete PRD, Tech Architecture, and Execution Plan based on the objective

export async function POST(
  req: Request,
  ctx: { params: Promise<{ projectId: string }> },
) {
  const { projectId } = await ctx.params;
  const session = await authSession();
  if (!session?.user?.email) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const projectRow = await queryOne<{ data: any; slug: string }>(
    `SELECT fs_projects.data, fs_projects.slug FROM fs_projects
     JOIN fs_users u ON u.id = fs_projects.user_id
     WHERE fs_projects.id = $1 AND u.data->>'email' = $2 LIMIT 1`,
    [projectId, session.user.email],
  );
  if (!projectRow)
    return NextResponse.json({ error: "Project not found" }, { status: 404 });

  const body = await req.json().catch(() => ({}));
  const objective = String(
    body.objective || projectRow.data?.plan?.vision || "",
  ).trim();

  if (!objective) {
    return NextResponse.json(
      { error: "Objective is required to generate a PRD." },
      { status: 400 },
    );
  }

  // We run sequential LLM calls to construct the complete Spec Kit documentation

  // 1. Generate User Stories
  const storiesPrompt = `You are a Principal Product Manager. Your goal is to write DEEP, COMPREHENSIVE documentation that engineers and AI agents can reference when building the product.
Do not be brief. Exhaustively detail the user journeys. Do not talk about technology (databases, frameworks); focus purely on user value and behavior.

OBJECTIVE:
${objective}

You MUST follow this exact structure for every core actor/role in the platform. Be exhaustive.

# User Stories & Journeys

## Actor: [e.g., Buyer / Seller / Admin]
### [US-1.1] [Action-oriented title] (Priority: P1)
**Description:** [Deeply describe the journey from start to finish]
**Business Value:** [Why are we building this?]
**Edge Cases & Error States:**
- What happens if [edge case]?
- How do we handle [error state]?
**Out of Scope (v1):** [What are we explicitly NOT building yet?]

### [US-1.2] ...`;

  const storiesResponse = await callVibnChat({
    systemPrompt: storiesPrompt,
    messages: [
      { role: "user", content: "Generate deep, comprehensive User Stories." },
    ],
    temperature: 0.3,
  });
  const storiesMd = storiesResponse.text || "Failed to generate User Stories.";

  // 2. Generate Acceptance Criteria
  const acceptancePrompt = `You are a strict QA Engineer. Based on the User Stories, write EXHAUSTIVE Acceptance Criteria using BDD (Behavior-Driven Development) Given/When/Then syntax.
These criteria must be deep enough that an AI Agent can write unit tests and E2E tests against them.

USER STORIES:
${storiesMd}

You MUST follow this exact structure:

# Acceptance Criteria

## Feature: [Title from User Story]

### Scenario 1: Happy Path - [Description]
**Given** [initial context/state]
**And** [additional context]
**When** [action is taken]
**Then** [expected outcome]
**And** [additional outcome]

### Scenario 2: Edge Case - [Description]
**Given** [initial context/state]
...

## Global Functional Requirements
- **FR-001**: System MUST [specific, testable capability]
- **FR-002**: Users MUST be able to [interaction]`;

  const acceptanceResponse = await callVibnChat({
    systemPrompt: acceptancePrompt,
    messages: [
      { role: "user", content: "Generate exhaustive Acceptance Criteria." },
    ],
    temperature: 0.2,
  });
  const acceptanceMd =
    acceptanceResponse.text || "Failed to generate Acceptance Criteria.";

  // 3. Generate UI & Design Requirements
  const uiDesignPrompt = `You are a Lead Product Designer. Define the complete UI, UX, and Design System requirements. Be highly specific so frontend engineers and AI coders know exactly what Tailwind classes and components to use.

USER STORIES:
${storiesMd}

You MUST follow this exact structure:

# Design System

## Global Theme
**Vibe/Personality:** [Describe the aesthetic - e.g., "Minimalist, high-trust, SaaS"]
**Component Library:** [e.g., shadcn/ui, Tremor, raw Tailwind]
**Spacing & Radii:** [e.g., "Use 8px (rounded-lg) for cards, 4px (rounded-md) for buttons"]

## Color Palette
- **Primary:** [Hex code] - [Usage: CTAs, active states]
- **Secondary:** [Hex code] - [Usage: Secondary buttons, subtle highlights]
- **Background:** [Hex code] - [Usage: App background]
- **Surface:** [Hex code] - [Usage: Cards, modals]
- **Text:** [Hex codes for headings vs body]

## Typography
- **Headings:** [Font Name] - [Weights used]
- **Body:** [Font Name] - [Weights used]
- **Monospace:** [Font Name] - [Usage]

## Key Layouts
### 1. [Screen Name]
- **Structure:** [e.g., Sidebar left, content right]
- **Key Components:** [e.g., Data table with pagination, Hero section]
- **Mobile Behavior:** [How it collapses on small screens]`;

  const uiDesignResponse = await callVibnChat({
    systemPrompt: uiDesignPrompt,
    messages: [
      { role: "user", content: "Generate deep UI Design Requirements." },
    ],
    temperature: 0.3,
  });
  const uiDesignMd =
    uiDesignResponse.text || "Failed to generate UI Design Requirements.";

  // 4. Generate Measurable Success
  const successPrompt = `You are a Data Analyst and Growth Lead. Define the precise, measurable success metrics for this project.
Do not use vague metrics. Use specific KPIs, target conversion rates, and performance benchmarks.

USER STORIES:
${storiesMd}

You MUST follow this exact structure:

# Success Metrics & KPIs

## Business Outcomes
- **SC-001 (Activation):** [e.g., "20% of signups complete onboarding within 24h"]
- **SC-002 (Retention):** [e.g., "40% MAU retention after 3 months"]

## Technical Benchmarks
- **TM-001 (Latency):** [e.g., "95th percentile API response < 200ms"]
- **TM-002 (Lighthouse):** [e.g., "Google Lighthouse performance score > 90"]

## North Star Metric
**[Metric Name]:** [Why this matters above all else]`;

  const successResponse = await callVibnChat({
    systemPrompt: successPrompt,
    messages: [{ role: "user", content: "Generate strict Success Criteria." }],
    temperature: 0.2,
  });
  const successMd =
    successResponse.text || "Failed to generate Success Criteria.";

  // 5. Generate Technical Context
  const techPrompt = `You are a Principal Software Architect. Define the definitive Technical Context and Infrastructure roadmap for this project.
Be exhaustive. If a tool isn't listed here, the AI coders will not use it.
Your choices MUST default to: Next.js 15 (App Router), Postgres, Tailwind CSS, and NextAuth.js (unless the objective demands otherwise).

USER STORIES:
${storiesMd}
UI DESIGN:
${uiDesignMd}

You MUST follow this exact structure:

# Technical Context & Architecture

## Core Stack
- **Framework:** Next.js 15 (App Router)
- **Language:** TypeScript (Strict mode enabled)
- **Database:** PostgreSQL
- **ORM:** Prisma
- **Authentication:** NextAuth.js v5
- **Styling:** Tailwind CSS + shadcn/ui

## Infrastructure & Hosting
- **Deployment:** [e.g., Coolify, Vercel, Docker]
- **File Storage:** [e.g., AWS S3, local, Vercel Blob]
- **Background Jobs:** [e.g., In-memory, Redis/BullMQ, Inngest]

## Integrations & APIs
- **[Integration 1]:** [What it does, e.g., "Stripe for payments and subscriptions"]
- **[Integration 2]:** [e.g., "OpenAI/Gemini for LLM processing"]

## Technical Constraints & Standards
- [e.g., "No client-side data fetching; use React Server Components where possible"]
- [e.g., "All DB queries must go through a dedicated data-access layer (DAL)"]`;

  const techResponse = await callVibnChat({
    systemPrompt: techPrompt,
    messages: [
      { role: "user", content: "Generate comprehensive Technical Context." },
    ],
    temperature: 0.2,
  });
  const techMd = techResponse.text || "Failed to generate Technical Context.";

  // 6. Generate Data Model
  const dataModelPrompt = `You are a Staff Database Architect. Write an EXHAUSTIVE data model based on the Technical Context and User Stories.
This model must be detailed enough that an AI coder can directly translate it into a Prisma schema.md or SQL migration. Include relationships, indexes, and enums.

TECHNICAL CONTEXT:
${techMd}
USER STORIES:
${storiesMd}

You MUST follow this exact structure:

# Data Model

## Enums
- **[EnumName]**: [VALUE_1, VALUE_2]

## Tables / Models

### \`[TableName]\`
**Purpose:** [What this stores]
**Fields:**
- \`id\` (String/UUID, PK) - Primary Key
- \`createdAt\` (DateTime) - Auto-generated timestamp
- \`[fieldName]\` ([Type]) - [Description, Default values, Nullability]
**Relationships:**
- \`[relationName]\` -> \`[OtherTable]\` (One-to-Many, Many-to-Many)
**Indexes:**
- [List any columns that require indexing for performance]

*(Repeat for all necessary tables)*`;

  const dataModelResponse = await callVibnChat({
    systemPrompt: dataModelPrompt,
    messages: [
      { role: "user", content: "Generate a deep, exhaustive Data Model." },
    ],
    temperature: 0.2,
  });
  const dataModelMd =
    dataModelResponse.text || "Failed to generate Data Model.";

  // 7. Generate File Structure
  const fileStructurePrompt = `You are a Staff Software Engineer. Map out the EXACT file structure for this Next.js App Router application.
This tree will be the literal blueprint the AI agents use to scaffold the application. It must be exhaustive. Include critical \`layout.tsx\`, \`page.tsx\`, \`route.ts\`, and component files.

TECHNICAL CONTEXT:
${techMd}
DATA MODEL:
${dataModelMd}

You MUST output a detailed ASCII file tree with comments explaining the purpose of each critical directory and file.

# File Structure

\`\`\`text
/
├── package.json
├── prisma/
│   └── schema.prisma        # Database schema
├── src/
│   ├── app/
│   │   ├── (auth)/          # Authentication route group
│   │   │   ├── login/page.tsx
│   │   │   └── register/page.tsx
│   │   ├── api/             # Backend API endpoints
│   │   │   └── webhooks/stripe/route.ts
│   │   ├── layout.tsx       # Root layout (Providers, Fonts)
│   │   └── page.tsx         # Marketing homepage
│   ├── components/
│   │   ├── ui/              # shadcn/ui generic components
│   │   └── shared/          # App-specific shared components (e.g., Navbar)
│   └── lib/
│       ├── db.ts            # Prisma client singleton
│       └── utils.ts         # Tailwind merge utilities
\`\`\`
*(Expand this tree to cover all routes and components required by the User Stories)*`;

  const fileStructureResponse = await callVibnChat({
    systemPrompt: fileStructurePrompt,
    messages: [
      { role: "user", content: "Generate a comprehensive File Structure." },
    ],
    temperature: 0.2,
  });
  const fileStructureMd =
    fileStructureResponse.text || "Failed to generate File Structure.";

  // 8. Generate the Execution Plan (Tasks)
  const tasksPrompt = `You are a Technical Project Manager.
Based on the User Stories and File Structure, break the implementation down into an atomic, dependency-ordered Task List.
These tasks will be handed to an autonomous AI agent to execute. They MUST be atomic (one clear PR/commit per task), chronological, and highly specific.

USER STORIES:
${storiesMd}
FILE STRUCTURE:
${fileStructureMd}

You MUST format each task EXACTLY as a markdown bullet with a checkbox, a phase tag, and a description containing the exact file paths.

# Execution Plan

## Phase 1: Infrastructure & DB Foundation
- [ ] [Phase 1] Initialize Next.js project, Tailwind, and layout.tsx
- [ ] [Phase 1] Setup Prisma schema based on the data model and run initial migration

## Phase 2: Core User Journeys
- [ ] [Phase 2] Build the API route for [Feature] in \`src/app/api/.../route.ts\`
- [ ] [Phase 2] Build the frontend UI component in \`src/app/.../page.tsx\` integrating with the API

## Phase 3: Polish & Deployment
- [ ] [Phase 3] ...`;

  const tasksResponse = await callVibnChat({
    systemPrompt: tasksPrompt,
    messages: [
      { role: "user", content: "Generate an atomic Execution Plan task list." },
    ],
    temperature: 0.2,
  });
  const tasksMd = tasksResponse.text || "";

  // 9. Generate the QA Checklist
  const checklistPrompt = `You are a strict QA Automation Engineer.
Write an exhaustive Pre-Flight Checklist. The AI agent MUST verify every single item on this list before declaring the feature "Done" and shipping to production.

ACCEPTANCE CRITERIA:
${acceptanceMd}
FILE STRUCTURE:
${fileStructureMd}

You MUST follow this exact structure:

# Pre-Flight QA Checklist

## Build & Environment
- [ ] \`npm run build\` completes with 0 TypeScript compilation errors.
- [ ] All required environment variables are documented in \`.env.example\`.
- [ ] Prisma migrations are synced with the database.

## Security & Auth
- [ ] Protected routes correctly redirect unauthenticated users to \`/login\`.
- [ ] Users cannot access or mutate data belonging to other users (Tenant isolation).

## Core Scenarios Verification
- [ ] Happy Path: [Specific user action] works end-to-end without console errors.
- [ ] Edge Case: [Specific edge case] is handled gracefully with a user-facing error message.
- [ ] ...`;

  const checklistResponse = await callVibnChat({
    systemPrompt: checklistPrompt,
    messages: [
      { role: "user", content: "Generate an exhaustive QA Checklist." },
    ],
    temperature: 0.2,
  });
  const checklistMd =
    checklistResponse.text || "Failed to generate QA Checklist.";

  // 6. Parse the tasks string into the JSON array expected by the DB
  // Extract all `- [ ] [Group] Task description` lines
  const taskLines = tasksMd.match(/- \[[ x]\] \[(.*?)\] (.*)/g) || [];
  const parsedTasks = taskLines
    .map((line) => {
      const match = line.match(/- \[[ x]\] \[(.*?)\] (.*)/);
      if (!match) return null;
      return {
        id: Math.random().toString(36).slice(2, 11),
        title: `[${match[1]}] ${match[2]}`, // Fixed backticks
        description: "",
        status: "open",
        createdAt: new Date().toISOString(),
      };
    })
    .filter(Boolean);

  // Update the Database Plan
  const currentPlan = projectRow.data?.plan || {};

  // Create a map of the new generated decisions
  const generatedDecisions = [
    {
      id: "prd_stories",
      title: "User Stories",
      choice: "Auto-generated",
      why: storiesMd,
      createdAt: new Date().toISOString(),
    },
    {
      id: "prd_acceptance",
      title: "Acceptance Criteria",
      choice: "Auto-generated",
      why: acceptanceMd,
      createdAt: new Date().toISOString(),
    },
    {
      id: "prd_success",
      title: "Success Metrics",
      choice: "Auto-generated",
      why: successMd,
      createdAt: new Date().toISOString(),
    },
    {
      id: "prd_ui_design",
      title: "UI & Design Requirements",
      choice: "Auto-generated",
      why: uiDesignMd,
      createdAt: new Date().toISOString(),
    },
    {
      id: "prd_tech_context",
      title: "Technical Context",
      choice: "Auto-generated",
      why: techMd,
      createdAt: new Date().toISOString(),
    },
    {
      id: "prd_data_model",
      title: "Data Model",
      choice: "Auto-generated",
      why: dataModelMd,
      createdAt: new Date().toISOString(),
    },
    {
      id: "prd_file_structure",
      title: "File Structure",
      choice: "Auto-generated",
      why: fileStructureMd,
      createdAt: new Date().toISOString(),
    },
    {
      id: "prd_tasks",
      title: "Task Breakdown",
      choice: "Auto-generated",
      why: tasksMd,
      createdAt: new Date().toISOString(),
    },
    {
      id: "prd_checklist",
      title: "QA Checklist",
      choice: "Auto-generated",
      why: checklistMd,
      createdAt: new Date().toISOString(),
    },
  ];

  // Merge the new decisions into the existing decisions array (updating if they exist, appending if they don't)
  const existingDecisions = currentPlan.decisions || [];
  const mergedDecisions = [...existingDecisions];

  for (const gen of generatedDecisions) {
    const idx = mergedDecisions.findIndex((d: any) => d.id === gen.id);
    if (idx >= 0) {
      mergedDecisions[idx] = gen;
    } else {
      mergedDecisions.push(gen);
    }
  }

  const updatedPlan = {
    ...currentPlan,
    vision: objective,
    tasks: parsedTasks.length > 0 ? parsedTasks : currentPlan.tasks,
    blueprint: {
      stories: storiesMd,
      acceptance: acceptanceMd,
      success: successMd,
      ui_design: uiDesignMd,
      tech_context: techMd,
      data_model: dataModelMd,
      file_structure: fileStructureMd,
      tasks: tasksMd,
      checklist: checklistMd,
    },
    decisions: mergedDecisions, // Legacy fallback
  };

  await query(
    `UPDATE fs_projects SET data = jsonb_set(data, '{plan}', $2::jsonb) WHERE id = $1`,
    [projectId, JSON.stringify(updatedPlan)],
  );

  return NextResponse.json({ plan: updatedPlan });
}
