import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/device_managment/device_setting/settings_model/sub_space_model.dart';
import 'package:syncrow_web/pages/space_tree/model/pagination_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/community_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/create_subspace_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_model.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/space_response_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/pages/spaces_management/space_model/models/tag_body_model.dart';
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_update_model.dart';
import 'package:syncrow_web/services/api/http_service.dart';
import 'package:syncrow_web/utils/constants/api_const.dart';

import '../pages/spaces_management/all_spaces/model/subspace_model.dart';

class CommunitySpaceManagementApi {
  // Community Management APIs
  Future<List<CommunityModel>> fetchCommunities(String projectId,
      {int page = 1}) async {
    try {
      List<CommunityModel> allCommunities = [];
      bool hasNext = true;

      while (hasNext) {
        await HTTPService().get(
          path: ApiEndpoints.getCommunityList
              .replaceAll('{projectId}', projectId),
          queryParameters: {
            'page': page,
          },
          expectedResponseModel: (json) {
            try {
              List<dynamic> jsonData = json['data'] ?? [];
              hasNext = json['hasNext'] ?? false;
              int currentPage = json['page'] ?? 1;
              List<CommunityModel> communityList = jsonData.map((jsonItem) {
                return CommunityModel.fromJson(jsonItem);
              }).toList();
              allCommunities.addAll(communityList);
              page = currentPage + 1;
              return communityList;
            } catch (_) {
              hasNext = false;
              return [];
            }
          },
        );
      }

      return allCommunities;
    } catch (e) {
      return [];
    }
  }

  Future<PaginationModel> fetchCommunitiesAndSpaces(
      {required String projectId, int page = 1, String search = ''}) async {
    PaginationModel paginationModel = const PaginationModel.emptyConstructor();

    try {
      bool hasNext = false;
      await HTTPService().get(
        path:
            ApiEndpoints.getCommunityList.replaceAll('{projectId}', projectId),
        queryParameters: {
          'page': page,
          'includeSpaces': true,
          'size': 25,
          'search': search
        },
        expectedResponseModel: (json) {
          try {
            List<dynamic> jsonData = json['data'] ?? [];
            hasNext = json['hasNext'] ?? false;
            int currentPage = json['page'] ?? 1;
            List<CommunityModel> communityList = jsonData.map((jsonItem) {
              return CommunityModel.fromJson(jsonItem);
            }).toList();

            page = currentPage + 1;
            paginationModel = PaginationModel(
                pageNum: page,
                hasNext: hasNext,
                size: 25,
                communities: communityList);
            return paginationModel;
          } catch (_) {
            hasNext = false;
            return [];
          }
        },
      );
    } catch (_) {}
    return paginationModel;
  }

  Future<CommunityModel?> getCommunityById(String communityId) async {
    try {
      final response = await HTTPService().get(
        path: ApiEndpoints.getCommunityById
            .replaceAll('{communityId}', communityId),
        expectedResponseModel: (json) {
          return CommunityModel.fromJson(json['data']);
        },
      );
      return response;
    } catch (e) {
      debugPrint('Error fetching community by ID: $e');
      return null;
    }
  }

  Future<CommunityModel?> createCommunity(
      String name, String description, String projectId) async {
    try {
      final response = await HTTPService().post(
        path: ApiEndpoints.createCommunity.replaceAll('{projectId}', projectId),
        body: {
          'name': name,
          'description': description,
        },
        expectedResponseModel: (json) {
          return CommunityModel.fromJson(json['data']);
        },
      );
      return response;
    } catch (e) {
      debugPrint('Error creating community: $e');
      return null;
    }
  }

  Future<bool> updateCommunity(
      String communityId, String name, String projectId) async {
    try {
      final response = await HTTPService().put(
        path: ApiEndpoints.updateCommunity
            .replaceAll('{communityId}', communityId)
            .replaceAll('{projectId}', projectId),
        body: {
          'name': name,
        },
        expectedResponseModel: (json) {
          return json['success'] ?? false;
        },
      );
      return response;
    } catch (e) {
      debugPrint('Error updating community: $e');
      return false;
    }
  }

  Future<bool> deleteCommunity(String communityId, String projectId) async {
    try {
      final response = await HTTPService().delete(
        path: ApiEndpoints.deleteCommunity
            .replaceAll('{communityId}', communityId)
            .replaceAll('{projectId}', projectId),
        expectedResponseModel: (json) {
          return json['success'] ?? false;
        },
      );
      return response;
    } catch (e) {
      debugPrint('Error deleting community: $e');
      return false;
    }
  }

  Future<SpacesResponse> fetchSpaces(
      String communityId, String projectId) async {
    try {
      final response = await HTTPService().get(
        path: ApiEndpoints.listSpaces
            .replaceAll('{communityId}', communityId)
            .replaceAll('{projectId}', projectId),
        expectedResponseModel: (json) {
          return SpacesResponse.fromJson(json);
        },
      );
      return response;
    } catch (e) {
      debugPrint('Error fetching spaces: $e');
      return SpacesResponse(
        data: [],
        message: 'Error fetching spaces',
        page: 1,
        size: 10,
        totalItem: 0,
        totalPage: 0,
        hasNext: false,
        hasPrevious: false,
      );
    }
  }

  Future<SpaceModel?> getSpace(
      String communityId, String spaceId, String projectId) async {
    try {
      final response = await HTTPService().get(
        path: ApiEndpoints.getSpace
            .replaceAll('{communityId}', communityId)
            .replaceAll('{spaceId}', spaceId)
            .replaceAll('{projectId}', projectId),
        expectedResponseModel: (json) {
          return SpaceModel.fromJson(json['data']);
        },
      );
      return response;
    } catch (e) {
      debugPrint('Error fetching space: $e');
      return null; // Assuming an empty SpaceModel constructor
    }
  }

  Future<SpaceModel?> createSpace(
      {required String communityId,
      required String name,
      String? parentId,
      bool isPrivate = false,
      required Offset position,
      String? spaceModelUuid,
      String? icon,
      List<CreateTagBodyModel>? tags,
      List<CreateSubspaceModel>? subspaces,
      required String projectId}) async {
    try {
      final body = {
        'spaceName': name,
        'isPrivate': isPrivate,
        'x': position.dx,
        'y': position.dy,
        'icon': icon,
      };
      if (parentId != null) {
        body['parentUuid'] = parentId;
      }
      if (tags != null) {
        body['tags'] = tags;
      }

      if (spaceModelUuid != null) body['spaceModelUuid'] = spaceModelUuid;

      if (subspaces != null) body['subspaces'] = subspaces;
      final response = await HTTPService().post(
        path: ApiEndpoints.createSpace
            .replaceAll('{communityId}', communityId)
            .replaceAll('{projectId}', projectId),
        body: body,
        expectedResponseModel: (json) {
          return SpaceModel.fromJson(json['data']);
        },
      );
      return response;
    } catch (e) {
      debugPrint('Error creating space: $e');
      return null;
    }
  }

  Future<bool> updateSpace(
      {required String communityId,
      required spaceId,
      required String name,
      String? parentId,
      String? icon,
      bool isPrivate = false,
      required Offset position,
      List<Tag>? tags,
      List<SubspaceModel>? subspaces,
      String? spaceModelUuid,
      required String projectId}) async {
    try {
      final body = {
        'spaceName': name,
        'isPrivate': isPrivate,
        'x': position.dx,
        'y': position.dy,
        'icon': icon,
        'subspaces': subspaces,
        'tags': tags,
        'spaceModelUuid': spaceModelUuid,
      };
      if (parentId != null) {
        body['parentUuid'] = parentId;
      }

      final response = await HTTPService().put(
        path: ApiEndpoints.updateSpace
            .replaceAll('{communityId}', communityId)
            .replaceAll('{spaceId}', spaceId)
            .replaceAll('{projectId}', projectId),
        body: body,
        expectedResponseModel: (json) {
          return json['success'] ?? false;
        },
      );

      return response;
    } catch (e) {
      debugPrint('Error updating space: $e');
      return false;
    }
  }

  Future<bool> deleteSpace(
      String communityId, String spaceId, String projectId) async {
    try {
      final response = await HTTPService().delete(
        path: ApiEndpoints.deleteSpace
            .replaceAll('{communityId}', communityId)
            .replaceAll('{spaceId}', spaceId)
            .replaceAll('{projectId}', projectId),
        expectedResponseModel: (json) {
          return json['success'] ?? false;
        },
      );
      return response;
    } catch (e) {
      debugPrint('Error deleting space: $e');
      return false;
    }
  }

  Future<List<SpaceModel>> getSpaceHierarchy(
      String communityId, String projectId) async {
    try {
      final response = await HTTPService().get(
        path: ApiEndpoints.getSpaceHierarchy
            .replaceAll('{communityId}', communityId)
            .replaceAll('{projectId}', projectId),
        expectedResponseModel: (json) {
          final spaceModels = (json['data'] as List)
              .map((spaceJson) => SpaceModel.fromJson(spaceJson))
              .toList();

          return spaceModels;
        },
      );
      return response;
    } catch (e) {
      debugPrint('Error fetching space hierarchy: $e');
      return [];
    }
  }

  Future<List<SpaceModel>> getSpaceOnlyWithDevices(
      {String? communityId, String? projectId}) async {
    try {
      final response = await HTTPService().get(
        path: ApiEndpoints.spaceOnlyWithDevices
            .replaceAll('{communityId}', communityId!)
            .replaceAll('{projectId}', projectId!),
        expectedResponseModel: (json) {
          final spaceModels = (json['data'] as List)
              .map((spaceJson) => SpaceModel.fromJson(spaceJson))
              .toList();
          return spaceModels;
        },
      );
      return response;
    } catch (e) {
      debugPrint('Error fetching space hierarchy: $e');
      return [];
    }
  }

  static Future<List<SubSpaceModel>> getSubSpaceBySpaceId(
      {required String communityId,
      required String spaceId,
      required String projectId}) async {
    try {
      final path = ApiEndpoints.listSubspace
          .replaceFirst('{communityUuid}', communityId)
          .replaceFirst('{spaceUuid}', spaceId)
          .replaceAll('{projectUuid}', projectId);

      final response = await HTTPService().get(
        path: path,
        queryParameters: {"page": 1, "pageSize": 10},
        showServerMessage: false,
        expectedResponseModel: (json) {
          List<SubSpaceModel> rooms = [];
          if (json['data'] != null) {
            for (var subspace in json['data']) {
              rooms.add(SubSpaceModel.fromJson(subspace));
            }
          }
          return rooms;
        },
      );

      return response;
    } catch (error, stackTrace) {
      return [];
    }
  }

  static Future<Map<String, dynamic>> assignDeviceToRoom(
      {required String communityId,
      required String spaceId,
      required String subSpaceId,
      required String deviceId,
      required String projectId}) async {
    try {
      final response = await HTTPService().post(
        path: ApiEndpoints.assignDeviceToRoom
            .replaceAll('{projectUuid}', projectId)
            .replaceAll('{communityUuid}', communityId)
            .replaceAll('{spaceUuid}', spaceId)
            .replaceAll('{subSpaceUuid}', subSpaceId)
            .replaceAll('{deviceUuid}', deviceId),
        expectedResponseModel: (json) {
          return json;
        },
      );
      return response;
    } catch (e) {
      rethrow;
    }
  }
}
