import { success, error, warning, info } from '../cli-core.js';
import type { CommandContext } from '../cli-core.js';
import chalk from 'chalk';
const { blue, yellow, green, magenta, cyan } = chalk;

interface SparcMode {
  slug: string;
  name: string;
  roleDefinition: string;
  customInstructions: string;
  groups: string[];
  source: string;
}

interface SparcConfig {
  customModes: SparcMode[];
}

let sparcConfig: SparcConfig | null = null;

async function loadSparcConfig(): Promise<SparcConfig> {
  if (sparcConfig) {
    return sparcConfig;
  }

  try {
    const configPath = '.roomodes';
    const { readFile } = await import('fs/promises');
    const content = await readFile(configPath, 'utf-8');
    sparcConfig = JSON.parse(content);
    return sparcConfig!;
  } catch (error) {
    throw new Error(
      `Failed to load SPARC configuration: ${error instanceof Error ? error.message : String(error)}`,
    );
  }
}

export async function sparcAction(ctx: CommandContext): Promise<void> {
  const subcommand = ctx.args[0];

  switch (subcommand) {
    case 'modes':
      await listSparcModes(ctx);
      break;
    case 'info':
      await showModeInfo(ctx);
      break;
    case 'run':
      await runSparcMode(ctx);
      break;
    case 'tdd':
      await runTddFlow(ctx);
      break;
    case 'workflow':
      await runSparcWorkflow(ctx);
      break;
    default:
      await showSparcHelp();
      break;
  }
}

async function listSparcModes(ctx: CommandContext): Promise<void> {
  try {
    const config = await loadSparcConfig();
    const verbose = ctx.flags.verbose as boolean;

    success('Available SPARC Modes:');
    console.log();

    for (const mode of config.customModes) {
      console.log(`${cyan('•')} ${green(mode.name)} ${blue(`(${mode.slug})`)}`);
      if (verbose) {
        console.log(`  ${mode.roleDefinition}`);
        console.log(`  Tools: ${mode.groups.join(', ')}`);
        console.log();
      }
    }

    if (!verbose) {
      console.log();
      info('Use --verbose for detailed descriptions');
    }
  } catch (err) {
    error(`Failed to list SPARC modes: ${(err as Error).message}`);
  }
}

async function showModeInfo(ctx: CommandContext): Promise<void> {
  const modeSlug = ctx.args[1];
  if (!modeSlug) {
    error('Usage: sparc info <mode-slug>');
    return;
  }

  try {
    const config = await loadSparcConfig();
    const mode = config.customModes.find((m) => m.slug === modeSlug);

    if (!mode) {
      error(`Mode not found: ${modeSlug}`);
      console.log('Available modes:');
      for (const m of config.customModes) {
        console.log(`  ${m.slug} - ${m.name}`);
      }
      return;
    }

    success(`SPARC Mode: ${mode.name}`);
    console.log();
    console.log(blue('Role Definition:'));
    console.log(mode.roleDefinition);
    console.log();
    console.log(blue('Custom Instructions:'));
    console.log(mode.customInstructions);
    console.log();
    console.log(blue('Tool Groups:'));
    console.log(mode.groups.join(', '));
    console.log();
    console.log(blue('Source:'));
    console.log(mode.source);
  } catch (err) {
    error(`Failed to show mode info: ${(err as Error).message}`);
  }
}

async function runSparcMode(ctx: CommandContext): Promise<void> {
  const modeSlug = ctx.args[1];
  const taskDescription = ctx.args.slice(2).join(' ');

  if (!modeSlug || !taskDescription) {
    error('Usage: sparc run <mode-slug> <task-description>');
    return;
  }

  try {
    const config = await loadSparcConfig();
    const mode = config.customModes.find((m) => m.slug === modeSlug);

    if (!mode) {
      error(`Mode not found: ${modeSlug}`);
      return;
    }

    // Build the enhanced task prompt using SPARC methodology
    const enhancedTask = buildSparcPrompt(mode, taskDescription, ctx.flags);
    const instanceId = `sparc-${modeSlug}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;

    // Build tools based on mode groups
    const tools = buildToolsFromGroups(mode.groups);

    if (ctx.flags.dryRun || ctx.flags['dry-run']) {
      warning('DRY RUN - SPARC Mode Configuration:');
      console.log(`Mode: ${mode.name} (${mode.slug})`);
      console.log(`Instance ID: ${instanceId}`);
      console.log(`Tools: ${tools}`);
      console.log(`Task: ${taskDescription}`);
      console.log();
      console.log('Enhanced prompt preview:');
      console.log(enhancedTask.substring(0, 300) + '...');
      return;
    }

    success(`Starting SPARC mode: ${mode.name}`);
    console.log(`📝 Instance ID: ${instanceId}`);
    console.log(`🎯 Mode: ${mode.slug}`);
    console.log(`🔧 Tools: ${tools}`);
    console.log(`📋 Task: ${taskDescription}`);
    console.log();

    // Execute Claude with SPARC configuration
    await executeClaudeWithSparc(enhancedTask, tools, instanceId, ctx.flags);
  } catch (err) {
    error(`Failed to run SPARC mode: ${(err as Error).message}`);
  }
}

async function runTddFlow(ctx: CommandContext): Promise<void> {
  const taskDescription = ctx.args.slice(1).join(' ');

  if (!taskDescription) {
    error('Usage: sparc tdd <task-description>');
    return;
  }

  try {
    const config = await loadSparcConfig();

    // Build TDD workflow using SPARC methodology
    const workflow = [
      {
        mode: 'spec-pseudocode',
        phase: 'Specification',
        description: `Create detailed spec and pseudocode for: ${taskDescription}`,
      },
      { mode: 'tdd', phase: 'Red', description: `Write failing tests for: ${taskDescription}` },
      {
        mode: 'code',
        phase: 'Green',
        description: `Implement minimal code to pass tests for: ${taskDescription}`,
      },
      {
        mode: 'refinement-optimization-mode',
        phase: 'Refactor',
        description: `Refactor and optimize implementation for: ${taskDescription}`,
      },
      {
        mode: 'integration',
        phase: 'Integration',
        description: `Integrate and verify complete solution for: ${taskDescription}`,
      },
    ];

    if (ctx.flags.dryRun || ctx.flags['dry-run']) {
      warning('DRY RUN - TDD Workflow:');
      for (const step of workflow) {
        console.log(`${cyan(step.phase)}: ${step.mode} - ${step.description}`);
      }
      return;
    }

    success('Starting SPARC TDD Workflow');
    console.log('Following Test-Driven Development with SPARC methodology');
    console.log();

    for (let i = 0; i < workflow.length; i++) {
      const step = workflow[i];
      const mode = config.customModes.find((m) => m.slug === step.mode);

      if (!mode) {
        warning(`Mode not found: ${step.mode}, skipping step`);
        continue;
      }

      info(`Phase ${i + 1}/5: ${step.phase} (${mode.name})`);
      console.log(`📋 ${step.description}`);
      console.log();

      const enhancedTask = buildSparcPrompt(mode, step.description, {
        ...ctx.flags,
        tddPhase: step.phase,
        workflowStep: i + 1,
        totalSteps: workflow.length,
      });

      const tools = buildToolsFromGroups(mode.groups);
      const instanceId = `sparc-tdd-${step.phase.toLowerCase()}-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;

      await executeClaudeWithSparc(enhancedTask, tools, instanceId, ctx.flags);

      // Store phase completion in memory for next step
      if (ctx.flags.sequential !== false) {
        console.log('Phase completed. Press Enter to continue to next phase, or Ctrl+C to stop...');
        await new Promise<void>(async (resolve) => {
          const readline = await import('readline');
          const rl = readline.createInterface({
            input: process.stdin,
            output: process.stdout,
          });
          rl.question('', () => {
            rl.close();
            resolve();
          });
        });
      }
    }

    success('SPARC TDD Workflow completed!');
  } catch (err) {
    error(`Failed to run TDD flow: ${(err as Error).message}`);
  }
}

async function runSparcWorkflow(ctx: CommandContext): Promise<void> {
  const workflowFile = ctx.args[1];

  if (!workflowFile) {
    error('Usage: sparc workflow <workflow-file.json>');
    return;
  }

  try {
    const { readFile } = await import('fs/promises');
    const workflowContent = await readFile(workflowFile, 'utf-8');
    const workflow = JSON.parse(workflowContent);

    if (!workflow.steps || !Array.isArray(workflow.steps)) {
      error("Invalid workflow file: missing 'steps' array");
      return;
    }

    const config = await loadSparcConfig();

    success(`Loading SPARC workflow: ${workflow.name || 'Unnamed'}`);
    console.log(`📋 Steps: ${workflow.steps.length}`);
    console.log(`📝 Description: ${workflow.description || 'No description'}`);
    console.log();

    if (ctx.flags.dryRun || ctx.flags['dry-run']) {
      warning('DRY RUN - Workflow Steps:');
      for (let i = 0; i < workflow.steps.length; i++) {
        const step = workflow.steps[i];
        console.log(`${i + 1}. ${cyan(step.mode)} - ${step.description || step.task}`);
      }
      return;
    }

    for (let i = 0; i < workflow.steps.length; i++) {
      const step = workflow.steps[i];
      const mode = config.customModes.find((m) => m.slug === step.mode);

      if (!mode) {
        warning(`Mode not found: ${step.mode}, skipping step ${i + 1}`);
        continue;
      }

      info(`Step ${i + 1}/${workflow.steps.length}: ${mode.name}`);
      console.log(`📋 ${step.description || step.task}`);
      console.log();

      const enhancedTask = buildSparcPrompt(mode, step.description || step.task, {
        ...ctx.flags,
        workflowStep: i + 1,
        totalSteps: workflow.steps.length,
        workflowName: workflow.name,
      });

      const tools = buildToolsFromGroups(mode.groups);
      const instanceId = `sparc-workflow-${i + 1}-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`;

      await executeClaudeWithSparc(enhancedTask, tools, instanceId, ctx.flags);

      if (workflow.sequential !== false && i < workflow.steps.length - 1) {
        console.log('Step completed. Press Enter to continue, or Ctrl+C to stop...');
        await new Promise<void>((resolve) => {
          const readline = require('readline');
          const rl = readline.createInterface({
            input: process.stdin,
            output: process.stdout,
          });
          rl.question('', () => {
            rl.close();
            resolve();
          });
        });
      }
    }

    success('SPARC workflow completed!');
  } catch (err) {
    error(`Failed to run workflow: ${(err as Error).message}`);
  }
}

function buildSparcPrompt(mode: SparcMode, taskDescription: string, flags: any): string {
  const memoryNamespace = flags.namespace || mode.slug || 'default';

  return `# SPARC Development Mode: ${mode.name}

## Your Role
${mode.roleDefinition}

## Your Task
${taskDescription}

## Mode-Specific Instructions
${mode.customInstructions}

## SPARC Development Environment

You are working within the SPARC (Specification, Pseudocode, Architecture, Refinement, Completion) methodology using claude-flow orchestration features.

### Available Development Tools
- **Memory Persistence**: Use \`npx claude-flow memory store <key> "<value>"\` to save progress and findings
- **Memory Retrieval**: Use \`npx claude-flow memory query <search>\` to access previous work
- **Namespace**: Your work is stored in the "${memoryNamespace}" namespace

### SPARC Methodology Integration
${
  flags.tddPhase
    ? `
**Current TDD Phase**: ${flags.tddPhase}
- Follow the Red-Green-Refactor cycle
- Store test results and refactoring notes in memory
`
    : ''
}

${
  flags.workflowStep
    ? `
**Workflow Progress**: Step ${flags.workflowStep} of ${flags.totalSteps}
- Review previous steps: \`npx claude-flow memory query previous_steps\`
- Store this step's output: \`npx claude-flow memory store step_${flags.workflowStep}_output "<results>"\`
`
    : ''
}

### Best Practices
1. **Modular Development**: Keep all files under 500 lines
2. **Environment Safety**: Never hardcode secrets or environment values
3. **Memory Usage**: Store key findings and decisions in memory for future reference
4. **Tool Integration**: Use \`new_task\` for subtasks and \`attempt_completion\` when finished

### Memory Commands Examples
\`\`\`bash
# Store your progress
npx claude-flow memory store ${memoryNamespace}_progress "Current status and findings"

# Check for previous work
npx claude-flow memory query ${memoryNamespace}

# Store phase-specific results
npx claude-flow memory store ${memoryNamespace}_${flags.tddPhase || 'results'} "Phase output and decisions"
\`\`\`

### Integration with Other SPARC Modes
When working with other SPARC modes, use memory to:
- Share findings with spec-pseudocode mode
- Pass requirements to architect mode  
- Coordinate with code and tdd modes
- Communicate results to integration mode

Now proceed with your task following the SPARC methodology and your specific role instructions.`;
}

function buildToolsFromGroups(groups: string[]): string {
  const toolMappings: Record<string, string[]> = {
    read: ['View', 'LS', 'GlobTool', 'GrepTool'],
    edit: ['Edit', 'Replace', 'MultiEdit', 'Write'],
    browser: ['WebFetch'],
    mcp: ['mcp_tools'],
    command: ['Bash', 'Terminal'],
  };

  const tools = new Set<string>();

  // Always include basic tools
  tools.add('View');
  tools.add('Edit');
  tools.add('Bash');

  for (const group of groups) {
    if (Array.isArray(group)) {
      // Handle nested group definitions
      const groupName = group[0];
      if (toolMappings[groupName]) {
        toolMappings[groupName].forEach((tool) => tools.add(tool));
      }
    } else if (toolMappings[group]) {
      toolMappings[group].forEach((tool) => tools.add(tool));
    }
  }

  return Array.from(tools).join(',');
}

async function executeClaudeWithSparc(
  enhancedTask: string,
  tools: string,
  instanceId: string,
  flags: any,
): Promise<void> {
  const claudeArgs = [enhancedTask];
  claudeArgs.push('--allowedTools', tools);

  if (flags.noPermissions || flags['no-permissions']) {
    claudeArgs.push('--dangerously-skip-permissions');
  }

  if (flags.config) {
    claudeArgs.push('--mcp-config', flags.config);
  }

  if (flags.verbose) {
    claudeArgs.push('--verbose');
  }

  try {
    const { spawn } = await import('child_process');
    const child = spawn('claude', claudeArgs, {
      env: {
        ...process.env,
        CLAUDE_INSTANCE_ID: instanceId,
        CLAUDE_SPARC_MODE: 'true',
        CLAUDE_FLOW_MEMORY_ENABLED: 'true',
        CLAUDE_FLOW_MEMORY_NAMESPACE: flags.namespace || 'sparc',
      },
      stdio: 'inherit',
    });

    const status = await new Promise<{ success: boolean; code: number | null }>((resolve) => {
      child.on('close', (code) => {
        resolve({ success: code === 0, code });
      });
    });

    if ((status as any).success) {
      success(`SPARC instance ${instanceId} completed successfully`);
    } else {
      error(`SPARC instance ${instanceId} exited with code ${(status as any).code}`);
    }
  } catch (err) {
    error(`Failed to execute Claude: ${(err as Error).message}`);
  }
}

async function showSparcHelp(): Promise<void> {
  console.log(
    `${cyan('SPARC')} - ${green('Specification, Pseudocode, Architecture, Refinement, Completion')}`,
  );
  console.log();
  console.log('SPARC development methodology with TDD and multi-agent coordination.');
  console.log();
  console.log(blue('Commands:'));
  console.log('  modes                    List all available SPARC modes');
  console.log('  info <mode>              Show detailed information about a mode');
  console.log('  run <mode> <task>        Execute a task using a specific SPARC mode');
  console.log('  tdd <task>               Run full TDD workflow using SPARC methodology');
  console.log('  workflow <file>          Execute a custom SPARC workflow from JSON file');
  console.log();
  console.log(blue('Common Modes:'));
  console.log('  spec-pseudocode          Create specifications and pseudocode');
  console.log('  architect                Design system architecture');
  console.log('  code                     Implement code solutions');
  console.log('  tdd                      Test-driven development');
  console.log('  debug                    Debug and troubleshoot issues');
  console.log('  security-review          Security analysis and review');
  console.log('  docs-writer              Documentation creation');
  console.log('  integration              System integration and testing');
  console.log();
  console.log(blue('Options:'));
  console.log('  --namespace <ns>         Memory namespace for this session');
  console.log('  --no-permissions         Skip permission prompts');
  console.log('  --config <file>          MCP configuration file');
  console.log('  --verbose               Enable verbose output');
  console.log('  --dry-run               Preview what would be executed');
  console.log('  --sequential            Wait between workflow steps (default: true)');
  console.log();
  console.log(blue('Examples:'));
  console.log(
    `  ${yellow('claude-flow sparc modes')}                              # List all modes`,
  );
  console.log(
    `  ${yellow('claude-flow sparc run code')} "implement user auth"      # Run specific mode`,
  );
  console.log(
    `  ${yellow('claude-flow sparc tdd')} "payment processing system"    # Full TDD workflow`,
  );
  console.log(
    `  ${yellow('claude-flow sparc workflow')} project-workflow.json     # Custom workflow`,
  );
  console.log();
  console.log(blue('TDD Workflow:'));
  console.log('  1. Specification - Define requirements and create pseudocode');
  console.log('  2. Red Phase - Write failing tests');
  console.log('  3. Green Phase - Implement minimal code to pass tests');
  console.log('  4. Refactor Phase - Optimize and clean up code');
  console.log('  5. Integration - Verify complete solution');
  console.log();
  console.log('For more information: https://github.com/ruvnet/claude-code-flow/docs/sparc.md');
}
