#!/usr/bin/env node

import { program } from 'commander';
import chalk from 'chalk';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { readFileSync } from 'fs';

import { initCommand } from '../src/commands/init.js';
import { updateCommand } from '../src/commands/update.js';
import { doctorCommand } from '../src/commands/doctor.js';
import { detectCommand } from '../src/commands/detect.js';
import { syncCommand } from '../src/commands/sync.js';
import { createStoryCommand } from '../src/commands/create-story.js';
import { shardSpecCommand } from '../src/commands/shard-spec.js';
import { sprintStatusCommand } from '../src/commands/sprint-status.js';
import { stateCommand } from '../src/commands/state.js';
import { taskDoneCommand, taskStartCommand, taskNextCommand } from '../src/commands/task.js';
import { costCommand } from '../src/commands/cost.js';
import { generateDesignSystemCommand } from '../src/commands/generate.js';
import { updateResourcePricing, showPricing, validatePricing } from '../src/commands/update-pricing.js';
import { validateCommand } from './validate.js';
import { LearningSystem } from '../src/lib/learning-system.js';

const __dirname = dirname(fileURLToPath(import.meta.url));
const pkg = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8'));

const banner = chalk.cyan(`
  ███╗   ███╗ ██████╗ ██████╗ ██████╗ ██╗  ██╗
  ████╗ ████║██╔═══██╗██╔══██╗██╔══██╗██║  ██║
  ██╔████╔██║██║   ██║██████╔╝██████╔╝███████║
  ██║╚██╔╝██║██║   ██║██╔══██╗██╔═══╝ ██╔══██║
  ██║ ╚═╝ ██║╚██████╔╝██║  ██║██║     ██║  ██║
  ╚═╝     ╚═╝ ╚═════╝ ╚═╝  ╚═╝╚═╝     ╚═╝  ╚═╝

  Methodical Orchestration for Reliable Production-ready SPEC-driven development
  by Polymorphism Tech | v${pkg.version}
`);

program
  .name('morph-spec')
  .description('MORPH-SPEC Framework CLI')
  .version(pkg.version)
  .addHelpText('beforeAll', banner);

program
  .command('init')
  .description('Initialize MORPH-SPEC in current directory')
  .option('-f, --force', 'Overwrite existing MORPH installation')
  .option('-p, --path <path>', 'Target path (default: current directory)')
  .action(initCommand);

program
  .command('update')
  .description('Update MORPH templates and standards to latest version')
  .option('--templates', 'Update only templates')
  .option('--standards', 'Update only standards')
  .action(updateCommand);

program
  .command('doctor')
  .description('Check MORPH installation health')
  .action(doctorCommand);

program
  .command('detect')
  .description('Detect project stack, architecture, and patterns')
  .option('-p, --path <path>', 'Project path (default: current directory)')
  .option('-v, --verbose', 'Show detailed detection results')
  .option('--no-save', 'Do not save results to .morph/project/')
  .action(detectCommand);

program
  .command('sync')
  .description('Sync standards from feature decisions')
  .option('-p, --path <path>', 'Project path (default: current directory)')
  .option('--dry-run', 'Show what would be synced without updating files')
  .action(syncCommand);

// Story-driven development commands
const storyCommand = program
  .command('story')
  .description('Story-driven development commands');

storyCommand
  .command('create <feature> <story-id>')
  .description('Create a new story with auto-injected Dev Notes')
  .option('--title <title>', 'Story title')
  .option('--epic <epic>', 'Epic name')
  .option('--context <context>', 'Story context')
  .option('--tasks <tasks>', 'Comma-separated tasks')
  .option('--dry-run', 'Preview without writing file')
  .action(createStoryCommand);

storyCommand
  .command('shard <feature>')
  .description('Shard spec.md into manageable chunks (90% token savings)')
  .option('--dry-run', 'Preview shards without writing files')
  .option('--verbose', 'Show detailed shard info')
  .action(shardSpecCommand);

storyCommand
  .command('status <feature> [action] [story-id]')
  .description('Manage sprint status (show | start | qa | done | next)')
  .action(sprintStatusCommand);

// State management commands
program
  .command('state <action> [args...]')
  .description('Manage state.json (init | get | set | checkpoint | list | add-agent | remove-agent | mark-output)')
  .option('--force', 'Force overwrite (init command)')
  .option('--project <name>', 'Project name (init command)')
  .option('--type <type>', 'Project type (init command)')
  .option('--json', 'Output as JSON (get command)')
  .action((action, args, options) => stateCommand(action, args, options));

// Task management commands (MORPH-SPEC 3.0)
const taskCommand = program
  .command('task')
  .description('Manage feature tasks (done | start | next)');

taskCommand
  .command('done <feature> <task-ids...>')
  .description('Mark tasks as completed')
  .action((feature, taskIds, options) => taskDoneCommand(feature, taskIds, options));

taskCommand
  .command('start <feature> <task-id>')
  .description('Start a task (mark as in_progress)')
  .action((feature, taskId, options) => taskStartCommand(feature, taskId, options));

taskCommand
  .command('next <feature>')
  .description('Show next suggested task')
  .action((feature, options) => taskNextCommand(feature, options));

// Cost calculation command
program
  .command('cost <bicep-files>')
  .description('Calculate Azure infrastructure costs from Bicep files')
  .option('--config <path>', 'Custom config path')
  .option('--verbose', 'Show detailed breakdown')
  .option('--json', 'Output as JSON')
  .option('--strict', 'Exit with error if cost exceeds ADR threshold')
  .action(costCommand);

// Pricing management commands
const pricingCommand = program
  .command('pricing')
  .description('Manage Azure pricing table');

pricingCommand
  .command('show [resource-type]')
  .description('Show current pricing (all or specific resource type)')
  .option('--json', 'Output as JSON')
  .action((resourceType, options) => showPricing({ resourceType, format: options.json ? 'json' : 'table' }));

pricingCommand
  .command('update <resource-type> <sku> <price>')
  .description('Update pricing for a specific SKU')
  .option('--dry-run', 'Preview without saving')
  .option('--no-validate', 'Skip validation')
  .action((resourceType, sku, price, options) =>
    updateResourcePricing({
      resourceType,
      sku,
      price: parseFloat(price),
      dryRun: options.dryRun,
      validate: options.validate !== false
    })
  );

pricingCommand
  .command('validate')
  .description('Validate pricing file against JSON schema')
  .action(validatePricing);

// Generation commands
const generateCommand = program
  .command('generate')
  .description('Generate code from templates');

generateCommand
  .command('design-system <ui-design-system-md>')
  .description('Generate CSS + theme files from ui-design-system.md')
  .option('--fluent', 'Generate only Fluent UI theme')
  .option('--mud', 'Generate only MudBlazor theme')
  .option('--both', 'Generate both themes (default)')
  .option('--namespace <ns>', 'C# namespace (default: YourProject.Themes)')
  .option('--css-output <path>', 'CSS output path (default: wwwroot/css/design-system.css)')
  .option('--fluent-output <path>', 'Fluent theme output path (default: Themes/FluentDesignTheme.cs)')
  .option('--mud-output <path>', 'MudBlazor theme output path (default: Themes/MudDesignTheme.cs)')
  .option('--dry-run', 'Preview without writing files')
  .action(generateDesignSystemCommand);

// Validation commands (Sprint 4: Continuous Validation)
program
  .command('validate [validator]')
  .description('Run project validations (all | packages | architecture | contrast)')
  .option('-v, --verbose', 'Show detailed output')
  .option('--auto-fix, --fix', 'Auto-fix issues where possible')
  .option('--no-fail', 'Don\'t exit with error code')
  .option('-i, --insights', 'Show learning insights')
  .option('--wcag-aaa', 'Use WCAG AAA standard (stricter)')
  .action((validator, options) => {
    const args = validator ? [validator] : ['all'];
    if (options.verbose) args.push('--verbose');
    if (options.autoFix) args.push('--auto-fix');
    if (options.noFail) args.push('--no-fail');
    if (options.insights) args.push('--insights');
    if (options.wcagAaa) args.push('--wcag-aaa');
    validateCommand(args);
  });

// Learning commands (Sprint 4: Learning System)
const learnCommand = program
  .command('learn')
  .description('AI learning system commands');

learnCommand
  .command('analyze')
  .description('Learn from project history (decisions.md files)')
  .option('-v, --verbose', 'Show detailed learning progress')
  .action(async (options) => {
    const learner = new LearningSystem('.');
    await learner.learnFromProject();

    if (options.verbose) {
      learner.formatInsights();
    }
  });

learnCommand
  .command('insights')
  .description('Show AI insights and patterns')
  .option('--json', 'Output as JSON')
  .action((options) => {
    const learner = new LearningSystem('.');

    if (options.json) {
      console.log(JSON.stringify(learner.getInsightsSummary(), null, 2));
    } else {
      learner.formatInsights();
    }
  });

learnCommand
  .command('suggest [category]')
  .description('Get AI suggestions for a category (uiLibrary | architecture | infrastructure | authentication | stateManagement | testing)')
  .option('--json', 'Output as JSON')
  .action((category, options) => {
    const learner = new LearningSystem('.');

    if (category) {
      const suggestion = learner.getSuggestion(category);
      if (options.json) {
        console.log(JSON.stringify(suggestion, null, 2));
      } else {
        console.log(chalk.cyan(`\n💡 Suggestion for ${category}:\n`));
        if (suggestion.confidence === 'none') {
          console.log(chalk.yellow(`   ${suggestion.reason}`));
        } else {
          console.log(chalk.white(`   → ${suggestion.suggestion} (${suggestion.percentage}% confidence)`));
          console.log(chalk.gray(`     ${suggestion.reason}`));
        }
        console.log('');
      }
    } else {
      const suggestions = learner.getAllSuggestions();
      if (options.json) {
        console.log(JSON.stringify(suggestions, null, 2));
      } else {
        learner.formatSuggestions(suggestions);
      }
    }
  });

learnCommand
  .command('reset')
  .description('Reset knowledge base (clear all learned patterns)')
  .option('--force', 'Skip confirmation')
  .action((options) => {
    if (!options.force) {
      console.log(chalk.yellow('\n⚠️  This will delete all learned patterns and preferences.'));
      console.log(chalk.gray('   Run with --force to confirm.\n'));
      process.exit(1);
    }

    const learner = new LearningSystem('.');
    learner.reset();
    console.log(chalk.green('\n✅ Knowledge base reset\n'));
  });

program.parse();
