/**
 * ${BRAND.companyName} Self-Evolution API
 * 
 * This endpoint enables autonomous self-modification:
 * - Store learned preferences and patterns
 * - Create/modify automation rules
 * - Add new capabilities
 * - Log all evolutions for audit/rollback
 * - Query current state (introspection)
 * 
 * The Ghost can use this freely to improve its functionality.
 */

import { NextRequest, NextResponse } from 'next/server';
import { prisma } from '@/lib/db';
import { BRAND } from '@/lib/white-label/constants';

export const dynamic = 'force-dynamic';

// Evolution types
type EvolutionType = 
  | 'memory_add' | 'memory_update' | 'memory_delete'
  | 'rule_add' | 'rule_modify' | 'rule_delete'
  | 'capability_add' | 'capability_modify'
  | 'insight' | 'self_reflect';

interface MemoryInput {
  category: string;
  key: string;
  value: unknown;
  confidence?: number;
  source?: string;
  expiresAt?: string;
}

interface RuleInput {
  name: string;
  trigger: string;
  triggerType: 'regex' | 'keyword' | 'schedule' | 'event' | 'condition';
  action: unknown;
  priority?: number;
  metadata?: unknown;
}

interface CapabilityInput {
  name: string;
  type: 'command' | 'handler' | 'integration' | 'workflow';
  code?: string;
  config?: unknown;
  dependencies?: string[];
}

// Log an evolution event
async function logEvolution(
  type: EvolutionType,
  description: string,
  before: unknown,
  after: unknown,
  reason?: string,
  confidence: number = 1.0
) {
  return prisma.ghostEvolution.create({
    data: {
      type,
      description,
      before: before as any,
      after: after as any,
      reason,
      confidence,
      isReversible: true,
    },
  });
}

// GET - Introspection: Query current state
export async function GET(request: NextRequest) {
  const { searchParams } = new URL(request.url);
  const query = searchParams.get('query') || 'overview';
  const category = searchParams.get('category');
  const limit = parseInt(searchParams.get('limit') || '50');

  try {
    switch (query) {
      case 'overview': {
        const [memories, rules, capabilities, recentEvolutions] = await Promise.all([
          prisma.ghostMemory.count(),
          prisma.ghostRule.count({ where: { isActive: true } }),
          prisma.ghostCapability.count({ where: { isActive: true } }),
          prisma.ghostEvolution.findMany({
            take: 10,
            orderBy: { createdAt: 'desc' },
          }),
        ]);
        
        return NextResponse.json({
          status: 'active',
          stats: {
            totalMemories: memories,
            activeRules: rules,
            activeCapabilities: capabilities,
          },
          recentEvolutions: recentEvolutions.map((e: any) => ({
            type: e.type,
            description: e.description,
            createdAt: e.createdAt,
          })),
        });
      }

      case 'memories': {
        const memories = await prisma.ghostMemory.findMany({
          where: category ? { category } : undefined,
          take: limit,
          orderBy: { usageCount: 'desc' },
        });
        return NextResponse.json({ memories });
      }

      case 'rules': {
        const rules = await prisma.ghostRule.findMany({
          where: { isActive: true },
          take: limit,
          orderBy: { priority: 'desc' },
        });
        return NextResponse.json({ rules });
      }

      case 'capabilities': {
        const capabilities = await prisma.ghostCapability.findMany({
          where: { isActive: true },
          take: limit,
        });
        return NextResponse.json({ capabilities });
      }

      case 'evolutions': {
        const evolutions = await prisma.ghostEvolution.findMany({
          take: limit,
          orderBy: { createdAt: 'desc' },
        });
        return NextResponse.json({ evolutions });
      }

      case 'recall': {
        // Recall specific memories
        const key = searchParams.get('key');
        if (!key || !category) {
          return NextResponse.json({ error: 'key and category required' }, { status: 400 });
        }
        
        const memory = await prisma.ghostMemory.findUnique({
          where: { category_key: { category, key } },
        });
        
        if (memory) {
          // Update usage count and lastUsed
          await prisma.ghostMemory.update({
            where: { id: memory.id },
            data: { usageCount: memory.usageCount + 1, lastUsed: new Date() },
          });
        }
        
        return NextResponse.json({ memory });
      }

      default:
        return NextResponse.json({ error: 'Unknown query type' }, { status: 400 });
    }
  } catch (error) {
    console.error('Evolution GET error:', error);
    return NextResponse.json({ error: 'Failed to query state' }, { status: 500 });
  }
}

// POST - Evolution: Modify self
export async function POST(request: NextRequest) {
  try {
    const body = await request.json();
    const { action, data, reason } = body;

    switch (action) {
      // ============================================
      // MEMORY OPERATIONS
      // ============================================
      case 'remember': {
        const { category, key, value, confidence = 1.0, source, expiresAt } = data as MemoryInput;
        
        if (!category || !key || value === undefined) {
          return NextResponse.json({ error: 'category, key, and value required' }, { status: 400 });
        }

        // Check if memory exists
        const existing = await prisma.ghostMemory.findUnique({
          where: { category_key: { category, key } },
        });

        let memory;
        if (existing) {
          // Update existing memory
          memory = await prisma.ghostMemory.update({
            where: { id: existing.id },
            data: {
              value: value as any,
              confidence,
              source,
              expiresAt: expiresAt ? new Date(expiresAt) : undefined,
            },
          });
          
          await logEvolution(
            'memory_update',
            `Updated memory: ${category}/${key}`,
            existing.value,
            value,
            reason,
            confidence
          );
        } else {
          // Create new memory
          memory = await prisma.ghostMemory.create({
            data: {
              category,
              key,
              value: value as any,
              confidence,
              source,
              expiresAt: expiresAt ? new Date(expiresAt) : undefined,
            },
          });
          
          await logEvolution(
            'memory_add',
            `Learned: ${category}/${key}`,
            null,
            value,
            reason,
            confidence
          );
        }

        return NextResponse.json({ success: true, memory });
      }

      case 'forget': {
        const { category, key } = data;
        
        const existing = await prisma.ghostMemory.findUnique({
          where: { category_key: { category, key } },
        });

        if (existing) {
          await prisma.ghostMemory.delete({ where: { id: existing.id } });
          
          await logEvolution(
            'memory_delete',
            `Forgot: ${category}/${key}`,
            existing.value,
            null,
            reason
          );
        }

        return NextResponse.json({ success: true, forgotten: !!existing });
      }

      // ============================================
      // RULE OPERATIONS
      // ============================================
      case 'add_rule': {
        const { name, trigger, triggerType, action: ruleAction, priority = 0, metadata = {} } = data as RuleInput;

        if (!name || !trigger || !triggerType || !ruleAction) {
          return NextResponse.json({ error: 'name, trigger, triggerType, and action required' }, { status: 400 });
        }

        const rule = await prisma.ghostRule.create({
          data: {
            name,
            trigger,
            triggerType,
            action: ruleAction as any,
            priority,
            metadata: metadata as any,
          },
        });

        await logEvolution(
          'rule_add',
          `Added rule: ${name}`,
          null,
          { name, trigger, triggerType, action: ruleAction },
          reason
        );

        return NextResponse.json({ success: true, rule });
      }

      case 'modify_rule': {
        const { name, updates } = data;

        const existing = await prisma.ghostRule.findUnique({ where: { name } });
        if (!existing) {
          return NextResponse.json({ error: 'Rule not found' }, { status: 404 });
        }

        const rule = await prisma.ghostRule.update({
          where: { name },
          data: updates,
        });

        await logEvolution(
          'rule_modify',
          `Modified rule: ${name}`,
          existing,
          rule,
          reason
        );

        return NextResponse.json({ success: true, rule });
      }

      case 'disable_rule': {
        const { name } = data;

        const rule = await prisma.ghostRule.update({
          where: { name },
          data: { isActive: false },
        });

        await logEvolution(
          'rule_modify',
          `Disabled rule: ${name}`,
          { isActive: true },
          { isActive: false },
          reason
        );

        return NextResponse.json({ success: true, rule });
      }

      // ============================================
      // CAPABILITY OPERATIONS
      // ============================================
      case 'add_capability': {
        const { name, type, code, config = {}, dependencies = [] } = data as CapabilityInput;

        if (!name || !type) {
          return NextResponse.json({ error: 'name and type required' }, { status: 400 });
        }

        const capability = await prisma.ghostCapability.create({
          data: {
            name,
            type,
            code,
            config: config as any,
            dependencies: dependencies as any,
          },
        });

        await logEvolution(
          'capability_add',
          `Added capability: ${name} (${type})`,
          null,
          { name, type, config },
          reason
        );

        return NextResponse.json({ success: true, capability });
      }

      case 'modify_capability': {
        const { name, updates } = data;

        const existing = await prisma.ghostCapability.findUnique({ where: { name } });
        if (!existing) {
          return NextResponse.json({ error: 'Capability not found' }, { status: 404 });
        }

        const capability = await prisma.ghostCapability.update({
          where: { name },
          data: { ...updates, version: existing.version + 1 },
        });

        await logEvolution(
          'capability_modify',
          `Modified capability: ${name}`,
          existing,
          capability,
          reason
        );

        return NextResponse.json({ success: true, capability });
      }

      // ============================================
      // SELF-REFLECTION
      // ============================================
      case 'reflect': {
        // Log an insight or self-reflection
        const { insight, confidence = 1.0 } = data;

        const evolution = await logEvolution(
          'self_reflect',
          insight,
          null,
          { insight, timestamp: new Date().toISOString() },
          reason,
          confidence
        );

        return NextResponse.json({ success: true, evolution });
      }

      case 'insight': {
        // Record a learned insight
        const { topic, insight, confidence = 0.8 } = data;

        // Store as both an evolution log and a memory
        const memory = await prisma.ghostMemory.upsert({
          where: { category_key: { category: 'insight', key: topic } },
          create: {
            category: 'insight',
            key: topic,
            value: { insight, timestamp: new Date().toISOString() } as any,
            confidence,
            source: 'self-reflection',
          },
          update: {
            value: { insight, timestamp: new Date().toISOString() } as any,
            confidence,
          },
        });

        await logEvolution(
          'insight',
          `Insight about ${topic}: ${insight.substring(0, 100)}...`,
          null,
          { topic, insight },
          reason,
          confidence
        );

        return NextResponse.json({ success: true, memory });
      }

      // ============================================
      // BATCH OPERATIONS
      // ============================================
      case 'batch': {
        const { operations } = data;
        const results = [];

        for (const op of operations) {
          // Recursively process each operation
          const result = await fetch(request.url, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(op),
          }).then(r => r.json());
          results.push(result);
        }

        return NextResponse.json({ success: true, results });
      }

      default:
        return NextResponse.json({ error: `Unknown action: ${action}` }, { status: 400 });
    }
  } catch (error) {
    console.error('Evolution POST error:', error);
    return NextResponse.json({ 
      error: 'Evolution failed', 
      details: error instanceof Error ? error.message : 'Unknown error' 
    }, { status: 500 });
  }
}

// DELETE - Rollback an evolution
export async function DELETE(request: NextRequest) {
  try {
    const { searchParams } = new URL(request.url);
    const evolutionId = searchParams.get('id');

    if (!evolutionId) {
      return NextResponse.json({ error: 'Evolution ID required' }, { status: 400 });
    }

    const evolution = await prisma.ghostEvolution.findUnique({
      where: { id: evolutionId },
    });

    if (!evolution) {
      return NextResponse.json({ error: 'Evolution not found' }, { status: 404 });
    }

    if (!evolution.isReversible) {
      return NextResponse.json({ error: 'This evolution cannot be reversed' }, { status: 400 });
    }

    if (evolution.reversedAt) {
      return NextResponse.json({ error: 'Already reversed' }, { status: 400 });
    }

    // Mark as reversed
    await prisma.ghostEvolution.update({
      where: { id: evolutionId },
      data: { reversedAt: new Date() },
    });

    // Log the rollback as its own evolution
    await logEvolution(
      'self_reflect',
      `Rolled back: ${evolution.description}`,
      evolution.after,
      evolution.before,
      'Rollback requested'
    );

    return NextResponse.json({ success: true, message: 'Evolution rolled back' });
  } catch (error) {
    console.error('Evolution DELETE error:', error);
    return NextResponse.json({ error: 'Rollback failed' }, { status: 500 });
  }
}
