import { NextRequest, NextResponse } from 'next/server';
import { getDatabase, db_helpers } from '@/lib/db';
import { readFileSync, existsSync, readdirSync, writeFileSync, mkdirSync } from 'fs';
import { join, dirname, isAbsolute, resolve } from 'path';
import { config } from '@/lib/config';
import { resolveWithin } from '@/lib/paths';
import { getAgentWorkspaceCandidates, readAgentWorkspaceFile } from '@/lib/agent-workspace';
import { requireRole } from '@/lib/auth';
import { logger } from '@/lib/logger';

function resolveAgentWorkspacePath(workspace: string): string {
  if (isAbsolute(workspace)) return resolve(workspace)
  if (!config.openclawStateDir) throw new Error('OPENCLAW_STATE_DIR not configured')
  return resolveWithin(config.openclawStateDir, workspace)
}

/**
 * GET /api/agents/[id]/soul - Get agent's SOUL content
 */
export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  const auth = requireRole(request, 'viewer')
  if ('error' in auth) return NextResponse.json({ error: auth.error }, { status: auth.status })

  try {
    const db = getDatabase();
    const resolvedParams = await params;
    const agentId = resolvedParams.id;
    const workspaceId = auth.user.workspace_id ?? 1;
    
    // Get agent by ID or name
    let agent: any;
    if (isNaN(Number(agentId))) {
      agent = db.prepare('SELECT * FROM agents WHERE name = ? AND workspace_id = ?').get(agentId, workspaceId);
    } else {
      agent = db.prepare('SELECT * FROM agents WHERE id = ? AND workspace_id = ?').get(Number(agentId), workspaceId);
    }
    
    if (!agent) {
      return NextResponse.json({ error: 'Agent not found' }, { status: 404 });
    }
    
    // Try reading soul.md from workspace first, fall back to DB
    let soulContent = ''
    let source: 'workspace' | 'database' | 'none' = 'none'

    try {
      const agentConfig = agent.config ? JSON.parse(agent.config) : {}
      const candidates = getAgentWorkspaceCandidates(agentConfig, agent.name)
      const match = readAgentWorkspaceFile(candidates, ['soul.md', 'SOUL.md'])
      if (match.exists) {
        soulContent = match.content
        source = 'workspace'
      }
    } catch (err) {
      logger.warn({ err, agent: agent.name }, 'Failed to read soul.md from workspace')
    }

    // Fall back to database value
    if (!soulContent && agent.soul_content) {
      soulContent = agent.soul_content
      source = 'database'
    }

    const templatesPath = config.soulTemplatesDir;
    let availableTemplates: string[] = [];

    try {
      if (templatesPath && existsSync(templatesPath)) {
        const files = readdirSync(templatesPath);
        availableTemplates = files
          .filter(file => file.endsWith('.md'))
          .map(file => file.replace('.md', ''));
      }
    } catch (error) {
      logger.warn({ err: error }, 'Could not read soul templates directory');
    }

    return NextResponse.json({
      agent: {
        id: agent.id,
        name: agent.name,
        role: agent.role
      },
      soul_content: soulContent,
      source,
      available_templates: availableTemplates,
      updated_at: agent.updated_at
    });
  } catch (error) {
    logger.error({ err: error }, 'GET /api/agents/[id]/soul error');
    return NextResponse.json({ error: 'Failed to fetch SOUL content' }, { status: 500 });
  }
}

/**
 * PUT /api/agents/[id]/soul - Update agent's SOUL content
 */
export async function PUT(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  const auth = requireRole(request, 'operator');
  if ('error' in auth) return NextResponse.json({ error: auth.error }, { status: auth.status });

  try {
    const db = getDatabase();
    const resolvedParams = await params;
    const agentId = resolvedParams.id;
    const workspaceId = auth.user.workspace_id ?? 1;
    const body = await request.json();
    const { soul_content, template_name } = body;
    
    // Get agent by ID or name
    let agent: any;
    if (isNaN(Number(agentId))) {
      agent = db.prepare('SELECT * FROM agents WHERE name = ? AND workspace_id = ?').get(agentId, workspaceId);
    } else {
      agent = db.prepare('SELECT * FROM agents WHERE id = ? AND workspace_id = ?').get(Number(agentId), workspaceId);
    }
    
    if (!agent) {
      return NextResponse.json({ error: 'Agent not found' }, { status: 404 });
    }
    
    let newSoulContent = soul_content;
    
    // If template_name is provided, load from template
    if (template_name) {
      if (!config.soulTemplatesDir) {
        return NextResponse.json({ error: 'Templates directory not configured' }, { status: 500 });
      }
      let templatePath: string;
      try {
        templatePath = resolveWithin(config.soulTemplatesDir, `${template_name}.md`);
      } catch (pathError) {
        return NextResponse.json({ error: 'Invalid template name' }, { status: 400 });
      }
      
      try {
        if (existsSync(templatePath)) {
          const templateContent = readFileSync(templatePath, 'utf8');
          // Replace placeholders with agent info
          newSoulContent = templateContent
            .replace(/{{AGENT_NAME}}/g, agent.name)
            .replace(/{{AGENT_ROLE}}/g, agent.role)
            .replace(/{{TIMESTAMP}}/g, new Date().toISOString());
        } else {
          return NextResponse.json({ error: 'Template not found' }, { status: 404 });
        }
      } catch (error) {
        logger.error({ err: error }, 'Error loading soul template');
        return NextResponse.json({ error: 'Failed to load template' }, { status: 500 });
      }
    }
    
    const now = Math.floor(Date.now() / 1000);

    // Write to workspace file if available
    let savedToWorkspace = false
    try {
      const agentConfig = agent.config ? JSON.parse(agent.config) : {}
      const candidates = getAgentWorkspaceCandidates(agentConfig, agent.name)
      const safeWorkspace = candidates[0]
      if (safeWorkspace) {
        const safeSoulPath = resolveWithin(safeWorkspace, 'soul.md')
        mkdirSync(dirname(safeSoulPath), { recursive: true })
        writeFileSync(safeSoulPath, newSoulContent || '', 'utf-8')
        savedToWorkspace = true
      }
    } catch (err) {
      logger.warn({ err, agent: agent.name }, 'Failed to write soul.md to workspace, saving to DB only')
    }

    // Update SOUL content in DB
    const updateStmt = db.prepare(`
      UPDATE agents
      SET soul_content = ?, updated_at = ?
      WHERE ${isNaN(Number(agentId)) ? 'name' : 'id'} = ? AND workspace_id = ?
    `);

    updateStmt.run(newSoulContent, now, agentId, workspaceId);

    // Log activity
    db_helpers.logActivity(
      'agent_soul_updated',
      'agent',
      agent.id,
      auth.user.username,
      `SOUL content updated for agent ${agent.name}${template_name ? ` using template: ${template_name}` : ''}${savedToWorkspace ? ' (synced to workspace)' : ''}`,
      {
        template_used: template_name || null,
        content_length: newSoulContent ? newSoulContent.length : 0,
        previous_content_length: agent.soul_content ? agent.soul_content.length : 0,
        saved_to_workspace: savedToWorkspace
      },
      workspaceId
    );

    return NextResponse.json({
      success: true,
      message: `SOUL content updated for ${agent.name}`,
      soul_content: newSoulContent,
      saved_to_workspace: savedToWorkspace,
      updated_at: now
    });
  } catch (error) {
    logger.error({ err: error }, 'PUT /api/agents/[id]/soul error');
    return NextResponse.json({ error: 'Failed to update SOUL content' }, { status: 500 });
  }
}

/**
 * GET /api/agents/[id]/soul/templates - Get available SOUL templates
 * Also handles loading specific template content
 */
export async function PATCH(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> }
) {
  try {
    const { searchParams } = new URL(request.url);
    const templateName = searchParams.get('template');
    
    const templatesPath = config.soulTemplatesDir;
    
    if (!templatesPath || !existsSync(templatesPath)) {
      return NextResponse.json({
        templates: [],
        message: 'Templates directory not found'
      });
    }
    
    if (templateName) {
      // Get specific template content
      let templatePath: string;
      try {
        templatePath = resolveWithin(templatesPath, `${templateName}.md`);
      } catch (pathError) {
        return NextResponse.json({ error: 'Invalid template name' }, { status: 400 });
      }
      
      if (!existsSync(templatePath)) {
        return NextResponse.json({ error: 'Template not found' }, { status: 404 });
      }
      
      const templateContent = readFileSync(templatePath, 'utf8');
      
      return NextResponse.json({
        template_name: templateName,
        content: templateContent
      });
    }
    
    // List all available templates
    const files = readdirSync(templatesPath);
    const templates = files
      .filter(file => file.endsWith('.md'))
      .map(file => {
        const name = file.replace('.md', '');
        const templatePath = join(templatesPath, file);
        const content = readFileSync(templatePath, 'utf8');
        
        // Extract first line as description
        const firstLine = content.split('\n')[0];
        const description = firstLine.startsWith('#') 
          ? firstLine.replace(/^#+\s*/, '') 
          : `${name} template`;
        
        return {
          name,
          description,
          size: content.length
        };
      });
    
    return NextResponse.json({ templates });
  } catch (error) {
    logger.error({ err: error }, 'PATCH /api/agents/[id]/soul error');
    return NextResponse.json({ error: 'Failed to fetch templates' }, { status: 500 });
  }
}
