import 'package:supabase_flutter/supabase_flutter.dart';
import 'package:tugas_akhir_supabase/screens/community/models/group.dart';
import 'package:tugas_akhir_supabase/screens/community/models/group_member.dart';

class GroupManagementService {
  final _supabase = Supabase.instance.client;

  // Get current user ID
  String? get currentUserId => _supabase.auth.currentUser?.id;

  // Check if the current user is an admin
  Future<bool> isUserAdmin() async {
    if (currentUserId == null) return false;

    try {
      final response =
          await _supabase
              .from('user_roles')
              .select('role')
              .eq('user_id', currentUserId!)
              .maybeSingle();

      if (response == null) return false;
      return response['role'] == 'admin';
    } catch (e) {
      print('[ERROR] Failed to check if user is admin: $e');
      return false;
    }
  }

  // Get all groups (admin only)
  Future<List<Group>> getAllGroups() async {
    print('[DEBUG] Starting getAllGroups()');
    final bool isAdmin = await isUserAdmin();
    print('[DEBUG] isUserAdmin result: $isAdmin');

    if (!isAdmin) {
      print('[ERROR] Unauthorized access to admin function');
      return [];
    }

    try {
      print('[DEBUG] Fetching groups from database...');
      final response = await _supabase
          .from('groups')
          .select('*, group_members(count)')
          .order('created_at');

      print('[DEBUG] Raw response from groups query: $response');

      if (response.isEmpty) {
        print('[DEBUG] No groups found in response');
        return [];
      }

      final List<Group> groups = [];

      for (final item in response) {
        print('[DEBUG] Processing group: ${item['name']} (${item['id']})');
        final memberCount = item['group_members']?[0]?['count'] ?? 0;
        final groupData = Map<String, dynamic>.from(item);
        groupData['member_count'] = memberCount;

        final group = Group.fromMap(groupData);
        groups.add(group);
      }

      print('[DEBUG] Returned ${groups.length} groups');
      return groups;
    } catch (e) {
      print('[ERROR] Failed to load all groups: $e');
      return [];
    }
  }

  // Create a new group (admin only)
  Future<Group?> createGroup(Group group) async {
    if (!await isUserAdmin()) {
      print('[ERROR] Unauthorized access to admin function');
      return null;
    }

    try {
      // Insert group dengan id dari group parameter
      final response =
          await _supabase
              .from('groups')
              .insert({
                'id': group.id,
                'name': group.name,
                'description': group.description,
                'created_by': group.createdBy,
                'created_at': group.createdAt.toIso8601String(),
                'is_default': group.isDefault,
                'is_public': group.isPublic,
                'icon_url': group.iconUrl,
              })
              .select('id')
              .single();

      print('[INFO] Group created successfully: ${response['id']}');

      // Ensure we use the ID from response in case it's different
      final createdGroupId = response['id'] as String;

      // Add creator as admin member
      final member = GroupMember(
        groupId: createdGroupId,
        userId: currentUserId!,
        role: 'admin',
      );

      await _supabase.from('group_members').insert(member.toMap());

      // Return group with proper ID
      return group.copyWith(id: createdGroupId);
    } catch (e) {
      print('[ERROR] Failed to create group: $e');
      return null;
    }
  }

  // Update an existing group (admin only)
  Future<bool> updateGroup(Group group) async {
    if (!await isUserAdmin()) {
      print('[ERROR] Unauthorized access to admin function');
      return false;
    }

    try {
      await _supabase.from('groups').update(group.toMap()).eq('id', group.id);

      return true;
    } catch (e) {
      print('[ERROR] Failed to update group: $e');
      return false;
    }
  }

  // Delete a group (admin only)
  Future<bool> deleteGroup(String groupId) async {
    if (!await isUserAdmin()) {
      print('[ERROR] Unauthorized access to admin function');
      return false;
    }

    try {
      // Check if this is the default group
      final response =
          await _supabase
              .from('groups')
              .select('is_default')
              .eq('id', groupId)
              .single();

      if (response['is_default'] == true) {
        // Cannot delete default group
        return false;
      }

      // Delete group members first (due to foreign key constraints)
      await _supabase.from('group_members').delete().eq('group_id', groupId);

      // Delete the group
      await _supabase.from('groups').delete().eq('id', groupId);

      return true;
    } catch (e) {
      print('[ERROR] Failed to delete group: $e');
      return false;
    }
  }

  // Get all members of a group (admin only)
  Future<List<GroupMemberDetail>> getGroupMembers(String groupId) async {
    if (!await isUserAdmin()) {
      print('[ERROR] Unauthorized access to admin function');
      return [];
    }

    try {
      final response = await _supabase
          .from('group_members')
          .select('*, profiles:user_id(username, avatar_url, email)')
          .eq('group_id', groupId)
          .eq('is_active', true)
          .order('joined_at');

      final List<GroupMemberDetail> members = [];

      for (final item in response) {
        final member = GroupMember.fromMap(item);
        final profile = item['profiles'] as Map<String, dynamic>?;

        members.add(
          GroupMemberDetail(
            member: member,
            username: profile?['username'] as String? ?? 'Unknown User',
            email: profile?['email'] as String?,
            avatarUrl: profile?['avatar_url'] as String?,
          ),
        );
      }

      return members;
    } catch (e) {
      print('[ERROR] Failed to load group members: $e');
      return [];
    }
  }

  // Remove a user from a group (admin only)
  Future<bool> removeGroupMember(String groupId, String userId) async {
    if (!await isUserAdmin()) {
      print('[ERROR] Unauthorized access to admin function');
      return false;
    }

    try {
      // Mark as inactive instead of deleting
      await _supabase
          .from('group_members')
          .update({'is_active': false})
          .eq('group_id', groupId)
          .eq('user_id', userId);

      return true;
    } catch (e) {
      print('[ERROR] Failed to remove group member: $e');
      return false;
    }
  }

  // Change a member's role (admin only)
  Future<bool> changeGroupMemberRole(
    String groupId,
    String userId,
    String newRole,
  ) async {
    if (!await isUserAdmin()) {
      print('[ERROR] Unauthorized access to admin function');
      return false;
    }

    // Validate role
    if (!['admin', 'moderator', 'member'].contains(newRole)) {
      print('[ERROR] Invalid role: $newRole');
      return false;
    }

    try {
      await _supabase
          .from('group_members')
          .update({'role': newRole})
          .eq('group_id', groupId)
          .eq('user_id', userId);

      return true;
    } catch (e) {
      print('[ERROR] Failed to change member role: $e');
      return false;
    }
  }

  // Add all users to a default group (admin only)
  Future<bool> addAllUsersToDefaultGroup(String defaultGroupId) async {
    if (!await isUserAdmin()) {
      print('[ERROR] Unauthorized access to admin function');
      return false;
    }

    try {
      // Cara langsung menggunakan RPC untuk menghindari masalah RLS
      final result = await _supabase.rpc(
        'add_all_users_to_group',
        params: {'group_id_param': defaultGroupId},
      );

      print('[INFO] Added users to default group: $result');
      return result == true;
    } catch (e) {
      print('[ERROR] Failed to add all users to default group: $e');

      // Fallback jika RPC tidak tersedia
      try {
        // Get all user IDs
        final usersResponse = await _supabase
            .from('profiles')
            .select('user_id');

        // Get existing members of the group
        final membersResponse = await _supabase
            .from('group_members')
            .select('user_id')
            .eq('group_id', defaultGroupId);

        final existingMemberIds =
            membersResponse.map((m) => m['user_id'] as String).toSet();

        // Create members for users who aren't already in the group
        final List<Map<String, dynamic>> newMembers = [];

        for (final user in usersResponse) {
          final userId = user['user_id'] as String;
          if (!existingMemberIds.contains(userId)) {
            newMembers.add(
              GroupMember(groupId: defaultGroupId, userId: userId).toMap(),
            );
          }
        }

        if (newMembers.isNotEmpty) {
          await _supabase.from('group_members').insert(newMembers);
        }

        print(
          '[INFO] Added ${newMembers.length} users to default group (fallback method)',
        );
        return true;
      } catch (fallbackError) {
        print('[ERROR] Fallback method also failed: $fallbackError');
        return false;
      }
    }
  }

  // Create a new group (admin only) menggunakan RPC
  Future<Group?> createGroupViaRPC({
    required String name,
    required String description,
    required bool isPublic,
    required bool isDefault,
    String? iconUrl,
  }) async {
    if (currentUserId == null) {
      print('[ERROR] User not authenticated');
      return null;
    }

    try {
      // Panggil fungsi RPC di database
      final response = await _supabase.rpc(
        'create_group_with_creator',
        params: {
          'name': name,
          'description': description,
          'created_by': currentUserId,
          'is_public': isPublic,
          'is_default': isDefault,
          'icon_url': iconUrl,
        },
      );

      print('[INFO] Group created via RPC: $response');

      if (response != null) {
        // Buat objek Group dari hasil
        final createdGroup = Group(
          id: response as String,
          name: name,
          description: description,
          createdBy: currentUserId!,
          isPublic: isPublic,
          isDefault: isDefault,
          iconUrl: iconUrl,
        );

        return createdGroup;
      }

      return null;
    } catch (e) {
      print('[ERROR] Failed to create group via RPC: $e');
      return null;
    }
  }
}

// Helper class for group member details
class GroupMemberDetail {
  final GroupMember member;
  final String username;
  final String? email;
  final String? avatarUrl;

  GroupMemberDetail({
    required this.member,
    required this.username,
    this.email,
    this.avatarUrl,
  });
}
