import 'package:dart_framework/utils/system_util.dart';
import 'package:oto/oto/data/pipeline_data.dart';
import 'package:oto/oto/pipeline/pipeline.dart';
import 'package:oto/oto/pipeline/pipeline_condition.dart';
import 'package:oto/oto/pipeline/pipeline_exe.dart';

/// Executes tasks for the first matching case value.
/// Uses condition-string/int/etc. compared to each case value with ==.
///
/// Example YAML:
/// ```yaml
/// - switch:
///     condition-string: "<!property.env>"
///     cases:
///       - value: prod
///         tasks:
///           - exe: deployProd
///       - value: staging
///         tasks:
///           - exe: deployStaging
/// ```
class PipelineSwitch extends PipelineCondition {
  late Pipeline? _pipeline;

  @override
  PipelineValidateResult initialize(Map<String, dynamic> set) {
    var result = super.initialize(set);
    final raw = set.values.first;
    if (raw is! Map) {
      result.enable = false;
      result.message = 'switch: value must be a map.';
      return result;
    }
    final rawMap = Map<String, dynamic>.from(raw);
    final casesVal = rawMap['cases'];
    if (casesVal == null || casesVal is! List) {
      result.enable = false;
      result.message = casesVal == null
          ? 'switch: cases field is required.'
          : 'switch: cases must be a list, got: ${casesVal.runtimeType}.';
      return result;
    }
    for (var i = 0; i < casesVal.length; i++) {
      final caseItem = casesVal[i];
      if (caseItem is! Map) {
        result.enable = false;
        result.message = 'switch: cases[$i] must be a map.';
        return result;
      }
      final tasks = caseItem['tasks'];
      if (tasks == null || tasks is! List) {
        result.enable = false;
        result.message = tasks == null
            ? 'switch: cases[$i].tasks is required.'
            : 'switch: cases[$i].tasks must be a list, got: ${tasks.runtimeType}.';
        return result;
      }
    }
    DataSwitch data;
    try {
      data = DataSwitch.fromJson(rawMap);
    } on TypeError catch (_) {
      result.enable = false;
      result.message = 'switch: invalid field type in YAML definition.';
      return result;
    }
    var dataValidateResult = data.validate();
    if (!dataValidateResult.enable) {
      return dataValidateResult;
    }

    for (var item in data.cases) {
      var validateResult = PipelineExecutor.validateTasks(item.tasks, context: context);
      if (!validateResult.enable) {
        return validateResult;
      }
    }

    this.data = data;
    return result;
  }

  @override
  Future execute() async {
    var data = this.data as DataSwitch;
    var condition = '${data.condition!} == ';
    var executed = false;
    for (var item in data.cases) {
      var addCondition = '$condition${item.value}';
      var result = checkCondition(addCondition);
      if (result.result) {
        executed = true;
        var validateResult =
            PipelineExecutor.validateTasks(item.tasks, context: context);
        _pipeline = validateResult.pipeline;
        await PipelineExecutor.printCondition('Switch', data.condition!, 'Start task', result);
        await _pipeline?.execute();
        break;
      }
    }
    if (!executed) {
      var result = ConditionCheckResult();
      result.conditionValue = 'null';
      result.result = false;
      await PipelineExecutor.printCondition(
          'Switch', data.condition!, 'not exist Same condition', result);
    }
    return simpleFuture;
  }
}
