import 'dart:ui';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/connection_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/subspace_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/space_template_model.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:uuid/uuid.dart';

enum SpaceStatus { newSpace, modified, unchanged, deleted, parentDeleted }

class SpaceModel {
  String? uuid;
  String? icon;
  final String? spaceTuyaUuid;
  String name;
  String? lastThreeParents;
  final bool isPrivate;
  final String? invitationCode;
  SpaceModel? parent;
  final CommunityModel? community;
  List<SpaceModel> children;
  Offset position;
  bool isHovered;
  SpaceStatus status;
  String internalId;
  SpaceTemplateModel? spaceModel;
  List<Tag>? tags;
  List<SubspaceModel>? subspaces;

  List<Connection> outgoingConnections = []; // Connections from this space
  Connection? incomingConnection; // Connections to this space

  SpaceModel({
    this.uuid,
    String? internalId,
    this.lastThreeParents,
    this.spaceTuyaUuid,
    required this.icon,
    required this.name,
    required this.isPrivate,
    this.invitationCode,
    this.parent,
    this.community,
    required this.children,
    required this.position,
    this.isHovered = false,
    this.incomingConnection,
    this.status = SpaceStatus.unchanged,
    this.spaceModel,
    this.tags,
    this.subspaces,
  }) : internalId = internalId ?? const Uuid().v4();

  factory SpaceModel.fromJson(Map<String, dynamic> json,
      {String? parentInternalId}) {
    final String internalId = json['internalId'] ?? const Uuid().v4();

    final List<SpaceModel> children = json['children'] != null
        ? (json['children'] as List).map((childJson) {
            return SpaceModel.fromJson(
              childJson,
              parentInternalId: internalId,
            );
          }).toList()
        : [];

    final instance = SpaceModel(
      internalId: internalId,
      uuid: json['uuid'] ?? '',
      name: json['spaceName'],
      lastThreeParents: json['lastThreeParents'],
      isPrivate: json['isPrivate'] ?? false,
      invitationCode: json['invitationCode'],
      subspaces: (json['subspaces'] as List<dynamic>?)
              ?.where((e) => e is Map<String, dynamic>) // Validate type
              .map((e) => SubspaceModel.fromJson(e as Map<String, dynamic>))
              .toList() ??
          [],
      parent: parentInternalId != null
          ? SpaceModel(
              internalId: parentInternalId,
              uuid: json['parent']?['uuid'],
              spaceTuyaUuid: json['parent']?['spaceTuyaUuid'],
              name: json['parent']?['spaceName'] ?? '',
              isPrivate: json['parent']?['isPrivate'] ?? false,
              invitationCode: json['parent']?['invitationCode'],
              children: [],
              position:
                  Offset(json['parent']?['x'] ?? 0, json['parent']?['y'] ?? 0),
              icon: json['parent']?['icon'] ?? Assets.location,
            )
          : null,
      community: json['community'] != null
          ? CommunityModel.fromJson(json['community'])
          : null,
      children: children,
      icon: json['icon'] ?? Assets.location,
      position: Offset(json['x'] ?? 0, json['y'] ?? 0),
      isHovered: false,
      spaceModel: json['spaceModel'] != null
          ? SpaceTemplateModel.fromJson(json['spaceModel'])
          : null,
      tags: (json['productAllocations'] as List<dynamic>?)
              ?.where((item) => item is Map<String, dynamic>) // Validate type
              .map((item) => Tag.fromJson(item as Map<String, dynamic>))
              .toList() ??
          [],
    );

    if (json['incomingConnections'] != null &&
        json['incomingConnections'] is List &&
        (json['incomingConnections'] as List).isNotEmpty &&
        instance.parent != null) {
      final conn = json['incomingConnections'][0];
      instance.incomingConnection = Connection(
        startSpace: instance.parent ?? instance, // Parent space
        endSpace: instance, // This space instance
      );
    }

    return instance;
  }

  Map<String, dynamic> toMap() {
    return {
      'uuid': uuid ?? '',
      'spaceTuyaUuid': spaceTuyaUuid,
      'name': name,
      'lastThreeParents': lastThreeParents,
      'isPrivate': isPrivate,
      'invitationCode': invitationCode,
      'parent': parent?.uuid,
      'subspaces': subspaces?.map((e) => e.toJson()).toList(),
      'community': community?.toMap(),
      'children': children.map((child) => child.toMap()).toList(),
      'icon': icon,
      'position': {'dx': position.dx, 'dy': position.dy},
      'isHovered': isHovered,
      'outgoingConnections': outgoingConnections.map((c) => c.toMap()).toList(),
      'incomingConnection': incomingConnection?.toMap(),
      'tags': tags?.map((e) => e.toJson()).toList(),
    };
  }

  void addOutgoingConnection(Connection connection) {
    outgoingConnections.add(connection);
  }
}

extension SpaceExtensions on SpaceModel {
  List<String> listAllTagValues() {
    final List<String> tagValues = [];

    if (tags != null) {
      tagValues.addAll(
          tags!.map((tag) => tag.tag ?? '').where((tag) => tag.isNotEmpty));
    }

    if (subspaces != null) {
      for (final subspace in subspaces!) {
        if (subspace.tags != null) {
          tagValues.addAll(
            subspace.tags!
                .map((tag) => tag.tag ?? '')
                .where((tag) => tag.isNotEmpty),
          );
        }
      }
    }

    return tagValues;
  }

  bool isNoChangesSubmited(String name, icon, SpaceTemplateModel? spaceModel,
      List<SubspaceModel>? subspaces, List<Tag>? tags) {
    return (name == this.name &&
        icon == this.icon &&
        spaceModel == this.spaceModel &&
        subspaces == this.subspaces &&
        tags == this.tags);
  }
}
