/**
 * Tutorial Documentation Template
 * Generates step-by-step tutorials based on topics
 */

import { DocumentationIntent } from '../../../types/workflow';
import { DocumentationTemplate, TemplateContext } from './base-template';

export class TutorialTemplate extends DocumentationTemplate {
  canHandle(intent: DocumentationIntent): boolean {
    return intent.type === 'tutorial';
  }

  generate(context: TemplateContext): string {
    const { intent, workflow } = context;

    let content = `# Tutorial`;

    if (intent.scope) {
      content += `: ${this.capitalize(intent.scope)}`;
    }

    content += '\n\n';

    if (workflow.workflow.description) {
      content += `${workflow.workflow.description}\n\n`;
    }

    // Generate tutorials based on topics
    if (intent.topics && intent.topics.length > 0) {
      for (const topic of intent.topics) {
        content += this.generateTutorialForTopic(topic, context);
      }
    } else if (intent.scope) {
      // Generate general tutorial for the scope
      content += this.generateScopeTutorial(intent.scope, context);
    } else {
      // Generate getting started tutorial
      content += this.generateGettingStartedTutorial(context);
    }

    content += this.generateFooter(context);

    return content;
  }

  private generateTutorialForTopic(topic: string, context: TemplateContext): string {
    // Map topics to tutorial generators
    switch (topic) {
      case 'first_endpoint':
      case 'create_endpoint':
        return this.tutorialCreateEndpoint(context);

      case 'add_authentication':
      case 'authentication':
        return this.tutorialAddAuthentication(context);

      case 'create_model':
      case 'define_model':
        return this.tutorialCreateModel(context);

      case 'add_relationship':
      case 'relationships':
        return this.tutorialAddRelationship(context);

      case 'frontend_integration':
      case 'connect_frontend':
        return this.tutorialFrontendIntegration(context);

      case 'testing':
      case 'write_tests':
        return this.tutorialWriteTests(context);

      case 'deployment':
        return this.tutorialDeployment(context);

      default:
        return `## ${this.capitalize(topic.replace(/_/g, ' '))}\n\n` +
               `Tutorial for ${topic} coming soon.\n\n`;
    }
  }

  private generateScopeTutorial(scope: string, context: TemplateContext): string {
    switch (scope) {
      case 'api':
      case 'backend':
        return this.tutorialCreateEndpoint(context);
      case 'database':
        return this.tutorialCreateModel(context);
      case 'frontend':
        return this.tutorialFrontendIntegration(context);
      case 'authentication':
        return this.tutorialAddAuthentication(context);
      default:
        return this.generateGettingStartedTutorial(context);
    }
  }

  private generateGettingStartedTutorial(context: TemplateContext): string {
    const { extendedWorkflow } = context;

    let content = `## Getting Started\n\n`;
    content += `This tutorial will walk you through building your first feature.\n\n`;

    // Step 1: Set up the environment
    content += `### Step 1: Set Up Your Environment\n\n`;
    content += `Make sure you've completed the setup guide first:\n\n`;
    content += `1. Install all dependencies\n`;
    content += `2. Configure environment variables\n`;
    content += `3. Run database migrations\n`;
    content += `4. Start the development servers\n\n`;

    // Step 2: Create your first model
    if (extendedWorkflow?.models) {
      content += `### Step 2: Understanding the Data Models\n\n`;
      content += `Your application has the following models:\n\n`;

      for (const modelName of Object.keys(extendedWorkflow.models)) {
        content += `- **${modelName}**: Represents ${modelName.toLowerCase()} data\n`;
      }
      content += '\n';
    }

    // Step 3: Make your first API call
    content += `### Step 3: Make Your First API Call\n\n`;
    content += `Let's test the API:\n\n`;
    content += '```bash\n';
    content += `curl http://localhost:3001/api/health\n`;
    content += '```\n\n';

    return content;
  }

  private tutorialCreateEndpoint(context: TemplateContext): string {
    const { extendedWorkflow } = context;
    const _backend = extendedWorkflow?.technology?.backend;

    let content = `## Creating Your First API Endpoint\n\n`;
    content += `Learn how to add a new endpoint to your API.\n\n`;

    // Language/framework specific instructions
    if (_backend?.language === 'typescript' && _backend?.framework === 'express') {
      content += this.tutorialCreateEndpointTypeScriptExpress(context);
    } else if (_backend?.language === 'python' && _backend?.framework === 'flask') {
      content += this.tutorialCreateEndpointPythonFlask(context);
    } else {
      content += this.tutorialCreateEndpointGeneric(context);
    }

    return content;
  }

  private tutorialCreateEndpointTypeScriptExpress(_context: TemplateContext): string {
    let content = `### Step 1: Define the Route\n\n`;
    content += `Create a new route file in \`backend/src/routes/\`:\n\n`;
    content += '**backend/src/routes/items.ts:**\n';
    content += '```typescript\n';
    content += `import { Router } from 'express';\n`;
    content += `import { PrismaClient } from '@prisma/client';\n\n`;
    content += `const router = Router();\n`;
    content += `const prisma = new PrismaClient();\n\n`;
    content += `// GET /api/items\n`;
    content += `router.get('/', async (req, res) => {\n`;
    content += `  const items = await prisma.item.findMany();\n`;
    content += `  res.json(items);\n`;
    content += `});\n\n`;
    content += `export default router;\n`;
    content += '```\n\n';

    content += `### Step 2: Register the Route\n\n`;
    content += `Add the route to \`backend/src/index.ts\`:\n\n`;
    content += '```typescript\n';
    content += `import itemsRouter from './routes/items';\n\n`;
    content += `app.use('/api/items', itemsRouter);\n`;
    content += '```\n\n';

    content += `### Step 3: Test the Endpoint\n\n`;
    content += '```bash\n';
    content += `curl http://localhost:3001/api/items\n`;
    content += '```\n\n';

    return content;
  }

  private tutorialCreateEndpointPythonFlask(_context: TemplateContext): string {
    let content = `### Step 1: Create a Blueprint\n\n`;
    content += `Create a new file in \`backend/routes/\`:\n\n`;
    content += '**backend/routes/items.py:**\n';
    content += '```python\n';
    content += `from flask import Blueprint, jsonify\n`;
    content += `from models import db, Item\n\n`;
    content += `items_bp = Blueprint('items', __name__)\n\n`;
    content += `@items_bp.route('/items', methods=['GET'])\n`;
    content += `def get_items():\n`;
    content += `    items = Item.query.all()\n`;
    content += `    return jsonify([item.to_dict() for item in items])\n`;
    content += '```\n\n';

    content += `### Step 2: Register the Blueprint\n\n`;
    content += `Add to \`backend/app.py\`:\n\n`;
    content += '```python\n';
    content += `from routes.items import items_bp\n\n`;
    content += `app.register_blueprint(items_bp, url_prefix='/api')\n`;
    content += '```\n\n';

    content += `### Step 3: Test\n\n`;
    content += '```bash\n';
    content += `curl http://localhost:5000/api/items\n`;
    content += '```\n\n';

    return content;
  }

  private tutorialCreateEndpointGeneric(_context: TemplateContext): string {
    return `Follow your framework's documentation for creating endpoints.\n\n`;
  }

  private tutorialAddAuthentication(context: TemplateContext): string {
    const { extendedWorkflow } = context;
    const provider = extendedWorkflow?.auth?.provider;

    let content = `## Adding Authentication\n\n`;
    content += `Learn how to protect your endpoints with authentication.\n\n`;

    if (provider === 'clerk') {
      content += this.tutorialClerkAuth(context);
    } else {
      content += this.tutorialGenericAuth(context);
    }

    return content;
  }

  private tutorialClerkAuth(_context: TemplateContext): string {
    let content = `### Step 1: Install Clerk SDK\n\n`;
    content += `Clerk is already configured in your project.\n\n`;

    content += `### Step 2: Protect an Endpoint\n\n`;
    content += `Use the Clerk middleware:\n\n`;
    content += '```typescript\n';
    content += `import { requireAuth } from '../middleware/clerk';\n\n`;
    content += `router.get('/protected', requireAuth, async (req, res) => {\n`;
    content += `  const userId = req.auth.userId;\n`;
    content += `  res.json({ message: 'Protected route', userId });\n`;
    content += `});\n`;
    content += '```\n\n';

    content += `### Step 3: Test\n\n`;
    content += `Make a request with an auth token:\n\n`;
    content += '```typescript\n';
    content += `// Frontend\n`;
    content += `const { getToken } = useAuth();\n`;
    content += `const token = await getToken();\n\n`;
    content += `fetch('/api/protected', {\n`;
    content += `  headers: {\n`;
    content += `    'Authorization': \`Bearer \${token}\`\n`;
    content += `  }\n`;
    content += `});\n`;
    content += '```\n\n';

    return content;
  }

  private tutorialGenericAuth(_context: TemplateContext): string {
    return `Refer to your authentication provider's documentation.\n\n`;
  }

  private tutorialCreateModel(context: TemplateContext): string {
    const { extendedWorkflow } = context;
    const orm = extendedWorkflow?.technology?.backend?.orm;

    let content = `## Creating a Data Model\n\n`;

    if (orm === 'prisma') {
      content += this.tutorialPrismaModel(context);
    } else {
      content += this.tutorialGenericModel(context);
    }

    return content;
  }

  private tutorialPrismaModel(_context: TemplateContext): string {
    let content = `### Step 1: Define the Model\n\n`;
    content += `Edit \`backend/prisma/schema.prisma\`:\n\n`;
    content += '```prisma\n';
    content += `model Task {\n`;
    content += `  id          String   @id @default(uuid())\n`;
    content += `  title       String\n`;
    content += `  description String?\n`;
    content += `  completed   Boolean  @default(false)\n`;
    content += `  userId      String\n`;
    content += `  user        User     @relation(fields: [userId], references: [id])\n`;
    content += `  createdAt   DateTime @default(now())\n`;
    content += `  updatedAt   DateTime @updatedAt\n`;
    content += `}\n`;
    content += '```\n\n';

    content += `### Step 2: Run Migration\n\n`;
    content += '```bash\n';
    content += `cd backend\n`;
    content += `npx prisma migrate dev --name add-task-model\n`;
    content += '```\n\n';

    content += `### Step 3: Use the Model\n\n`;
    content += '```typescript\n';
    content += `const tasks = await prisma.task.findMany({\n`;
    content += `  where: { userId: req.auth.userId }\n`;
    content += `});\n`;
    content += '```\n\n';

    return content;
  }

  private tutorialGenericModel(_context: TemplateContext): string {
    return `Follow your ORM's documentation for creating models.\n\n`;
  }

  private tutorialAddRelationship(_context: TemplateContext): string {
    let content = `## Adding Relationships Between Models\n\n`;
    content += `Learn how to create relationships.\n\n`;

    content += `### One-to-Many Example\n\n`;
    content += `A User has many Tasks:\n\n`;
    content += '```prisma\n';
    content += `model User {\n`;
    content += `  id    String @id @default(uuid())\n`;
    content += `  tasks Task[]\n`;
    content += `}\n\n`;
    content += `model Task {\n`;
    content += `  id     String @id @default(uuid())\n`;
    content += `  userId String\n`;
    content += `  user   User   @relation(fields: [userId], references: [id])\n`;
    content += `}\n`;
    content += '```\n\n';

    return content;
  }

  private tutorialFrontendIntegration(context: TemplateContext): string {
    const { extendedWorkflow } = context;
    const framework = extendedWorkflow?.technology?.frontend?.framework;

    let content = `## Connecting Frontend to Backend\n\n`;

    if (framework === 'react') {
      content += this.tutorialReactIntegration(context);
    } else {
      content += this.tutorialGenericFrontendIntegration(context);
    }

    return content;
  }

  private tutorialReactIntegration(_context: TemplateContext): string {
    let content = `### Step 1: Create an API Client\n\n`;
    content += '**frontend/src/api/client.ts:**\n';
    content += '```typescript\n';
    content += `const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:3001';\n\n`;
    content += `export async function fetchItems() {\n`;
    content += `  const response = await fetch(\`\${API_URL}/api/items\`);\n`;
    content += `  return response.json();\n`;
    content += `}\n`;
    content += '```\n\n';

    content += `### Step 2: Use in a Component\n\n`;
    content += '```typescript\n';
    content += `import { useEffect, useState } from 'react';\n`;
    content += `import { fetchItems } from './api/client';\n\n`;
    content += `function ItemList() {\n`;
    content += `  const [items, setItems] = useState([]);\n\n`;
    content += `  useEffect(() => {\n`;
    content += `    fetchItems().then(setItems);\n`;
    content += `  }, []);\n\n`;
    content += `  return (\n`;
    content += `    <ul>\n`;
    content += `      {items.map(item => (\n`;
    content += `        <li key={item.id}>{item.name}</li>\n`;
    content += `      ))}\n`;
    content += `    </ul>\n`;
    content += `  );\n`;
    content += `}\n`;
    content += '```\n\n';

    return content;
  }

  private tutorialGenericFrontendIntegration(_context: TemplateContext): string {
    return `Follow your frontend framework's documentation for API integration.\n\n`;
  }

  private tutorialWriteTests(_context: TemplateContext): string {
    let content = `## Writing Tests\n\n`;
    content += `### Backend Tests\n\n`;
    content += '```typescript\n';
    content += `import request from 'supertest';\n`;
    content += `import app from '../src/app';\n\n`;
    content += `describe('GET /api/items', () => {\n`;
    content += `  it('should return all items', async () => {\n`;
    content += `    const response = await request(app)\n`;
    content += `      .get('/api/items')\n`;
    content += `      .expect(200);\n\n`;
    content += `    expect(Array.isArray(response.body)).toBe(true);\n`;
    content += `  });\n`;
    content += `});\n`;
    content += '```\n\n';

    return content;
  }

  private tutorialDeployment(_context: TemplateContext): string {
    let content = `## Deploying Your Application\n\n`;
    content += `### Using Docker\n\n`;
    content += '```bash\n';
    content += `docker compose up -d\n`;
    content += '```\n\n';

    return content;
  }
}
