import 'dart:convert';

import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_automation_model.dart';
import 'package:syncrow_web/pages/routines/models/create_scene_and_autoamtion/create_scene_model.dart';

class RoutineDetailsModel {
  final String spaceUuid;
  final String name;
  final String decisionExpr;
  final List<RoutineAction> actions;
  final String? iconId;
  final bool? showInDevice;
  final EffectiveTime? effectiveTime;
  final List<RoutineCondition>? conditions;
  final String? type;
  final String? sceneId;
  final String? automationId;

  RoutineDetailsModel({
    required this.spaceUuid,
    required this.name,
    required this.decisionExpr,
    required this.actions,
    this.iconId,
    this.showInDevice,
    this.effectiveTime,
    this.conditions,
    this.type,
    this.sceneId,
    this.automationId,
  });

  // Convert to CreateSceneModel
  CreateSceneModel toCreateSceneModel() {
    return CreateSceneModel(
      spaceUuid: spaceUuid,
      iconId: iconId ?? '',
      showInDevice: showInDevice ?? false,
      sceneName: name,
      decisionExpr: decisionExpr,
      actions: actions.map((a) => a.toCreateSceneAction()).toList(),
    );
  }

  // Convert to CreateAutomationModel
  CreateAutomationModel toCreateAutomationModel() {
    return CreateAutomationModel(
      spaceUuid: spaceUuid,
      automationName: name,
      decisionExpr: decisionExpr,
      effectiveTime: effectiveTime ?? EffectiveTime(start: '', end: '', loops: ''),
      conditions: conditions?.map((c) => c.toCondition()).toList() ?? [],
      actions: actions.map((a) => a.toAutomationAction()).toList(),
    );
  }

  Map<String, dynamic> toMap() {
    return {
      'spaceUuid': spaceUuid,
      'name': name,
      'decisionExpr': decisionExpr,
      'actions': actions.map((x) => x.toMap()).toList(),
      if (iconId != null) 'iconUuid': iconId,
      if (showInDevice != null) 'showInDevice': showInDevice,
      if (effectiveTime != null) 'effectiveTime': effectiveTime!.toMap(),
      if (conditions != null) 'conditions': conditions!.map((x) => x.toMap()).toList(),
      if (type != null) 'type': type,
      if (sceneId != null) 'sceneId': sceneId,
      if (automationId != null) 'automationId': automationId,
    };
  }

  factory RoutineDetailsModel.fromMap(Map<String, dynamic> map) {
    return RoutineDetailsModel(
      spaceUuid: map['spaceUuid'] ?? '',
      name: map['name'] ?? '',
      decisionExpr: map['decisionExpr'] ?? '',
      actions: List<RoutineAction>.from(
        map['actions']?.map((x) => RoutineAction.fromMap(x)) ?? [],
      ),
      iconId: map['iconUuid'],
      showInDevice: map['showInDevice'],
      effectiveTime:
          map['effectiveTime'] != null ? EffectiveTime.fromMap(map['effectiveTime']) : null,
      conditions: map['conditions'] != null
          ? List<RoutineCondition>.from(map['conditions'].map((x) => RoutineCondition.fromMap(x)))
          : null,
      type: map['type'],
      sceneId: map['sceneId'],
      automationId: map['automationId'],
    );
  }

  String toJson() => json.encode(toMap());

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

class RoutineAction {
  final String entityId;
  final String actionExecutor;
  final String? name;
  final RoutineExecutorProperty? executorProperty;
  final String productType;
  final String? type;
  final String? icon;

  RoutineAction(
      {required this.entityId,
      required this.actionExecutor,
      required this.productType,
      this.executorProperty,
      this.name,
      this.type,
      this.icon});

  CreateSceneAction toCreateSceneAction() {
    return CreateSceneAction(
      entityId: entityId,
      actionExecutor: actionExecutor,
      executorProperty: executorProperty?.toCreateSceneExecutorProperty(),
    );
  }

  AutomationAction toAutomationAction() {
    return AutomationAction(
      entityId: entityId,
      actionExecutor: actionExecutor,
      executorProperty: executorProperty?.toExecutorProperty(),
    );
  }

  Map<String, dynamic> toMap() {
    return {
      'entityId': entityId,
      'actionExecutor': actionExecutor,
      if (type != null) 'type': type,
      if (name != null) 'name': name,
      if (executorProperty != null) 'executorProperty': executorProperty!.toMap(),
    };
  }

  factory RoutineAction.fromMap(Map<String, dynamic> map) {
    return RoutineAction(
        entityId: map['entityId'] ?? '',
        actionExecutor: map['actionExecutor'] ?? '',
        productType: map['productType'] ?? '',
        name: map['name'] ?? '',
        type: map['type'] ?? '',
        executorProperty: map['executorProperty'] != null
            ? RoutineExecutorProperty.fromMap(map['executorProperty'])
            : null,
        icon: map['icon']);
  }
}

class RoutineExecutorProperty {
  final String? functionCode;
  final dynamic functionValue;
  final int? delaySeconds;

  RoutineExecutorProperty({
    this.functionCode,
    this.functionValue,
    this.delaySeconds,
  });

  CreateSceneExecutorProperty toCreateSceneExecutorProperty() {
    return CreateSceneExecutorProperty(
      functionCode: functionCode ?? '',
      functionValue: functionValue,
      delaySeconds: delaySeconds ?? 0,
    );
  }

  ExecutorProperty toExecutorProperty() {
    return ExecutorProperty(
      functionCode: functionCode,
      functionValue: functionValue,
      delaySeconds: delaySeconds,
    );
  }

  Map<String, dynamic> toMap() {
    return {
      if (functionCode != null) 'functionCode': functionCode,
      if (functionValue != null) 'functionValue': functionValue,
      if (delaySeconds != null) 'delaySeconds': delaySeconds,
    };
  }

  factory RoutineExecutorProperty.fromMap(Map<String, dynamic> map) {
    return RoutineExecutorProperty(
      functionCode: map['functionCode'],
      functionValue: map['functionValue'],
      delaySeconds: map['delaySeconds']?.toInt(),
    );
  }
}

class RoutineCondition {
  final int code;
  final String entityId;
  final String entityType;
  final RoutineConditionExpr expr;
  final String productType;

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

  Condition toCondition() {
    return Condition(
      code: code,
      entityId: entityId,
      entityType: entityType,
      expr: expr.toConditionExpr(),
    );
  }

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

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

class RoutineConditionExpr {
  final String statusCode;
  final String comparator;
  final dynamic statusValue;

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

  ConditionExpr toConditionExpr() {
    return ConditionExpr(
      statusCode: statusCode,
      comparator: comparator,
      statusValue: statusValue,
    );
  }

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

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