import 'dart:convert';

class SceneDetailsModel {
  final String id;
  final String name;
  final String status;
  final String? icon;
  final bool? showInDevice;
  final String type;
  final List<Action> actions;
  final List<Condition>? conditions;
  final String? decisionExpr;
  final EffectiveTime? effectiveTime;

  SceneDetailsModel({
    required this.id,
    required this.name,
    required this.status,
    required this.type,
    required this.actions,
    this.icon,
    this.showInDevice,
    this.conditions,
    this.decisionExpr,
    this.effectiveTime,
  });

  factory SceneDetailsModel.fromRawJson(String str) =>
      SceneDetailsModel.fromJson(json.decode(str));

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

  factory SceneDetailsModel.fromJson(Map<String, dynamic> json) =>
      SceneDetailsModel(
          id: json["uuid"] ?? json["id"],
          name: json["name"],
          status: json["status"],
          type: json["type"],
          actions: (json["actions"] as List)
              .map((x) => Action.fromJson(x))
              .where((x) => x != null)
              .toList()
              .cast<Action>(),
          conditions: json["conditions"] != null
              ? (json["conditions"] as List)
                  .map((x) => Condition.fromJson(x))
                  .toList()
              : null,
          decisionExpr: json["decisionExpr"],
          effectiveTime: json["effectiveTime"] != null
              ? EffectiveTime.fromJson(json["effectiveTime"])
              : null,
          icon: json["iconUuid"] != null ? json["iconUuid"] ?? '' : '',
          showInDevice:
              json['showInHome'] != null ? json['showInHome'] ?? false : false);

  Map<String, dynamic> toJson() => {
        "id": id,
        "name": name,
        "status": status,
        "type": type,
        "actions": List<dynamic>.from(actions.map((x) => x.toJson())),
        "conditions": conditions != null
            ? List<dynamic>.from(conditions!.map((x) => x.toJson()))
            : null,
        "decisionExpr": decisionExpr,
        "effectiveTime": effectiveTime?.toJson(),
      };
}

class Action {
  final String actionExecutor;
  final String entityId;
  ExecutorProperty? executorProperty;
  String? name;
  String? type;
  final String productType;
  final String deviceName;

  Action({
    required this.actionExecutor,
    required this.entityId,
    this.executorProperty,
    this.name,
    this.type,
    required this.productType,
    required this.deviceName,
  });

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

  static Action? fromJson(Map<String, dynamic> json) {
    // Safely extract required fields with null checks
    final String? actionExecutor = json["actionExecutor"] as String?;
    final String? entityId = json["entityId"] as String?;
    final String? productType = json['productType'] as String?;
    final String? deviceName = json['deviceName'] as String?;

    // Skip invalid actions with missing required fields
    if (actionExecutor == null ||
        entityId == null ||
        productType == null ||
        deviceName == null) {
      return null;
    }

    // Handle actions with 'name' and 'type'
    if (json['name'] != null && json['type'] != null) {
      return Action(
        actionExecutor: actionExecutor,
        entityId: entityId,
        name: json['name'] as String?,
        type: json['type'] as String?,
        productType: productType,
        deviceName: deviceName,
      );
    }

    // Handle actions with 'executorProperty'
    if (json["executorProperty"] != null) {
      return Action(
        actionExecutor: actionExecutor,
        entityId: entityId,
        executorProperty: ExecutorProperty.fromJson(json["executorProperty"]),
        productType: productType,
        deviceName: deviceName,
      );
    }

    return null; // Skip invalid actions
  }

  Map<String, dynamic> toJson() => {
        "actionExecutor": actionExecutor,
        "entityId": entityId,
        "executorProperty": executorProperty?.toJson(),
        // "productType": productType
      };
}

class ExecutorProperty {
  final String? functionCode;
  dynamic functionValue;
  final dynamic delaySeconds;

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

  factory ExecutorProperty.fromJson(Map<String, dynamic> json) =>
      ExecutorProperty(
        functionCode: json["functionCode"] ?? '',
        functionValue: json["functionValue"] ?? '',
        delaySeconds: json["delaySeconds"] ?? 0,
      );

  Map<String, dynamic> toJson() => {
        "functionCode": functionCode,
        "functionValue": functionValue,
        "delaySeconds": delaySeconds,
      };
}

class Condition {
  final int code;
  final String entityId;
  final String entityType;
  final Expr expr;
  final String productType;
  final String deviceName;

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

  factory Condition.fromRawJson(String str) =>
      Condition.fromJson(json.decode(str));

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

  factory Condition.fromJson(Map<String, dynamic> json) => Condition(
        code: json["code"],
        entityId: json["entityId"],
        entityType: json["entityType"],
        expr: Expr.fromJson(json["expr"]),
        productType: json['productType'] as String,
        deviceName: json['deviceName'] as String,
      );

  Map<String, dynamic> toJson() => {
        "code": code,
        "entityId": entityId,
        "entityType": entityType,
        "expr": expr.toJson(),
      };
}

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

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

  factory Expr.fromRawJson(String str) => Expr.fromJson(json.decode(str));

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

  factory Expr.fromJson(Map<String, dynamic> json) => Expr(
        comparator: json["comparator"],
        statusCode: json["statusCode"],
        statusValue: json["statusValue"],
      );

  Map<String, dynamic> toJson() => {
        "comparator": comparator,
        "statusCode": statusCode,
        "statusValue": statusValue,
      };
}

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

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

  factory EffectiveTime.fromRawJson(String str) =>
      EffectiveTime.fromJson(json.decode(str));

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

  factory EffectiveTime.fromJson(Map<String, dynamic> json) => EffectiveTime(
        start: json["start"],
        end: json["end"],
        loops: json["loops"],
      );

  Map<String, dynamic> toJson() => {
        "start": start,
        "end": end,
        "loops": loops,
      };
}
