import 'dart:async';
import 'dart:io';
import 'package:dart_framework/utils/system_util.dart';
import 'package:oto/cli/cli.dart';
import 'package:oto/cli/commands/command_base.dart';
import 'package:oto/oto/agent/agent_config.dart';
import 'package:oto/oto/agent/agent_runner.dart';

class CommandAgent extends CommandBase {
  AgentRunner runner;

  CommandAgent({AgentRunner? runner}) : runner = runner ?? DefaultAgentRunner();

  @override
  String get name => 'agent';

  @override
  String get usage => 'run --config <path>';

  @override
  Map<String, List<String>> get arguments => {
        'run': ['Run the OTO agent daemon.'],
        '--config {file path}': ['Path to the agent configuration YAML file.'],
      };

  @override
  String getDescription() {
    return ':::: Manage the OTO agent lifecycle and connections.';
  }

  @override
  bool shouldExecuteWithoutParameters() => false;

  @override
  Future execute(List<String> parameters) async {
    if (parameters.isEmpty) {
      printHelp();
      return simpleFuture;
    }

    final subcommand = parameters[0];
    if (subcommand != 'run') {
      printOut('Unknown subcommand: "$subcommand"', PrintType.error);
      return simpleFuture;
    }

    if (parameters.contains('-h') || parameters.contains('--help')) {
      printRunHelp();
      return simpleFuture;
    }

    String? configPath;
    for (int i = 1; i < parameters.length; i++) {
      final param = parameters[i];
      if (param == '--config') {
        if (i + 1 < parameters.length) {
          configPath = parameters[++i];
        } else {
          printOut('Missing value for --config parameter.', PrintType.error);
          return simpleFuture;
        }
      } else if (param.startsWith('--config=')) {
        configPath = param.substring('--config='.length);
      } else {
        printOut('Unknown argument: "$param"', PrintType.error);
        return simpleFuture;
      }
    }

    if (configPath == null || configPath.trim().isEmpty) {
      printOut('Missing required parameter "--config <path>"', PrintType.error);
      return simpleFuture;
    }

    try {
      final config = AgentConfig.fromFile(configPath);
      await runner.run(config);
    } on AgentConfigException catch (e) {
      printOut('Configuration error: ${e.message}', PrintType.error);
      exitCode = 10;
    } on RegistrationException catch (e) {
      await CLI.println('Error: ${e.message}', color: Color.red);
      exitCode = 10;
    } catch (e) {
      await CLI.println('Error: Failed to run agent: $e', color: Color.red);
      exitCode = 10;
    }

    return simpleFuture;
  }

  void printRunHelp() {
    final exeName = CLI.executableFileName;
    final list = [
      '',
      'Run the OTO agent daemon and connect to the Edge server.',
      '',
      'Usage: ${CLI.style('$exeName agent run --config <path>', color: Color.greenStrong)}',
      '',
      'Available arguments:',
      '  --config <path>      Path to the agent configuration YAML file.',
      '',
    ];
    CLI.print(list);
  }
}
