import 'dart:convert';

import 'package:syncrow_app/features/scene/model/create_scene_model.dart';

class CreateAutomationModel {
  String unitUuid;
  String automationName;
  String decisionExpr;
  EffectiveTime effectiveTime;
  List<CreateCondition> conditions;
  List<CreateSceneAction> actions;

  CreateAutomationModel({
    required this.unitUuid,
    required this.automationName,
    required this.decisionExpr,
    required this.effectiveTime,
    required this.conditions,
    required this.actions,
  });

  CreateAutomationModel copyWith({
    String? unitUuid,
    String? automationName,
    String? decisionExpr,
    EffectiveTime? effectiveTime,
    List<CreateCondition>? conditions,
    List<CreateSceneAction>? actions,
  }) {
    return CreateAutomationModel(
      unitUuid: unitUuid ?? this.unitUuid,
      automationName: automationName ?? this.automationName,
      decisionExpr: decisionExpr ?? this.decisionExpr,
      effectiveTime: effectiveTime ?? this.effectiveTime,
      conditions: conditions ?? this.conditions,
      actions: actions ?? this.actions,
    );
  }

  Map<String, dynamic> toMap([String? automationId]) {
    return {
      if (automationId == null) 'spaceUuid': unitUuid,
      'automationName': automationName,
      'decisionExpr': decisionExpr,
      'effectiveTime': effectiveTime.toMap(),
      'conditions': conditions.map((x) => x.toMap()).toList(),
      'actions': actions.map((x) => x.toMap()).toList(),
    };
  }

  factory CreateAutomationModel.fromMap(Map<String, dynamic> map) {
    return CreateAutomationModel(
      unitUuid: map['spaceUuid'] ?? '',
      automationName: map['automationName'] ?? '',
      decisionExpr: map['decisionExpr'] ?? '',
      effectiveTime: EffectiveTime.fromMap(map['effectiveTime']),
      conditions: List<CreateCondition>.from(
          map['conditions']?.map((x) => CreateCondition.fromMap(x))),
      actions: List<CreateSceneAction>.from(
          map['actions']?.map((x) => CreateSceneAction.fromMap(x))),
    );
  }

  String toJson([String? automationId]) => json.encode(toMap(automationId));

  factory CreateAutomationModel.fromJson(String source) =>
      CreateAutomationModel.fromMap(json.decode(source));

  @override
  String toString() {
    return 'CreateAutomationModel(unitUuid: $unitUuid, automationName: $automationName, decisionExpr: $decisionExpr, effectiveTime: $effectiveTime, conditions: $conditions, actions: $actions)';
  }
}

class EffectiveTime {
  String start;
  String end;
  String loops;

  EffectiveTime({
    required this.start,
    required this.end,
    required this.loops,
  });

  Map<String, dynamic> toMap() {
    return {
      'start': start,
      'end': end,
      'loops': loops,
    };
  }

  factory EffectiveTime.fromMap(Map<String, dynamic> map) {
    return EffectiveTime(
      start: map['start'] ?? '',
      end: map['end'] ?? '',
      loops: map['loops'] ?? '',
    );
  }

  @override
  String toString() => 'EffectiveTime(start: $start, end: $end, loops: $loops)';
}

class CreateCondition {
  int code;
  String entityId;
  String entityType;
  ConditionExpr expr;

  CreateCondition({
    required this.code,
    required this.entityId,
    required this.entityType,
    required this.expr,
  });

  Map<String, dynamic> toMap() {
    return {
      'code': code,
      'entityId': entityId,
      'entityType': entityType,
      'expr': expr.toMap(),
    };
  }

  factory CreateCondition.fromMap(Map<String, dynamic> map) {
    return CreateCondition(
      code: map['code'] ?? 0,
      entityId: map['entityId'] ?? '',
      entityType: map['entityType'] ?? '',
      expr: ConditionExpr.fromMap(map['expr']),
    );
  }

  @override
  String toString() =>
      'CreateCondition(code: $code, entityId: $entityId, entityType: $entityType, expr: $expr)';
}

class ConditionExpr {
  String statusCode;
  String comparator;
  dynamic statusValue;

  ConditionExpr({
    required this.statusCode,
    required this.comparator,
    required this.statusValue,
  });

  Map<String, dynamic> toMap() {
    return {
      'statusCode': statusCode,
      'comparator': comparator,
      'statusValue': statusValue,
    };
  }

  factory ConditionExpr.fromMap(Map<String, dynamic> map) {
    return ConditionExpr(
      statusCode: map['statusCode'] ?? '',
      comparator: map['comparator'] ?? '',
      statusValue: map['statusValue'],
    );
  }

  @override
  String toString() =>
      'ConditionExpr(statusCode: $statusCode, comparator: $comparator, statusValue: $statusValue)';
}
