import 'package:get/get.dart';
import 'package:logger/Logger.dart';
import 'package:sigap/src/cores/services/supabase_service.dart';
import 'package:sigap/src/features/auth/data/models/permissions_model.dart';
import 'package:sigap/src/utils/exceptions/exceptions.dart';
import 'package:supabase_flutter/supabase_flutter.dart';

class PermissionsRepository extends GetxController {
  static PermissionsRepository get instance => Get.find();

  final _supabase = SupabaseService.instance.client;
  final _logger = Get.find<Logger>();

  // Get all permissions
  Future<List<PermissionModel>> getAllPermissions() async {
    try {
      final permissions = await _supabase
          .from('permissions')
          .select('*, resource(*), role(*)')
          .order('action');

      return (permissions as List)
          .map((permission) => PermissionModel.fromJson(permission))
          .toList();
    } on PostgrestException catch (error) {
      _logger.e('PostgrestException in getAllPermissions: ${error.message}');
      throw TExceptions.fromCode(error.code ?? 'unknown-error');
    } catch (e) {
      _logger.e('Exception in getAllPermissions: $e');
      throw 'Failed to fetch permissions: ${e.toString()}';
    }
  }

  // Get permissions by role ID
  Future<List<PermissionModel>> getPermissionsByRole(String roleId) async {
    try {
      final permissions = await _supabase
          .from('permissions')
          .select('*, resource(*), role(*)')
          .eq('role_id', roleId);

      return (permissions as List)
          .map((permission) => PermissionModel.fromJson(permission))
          .toList();
    } on PostgrestException catch (error) {
      _logger.e('PostgrestException in getPermissionsByRole: ${error.message}');
      throw TExceptions.fromCode(error.code ?? 'unknown-error');
    } catch (e) {
      _logger.e('Exception in getPermissionsByRole: $e');
      throw 'Failed to fetch role permissions: ${e.toString()}';
    }
  }

  // Get permissions by resource ID
  Future<List<PermissionModel>> getPermissionsByResource(
    String resourceId,
  ) async {
    try {
      final permissions = await _supabase
          .from('permissions')
          .select('*, resource(*), role(*)')
          .eq('resource_id', resourceId);

      return (permissions as List)
          .map((permission) => PermissionModel.fromJson(permission))
          .toList();
    } on PostgrestException catch (error) {
      _logger.e(
        'PostgrestException in getPermissionsByResource: ${error.message}',
      );
      throw TExceptions.fromCode(error.code ?? 'unknown-error');
    } catch (e) {
      _logger.e('Exception in getPermissionsByResource: $e');
      throw 'Failed to fetch resource permissions: ${e.toString()}';
    }
  }

  // Check if the current user has a specific permission
  Future<bool> checkPermission({
    required String action,
    required String resourceName,
  }) async {
    try {
      // Get current user's role ID
      final user = _supabase.auth.currentUser;
      if (user == null) return false;

      final userData =
          await _supabase
              .from('users')
              .select('roles_id')
              .eq('id', user.id)
              .single();

      final roleId = userData['roles_id'] as String;

      // Get resource ID by name
      final resourceData =
          await _supabase
              .from('resources')
              .select('id')
              .eq('name', resourceName)
              .single();

      final resourceId = resourceData['id'] as String;

      // Check if permission exists
      final permissions = await _supabase
          .from('permissions')
          .select()
          .eq('role_id', roleId)
          .eq('resource_id', resourceId)
          .eq('action', action);

      return (permissions as List).isNotEmpty;
    } on PostgrestException catch (error) {
      _logger.e('PostgrestException in checkPermission: ${error.message}');
      // If no rows found, return false instead of throwing an exception
      if (error.code == 'PGRST116') return false;
      throw TExceptions.fromCode(error.code ?? 'unknown-error');
    } catch (e) {
      _logger.e('Exception in checkPermission: $e');
      return false; // Default to no permission on error
    }
  }

  // Create a new permission
  Future<PermissionModel> createPermission({
    required String action,
    required String resourceId,
    required String roleId,
  }) async {
    try {
      final data = {
        'action': action,
        'resource_id': resourceId,
        'role_id': roleId,
      };

      final createdPermission =
          await _supabase
              .from('permissions')
              .insert(data)
              .select('*, resource(*), role(*)')
              .single();

      return PermissionModel.fromJson(createdPermission);
    } on PostgrestException catch (error) {
      _logger.e('PostgrestException in createPermission: ${error.message}');
      throw TExceptions.fromCode(error.code ?? 'unknown-error');
    } catch (e) {
      _logger.e('Exception in createPermission: $e');
      throw 'Failed to create permission: ${e.toString()}';
    }
  }

  // Delete a permission
  Future<void> deletePermission(String permissionId) async {
    try {
      await _supabase.from('permissions').delete().eq('id', permissionId);
    } on PostgrestException catch (error) {
      _logger.e('PostgrestException in deletePermission: ${error.message}');
      throw TExceptions.fromCode(error.code ?? 'unknown-error');
    } catch (e) {
      _logger.e('Exception in deletePermission: $e');
      throw 'Failed to delete permission: ${e.toString()}';
    }
  }
}
