/**
 * MORPH-SPEC State Command
 * CLI wrapper for state management operations
 */

import ora from 'ora';
import chalk from 'chalk';
import { logger } from '../utils/logger.js';
import * as StateManager from '../lib/state-manager.js';

// ============================================================================
// Command Functions
// ============================================================================

/**
 * Main state command router
 */
export async function stateCommand(action, args, options) {
  switch (action) {
    case 'init':
      await initCommand(options);
      break;

    case 'get':
      await getCommand(args[0], options);
      break;

    case 'set':
      await setCommand(args[0], args[1], args[2], options);
      break;

    case 'checkpoint':
      await checkpointCommand(args[0], args.slice(1).join(' '), options);
      break;

    case 'list':
      await listCommand(options);
      break;

    case 'add-agent':
      await addAgentCommand(args[0], args[1], options);
      break;

    case 'remove-agent':
      await removeAgentCommand(args[0], args[1], options);
      break;

    case 'mark-output':
      await markOutputCommand(args[0], args[1], options);
      break;

    default:
      logger.error(`Unknown action: ${action}`);
      logger.blank();
      logger.info('Available actions:');
      logger.dim('  init, get, set, checkpoint, list, add-agent, remove-agent, mark-output');
      logger.blank();
      logger.dim('Run "morph-spec state --help" for more information');
      process.exit(1);
  }
}

/**
 * Initialize state file
 */
async function initCommand(options) {
  logger.header('Initialize State');
  logger.blank();

  try {
    if (StateManager.stateExists() && !options.force) {
      logger.warn('State file already exists.');
      logger.dim('  Use --force to overwrite');
      logger.blank();
      return;
    }

    const spinner = ora('Initializing state.json...').start();

    StateManager.initState({
      force: options.force,
      projectName: options.project || '{PROJECT_NAME}',
      projectType: options.type || 'blazor-server'
    });

    spinner.succeed('State initialized!');
    logger.blank();
    logger.dim(`Location: ${StateManager.getStatePath()}`);
    logger.blank();

  } catch (error) {
    logger.error(error.message);
    process.exit(1);
  }
}

/**
 * Get feature state
 */
async function getCommand(featureName, options) {
  if (!featureName) {
    logger.error('Feature name required');
    logger.dim('  Usage: morph-spec state get <feature>');
    process.exit(1);
  }

  try {
    const feature = StateManager.getFeature(featureName);

    if (!feature) {
      logger.error(`Feature '${featureName}' not found`);
      process.exit(1);
    }

    if (options.json) {
      console.log(JSON.stringify(feature, null, 2));
    } else {
      logger.header(`Feature: ${featureName}`);
      logger.blank();
      logger.info(`Status: ${chalk.cyan(feature.status)}`);
      logger.info(`Phase: ${chalk.cyan(feature.phase)}`);
      logger.info(`Tasks: ${chalk.cyan(`${feature.tasks.completed}/${feature.tasks.total}`)}`);
      logger.info(`Agents: ${chalk.cyan(feature.activeAgents.join(', ') || 'None')}`);
      logger.blank();
    }

  } catch (error) {
    logger.error(error.message);
    process.exit(1);
  }
}

/**
 * Set feature property
 */
async function setCommand(featureName, key, value, options) {
  if (!featureName || !key || value === undefined) {
    logger.error('Missing required arguments');
    logger.dim('  Usage: morph-spec state set <feature> <key> <value>');
    logger.blank();
    logger.dim('  Example: morph-spec state set my-feature phase implement');
    process.exit(1);
  }

  try {
    const spinner = ora('Updating state...').start();

    // Parse value automatically (JSON, number, boolean)
    let parsedValue = value;
    try {
      parsedValue = JSON.parse(value);
    } catch {
      // Keep as string if not valid JSON
    }

    StateManager.updateFeature(featureName, key, parsedValue);

    spinner.succeed(`Updated ${chalk.cyan(featureName)}.${chalk.cyan(key)}`);
    logger.blank();
    logger.dim(`Value: ${JSON.stringify(parsedValue)}`);
    logger.blank();

  } catch (error) {
    logger.error(error.message);
    process.exit(1);
  }
}

/**
 * Add checkpoint
 */
async function checkpointCommand(featureName, note, options) {
  if (!featureName || !note) {
    logger.error('Missing required arguments');
    logger.dim('  Usage: morph-spec state checkpoint <feature> "<note>"');
    logger.blank();
    logger.dim('  Example: morph-spec state checkpoint my-feature "Completed T001-T003"');
    process.exit(1);
  }

  try {
    const spinner = ora('Creating checkpoint...').start();

    const checkpoint = StateManager.addCheckpoint(featureName, note);

    spinner.succeed(`Checkpoint registered for ${chalk.cyan(featureName)}`);
    logger.blank();
    logger.dim(`  ${checkpoint.note}`);
    logger.dim(`  Phase: ${checkpoint.phase}`);
    logger.dim(`  Tasks completed: ${checkpoint.completedTasks}`);
    logger.blank();

  } catch (error) {
    logger.error(error.message);
    process.exit(1);
  }
}

/**
 * List all features
 */
async function listCommand(options) {
  logger.header('MORPH-SPEC Project Status');
  logger.blank();

  try {
    const summary = StateManager.getSummary();
    const features = StateManager.listFeatures();

    // Project info
    logger.info(`Project: ${chalk.cyan(summary.project.name)}`);
    logger.info(`Type: ${chalk.cyan(summary.project.type)}`);
    logger.blank();

    if (features.length === 0) {
      logger.warn('No features found');
      logger.blank();
      return;
    }

    // Features table
    logger.header('Features:');
    logger.blank();

    features.forEach(([name, feature]) => {
      const statusEmoji = {
        draft: '📝',
        in_review: '👀',
        approved: '✅',
        in_progress: '🚧',
        done: '✔️',
        archived: '📦'
      }[feature.status] || '❓';

      const progress = feature.tasks.total > 0
        ? `${feature.tasks.completed}/${feature.tasks.total}`
        : '0/0';

      logger.info(`${statusEmoji}  ${chalk.bold(name)}`);
      logger.dim(`   Phase: ${feature.phase.padEnd(16)} │ Tasks: ${progress}`);
      logger.dim(`   Agents: ${feature.activeAgents.slice(0, 5).join(', ') || 'None'}`);
      logger.blank();
    });

    // Summary
    logger.header('Summary:');
    logger.info(`Total Features: ${chalk.cyan(summary.metadata.totalFeatures)}`);
    logger.info(`Completed: ${chalk.cyan(summary.metadata.completedFeatures)}`);
    logger.info(`Estimated Cost: ${chalk.cyan(`$${summary.metadata.totalCostEstimated.toFixed(2)}/month`)}`);
    logger.blank();

  } catch (error) {
    logger.error(error.message);
    process.exit(1);
  }
}

/**
 * Add agent to feature
 */
async function addAgentCommand(featureName, agentId, options) {
  if (!featureName || !agentId) {
    logger.error('Missing required arguments');
    logger.dim('  Usage: morph-spec state add-agent <feature> <agent-id>');
    process.exit(1);
  }

  try {
    const added = StateManager.addAgent(featureName, agentId);

    if (added) {
      logger.success(`Agent '${chalk.cyan(agentId)}' added to ${chalk.cyan(featureName)}`);
    } else {
      logger.warn(`Agent '${agentId}' already active`);
    }
    logger.blank();

  } catch (error) {
    logger.error(error.message);
    process.exit(1);
  }
}

/**
 * Remove agent from feature
 */
async function removeAgentCommand(featureName, agentId, options) {
  if (!featureName || !agentId) {
    logger.error('Missing required arguments');
    logger.dim('  Usage: morph-spec state remove-agent <feature> <agent-id>');
    process.exit(1);
  }

  try {
    const removed = StateManager.removeAgent(featureName, agentId);

    if (removed) {
      logger.success(`Agent '${chalk.cyan(agentId)}' removed from ${chalk.cyan(featureName)}`);
    } else {
      logger.warn(`Agent '${agentId}' not found`);
    }
    logger.blank();

  } catch (error) {
    logger.error(error.message);
    process.exit(1);
  }
}

/**
 * Mark output as created
 */
async function markOutputCommand(featureName, outputType, options) {
  if (!featureName || !outputType) {
    logger.error('Missing required arguments');
    logger.dim('  Usage: morph-spec state mark-output <feature> <output-type>');
    logger.blank();
    logger.dim('  Valid types: proposal, spec, contracts, tasks, decisions, recap');
    logger.dim('               uiDesignSystem, uiMockups, uiComponents, uiFlows');
    process.exit(1);
  }

  try {
    StateManager.markOutput(featureName, outputType);

    logger.success(`Output '${chalk.cyan(outputType)}' marked as created for ${chalk.cyan(featureName)}`);
    logger.blank();

  } catch (error) {
    logger.error(error.message);
    process.exit(1);
  }
}
