// wizard.dart — Interactive CLI wizard (brief discovery UX gap fix)

import 'dart:io';
import 'logger.dart';

class Wizard {
  static Future<void> run({required String outputPath}) async {
    Logger.info('\n🧙  cursor_gen Interactive Wizard');
    Logger.info('─' * 42);
    Logger.info(
        'Answer the questions below to generate your project-brief.yaml.\n');

    final answers = <String, dynamic>{};

    // Project basics
    answers['name'] = _ask('Project name', hint: 'ShopEasy');
    answers['package'] = _ask('Package ID', hint: 'com.company.shopeasy');
    answers['description'] = _ask('Short description',
        hint: 'E-commerce app with real-time inventory');
    answers['scale'] = _askChoice('Project scale', ['small', 'medium', 'large'],
        defaultIdx: 1);

    Logger.info('');

    // Stack
    answers['state_management'] = _askChoice(
        'State management', ['bloc', 'riverpod', 'getx', 'hooks_riverpod'],
        defaultIdx: 1);
    answers['architecture'] = _askChoice(
        'Architecture', ['clean', 'feature_first', 'mvvm', 'mvc', 'layered'],
        defaultIdx: 0);
    answers['routing'] = _askChoice(
        'Routing', ['gorouter', 'getx_nav', 'auto_route'],
        defaultIdx: 0);
    answers['backend'] = _askChoice('Backend(s)',
        ['firebase', 'supabase', 'rest', 'firebase+rest', 'supabase+rest'],
        defaultIdx: 2);
    answers['auth'] = _askChoice('Auth method',
        ['firebase_auth', 'supabase_auth', 'jwt_rest', 'oauth2', 'none'],
        defaultIdx: 4);

    Logger.info('');

    // Platforms (Pillar 4)
    answers['platforms'] = _askMultiChoice(
        'Target platforms', ['ios', 'android', 'web', 'desktop'],
        defaults: [0, 1]);

    // Codegen (Pillar 4)
    answers['codegen'] = _askMultiChoice('Code generation tools (optional)', [
      'freezed',
      'json_serializable',
      'injectable',
      'retrofit'
    ], defaults: []);

    Logger.info('');

    // References & app UX
    final reposRaw =
        _ask('Git reference repo URLs (comma-separated, optional)', hint: '');
    answers['reference_repos'] = _splitComma(reposRaw);
    final localRaw =
        _ask('Local reference paths (comma-separated, optional)', hint: '');
    answers['local_paths'] = _splitComma(localRaw);
    answers['theme_variants'] = _askMultiChoice(
        'Theme variants to support',
        ['light', 'dark', 'high_contrast'],
        defaults: [0, 1]);
    final rolesOn =
        _askBool('Does the app support user roles?', defaultYes: false);
    answers['roles_enabled'] = rolesOn;
    if (rolesOn) {
      final raw =
          _ask('Role names (comma-separated)', hint: 'admin,member,guest');
      answers['role_names'] = _splitComma(raw);
    } else {
      answers['role_names'] = <String>[];
    }

    Logger.info('');

    // Environments
    final flavorsInput =
        _ask('Build flavors (comma-separated)', hint: 'dev,staging,prod');
    answers['flavors'] = flavorsInput.split(',').map((e) => e.trim()).toList();
    answers['cicd'] = _askChoice(
        'CI/CD', ['github_actions', 'codemagic', 'fastlane', 'none'],
        defaultIdx: 0);

    // Testing
    answers['testing_depth'] = _askChoice(
        'Testing depth', ['unit_widget', 'integration', 'e2e', 'full'],
        defaultIdx: 0);

    // Localization
    final l10n = _askBool('Enable localization / i18n?', defaultYes: false);
    answers['i18n'] = l10n;

    // Telemetry opt-in (Pillar 6)
    final telemetry = _askBool(
        '\nOpt in to local telemetry (rule trigger logging, stored locally)?',
        defaultYes: false);
    answers['telemetry'] = telemetry;

    Logger.info('');
    final yaml = _buildYaml(answers);
    final file = File(outputPath);
    await file.writeAsString(yaml);
    Logger.success('✔  project-brief.yaml written to $outputPath');
    Logger.info('\nNext: cursor_gen --validate  →  cursor_gen');
  }

  static String _ask(String label, {String hint = ''}) {
    final display = hint.isNotEmpty ? '$label [$hint]: ' : '$label: ';
    stdout.write('  $display');
    final input = stdin.readLineSync()?.trim() ?? '';
    return input.isEmpty ? hint : input;
  }

  static String _askChoice(String label, List<String> options,
      {int defaultIdx = 0}) {
    Logger.info('  $label:');
    for (var i = 0; i < options.length; i++) {
      final marker = i == defaultIdx ? ' ◀' : '';
      Logger.dim('    ${i + 1}) ${options[i]}$marker');
    }
    stdout.write('  Choice [${defaultIdx + 1}]: ');
    final input = stdin.readLineSync()?.trim() ?? '';
    if (input.isEmpty) return options[defaultIdx];
    final idx = int.tryParse(input);
    if (idx != null && idx >= 1 && idx <= options.length)
      return options[idx - 1];
    return options[defaultIdx];
  }

  static List<String> _askMultiChoice(String label, List<String> options,
      {List<int> defaults = const []}) {
    Logger.info('  $label (comma-separated numbers, or leave blank):');
    for (var i = 0; i < options.length; i++) {
      final marker = defaults.contains(i) ? ' ◀' : '';
      Logger.dim('    ${i + 1}) ${options[i]}$marker');
    }
    final defaultStr = defaults.map((d) => '${d + 1}').join(',');
    stdout.write('  Choices [$defaultStr]: ');
    final input = stdin.readLineSync()?.trim() ?? '';
    if (input.isEmpty) return defaults.map((d) => options[d]).toList();
    return input
        .split(',')
        .map((s) => int.tryParse(s.trim()))
        .where((i) => i != null && i >= 1 && i <= options.length)
        .map((i) => options[i! - 1])
        .toList();
  }

  static bool _askBool(String label, {bool defaultYes = false}) {
    final hint = defaultYes ? 'Y/n' : 'y/N';
    stdout.write('  $label ($hint): ');
    final input = stdin.readLineSync()?.trim().toLowerCase() ?? '';
    if (input.isEmpty) return defaultYes;
    return input == 'y' || input == 'yes';
  }

  static List<String> _splitComma(String s) => s
      .split(',')
      .map((e) => e.trim())
      .where((e) => e.isNotEmpty)
      .toList();

  static String _yamlQStringList(List<String> xs) {
    if (xs.isEmpty) return '';
    return xs.map((e) => '"${_yamlEsc(e)}"').join(', ');
  }

  static String _yamlEsc(String s) =>
      s.replaceAll(r'\', r'\\').replaceAll('"', r'\"');

  static String _buildYaml(Map<String, dynamic> a) {
    final platforms = (a['platforms'] as List).map((p) => '"$p"').join(', ');
    final codegen = (a['codegen'] as List).map((c) => '"$c"').join(', ');
    final flavors = (a['flavors'] as List).map((f) => '"$f"').join(', ');
    final refRepos = List<String>.from(a['reference_repos'] as List);
    final refLocals = List<String>.from(a['local_paths'] as List);
    final themes = List<String>.from(a['theme_variants'] as List);
    final roles = List<String>.from(a['role_names'] as List);
    return '''# project-brief.yaml — cursor_gen configuration
# Generated by cursor_gen --wizard
# Run: cursor_gen  to generate .cursor/
# Run: cursor_gen --refresh  to update after changes

# Pillar 1: Pin to template version for reproducibility
cursor_templates_version: "1.0.1"

project:
  name: "${a['name']}"
  package: "${a['package']}"
  description: "${a['description']}"
  scale: "${a['scale']}"

stack:
  state_management: "${a['state_management']}"
  routing: "${a['routing']}"
  architecture: "${a['architecture']}"
  backend: "${a['backend']}"
  auth: "${a['auth']}"

  # Pillar 4: Platform targets
  platforms: [$platforms]

  # Pillar 4: Code generation tools
  codegen: [$codegen]

environments:
  flavors: [$flavors]
  cicd: "${a['cicd']}"

testing:
  depth: "${a['testing_depth']}"
  e2e_tool: "patrol"

design:
  source: "none"
  figma_url: ""

api_docs:
  format: "none"
  path: ""

references:
  repos: [${_yamlQStringList(refRepos)}]
  local_paths: [${_yamlQStringList(refLocals)}]

app_context:
  theme_variants: [${_yamlQStringList(themes)}]
  roles_enabled: ${a['roles_enabled']}
  role_names: [${_yamlQStringList(roles)}]

features:
  modules: []
  special: []

localization:
  enabled: ${a['i18n']}
  locales: ["en"]

# Pillar 6: Opt-in local telemetry (logs rule trigger frequency locally)
telemetry_opt_in: ${a['telemetry']}
''';
  }
}
