import 'package:dart_framework/utils/system_util.dart';
import 'package:oto/oto/core/tag_system.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';

class PipelineContain extends PipelineExecutor {
  late DataContain data;
  late Pipeline? _pipelineTrue;
  late Pipeline? _pipelineFalse;

  @override
  PipelineValidateResult initialize(Map<String, dynamic> set) {
    var result = PipelineValidateResult();
    final raw = set.values.first;
    if (raw is! Map) {
      result.enable = false;
      result.message = 'contain: value must be a map.';
      return result;
    }
    final rawMap = Map<String, dynamic>.from(raw);
    final targetVal = rawMap['target'];
    if (targetVal == null || targetVal is! String || targetVal.trim().isEmpty) {
      result.enable = false;
      result.message = 'contain: "target" must be a non-empty string.';
      return result;
    }
    final listVal = rawMap['list'];
    if (listVal == null || (listVal is! List && listVal is! String)) {
      result.enable = false;
      result.message = 'contain: "list" must be a List or String.';
      return result;
    }
    final onTrue = rawMap['on-true'];
    if (onTrue != null && onTrue is! List) {
      result.enable = false;
      result.message =
          'contain: "on-true" must be a list, got: ${onTrue.runtimeType}.';
      return result;
    }
    final onFalse = rawMap['on-false'];
    if (onFalse != null && onFalse is! List) {
      result.enable = false;
      result.message =
          'contain: "on-false" must be a list, got: ${onFalse.runtimeType}.';
      return result;
    }
    DataContain data;
    try {
      data = DataContain.fromJson(rawMap);
    } on TypeError catch (_) {
      result.enable = false;
      result.message = 'contain: invalid field type in YAML definition.';
      return result;
    }
    var dataValidateResult = data.validate();
    if (!dataValidateResult.enable) {
      return dataValidateResult;
    }

    //set true task
    var validateResult =
        PipelineExecutor.validateTasks(data.on_true, context: context);
    if (!validateResult.enable) {
      return validateResult;
    }
    _pipelineTrue = validateResult.pipeline;

    //set false task
    validateResult =
        PipelineExecutor.validateTasks(data.on_false, context: context);
    if (!validateResult.enable) {
      return validateResult;
    }
    _pipelineFalse = validateResult.pipeline;
    this.data = data;

    return result;
  }

  @override
  Future execute() async {
    var result = ConditionCheckResult();
    var value = TagSystem.replaceSingleTagValue(data.target, context: runtimeContext);
    value ??= data.target;
    result.conditionValue = 'Contain in "$value".';

    var listRaw = data.list;
    if(listRaw is String) {
      var str = TagSystem.replaceTagValue(listRaw, context: runtimeContext) as String;
      result.result = str.contains(value);
    } else {
      var list = listRaw as List;
      result.result = list.contains(value);
    }
    
    
    await PipelineExecutor.printCondition('Contain', 'Contain in "${data.target}"', getPostfix(result.result), result);
    if (result.result) {
      await _pipelineTrue?.execute();
    } else {
      await _pipelineFalse?.execute();
    }
    return simpleFuture;
  }

  String getPostfix(bool condition) {
    if (condition) {
      return _pipelineTrue == null
          ? 'on-true not exist. Passed'
          : 'Execute: on-true ';
    } else {
      return _pipelineFalse == null
          ? 'on-false not exist. Passed'
          : 'Execute: on-false ';
    }
  }
}
