import 'package:flutter/services.dart';
import 'package:get/get.dart';
import 'package:logger/logger.dart';
import 'package:sigap/src/features/auth/data/repositories/authentication_repository.dart';
import 'package:sigap/src/features/daily-ops/data/models/models/officers_model.dart';
import 'package:sigap/src/utils/exceptions/exceptions.dart';
import 'package:sigap/src/utils/exceptions/format_exceptions.dart';
import 'package:sigap/src/utils/exceptions/platform_exceptions.dart';
import 'package:supabase_flutter/supabase_flutter.dart';

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

  final _supabase = Supabase.instance.client;

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

  // Get officer data
  Future<OfficerModel> getOfficerData() async {
    try {
      if (currentUserId == null) {
        throw 'User not authenticated';
      }

      final officerData =
          await _supabase
              .from('officers')
              .select(
                '*, roles(*), units:unit_id(*), patrol_units:patrol_unit_id(*)',
              )
              .eq('id', currentUserId!)
              .single();

      return OfficerModel.fromJson(officerData);
    } on PostgrestException catch (error) {
      throw TExceptions.fromCode(error.code!);
    } on FormatException catch (_) {
      throw const TFormatException();
    } on PlatformException catch (e) {
      throw TPlatformException(e.code).message;
    } catch (e) {
      throw 'Failed to fetch officer data: ${e.toString()}';
    }
  }

  // Update officer profile
  Future<OfficerModel?> updateOfficer(OfficerModel officer) async {
    try {
      if (currentUserId == null) {
        throw 'User not authenticated';
      }

      final data = officer.toJson();

      final updatedOfficer =
          await _supabase
              .from('officers')
              .update(data)
              .eq('id', currentUserId!)
              .select()
              .maybeSingle();

      if (updatedOfficer == null) {
        return null;
      }

      Logger().i('Officer updated successfully: $updatedOfficer');

      // updatedOfficer is a List, so we take the first item and convert it
      return OfficerModel.fromJson(updatedOfficer);
    } on PostgrestException catch (error) {
      throw TExceptions.fromCode(error.code!);
    } on AuthException catch (e) {
      throw TExceptions(e.message);
    } on FormatException catch (_) {
      throw const TFormatException();
    } on PlatformException catch (e) {
      throw TPlatformException(e.code).message;
    } catch (e) {
      throw 'Failed to update officer profile: ${e.toString()}';
    }
  }

  // Get officer by ID
  Future<OfficerModel> getOfficerById(String officerId) async {
    try {
      final officerData =
          await _supabase
              .from('officers')
              .select(
                '*, roles(*), units:unit_id(*), patrol_units:patrol_unit_id(*)',
              )
              .eq('id', officerId)
              .single();

      Logger().i('Fetched officer data: $officerData');

      return OfficerModel.fromJson(officerData);
    } on PostgrestException catch (error) {
      throw TExceptions.fromCode(error.code!);
    } catch (e) {
      throw 'Failed to fetch officer data: ${e.toString()}';
    }
  }

  // Convert regular user to officer
  Future<void> convertToOfficer(OfficerModel officer) async {
    try {
      if (currentUserId == null) {
        throw 'User not authenticated';
      }

      final authRepository = Get.put(AuthenticationRepository());

      // Prepare officer data
      final officerData = {
        'unit_id': officer.unitId,
        'nrp': officer.nrp,
        'name': officer.name,
        'rank': officer.rank ?? '',
        'position': officer.position ?? '',
        'phone': officer.phone ?? '',
        'email': officer.email ?? '',
      };

      // Update user metadata with officer flag and data
      await authRepository.updateUserRole(
        isOfficer: true,
        officerData: officerData,
      );
    } on PostgrestException catch (error) {
      throw TExceptions.fromCode(error.code!);
    } on AuthException catch (e) {
      throw TExceptions(e.message);
    } catch (e) {
      throw 'Failed to convert to officer: ${e.toString()}';
    }
  }

  // Convert officer to regular user
  Future<void> convertToRegularUser() async {
    try {
      if (currentUserId == null) {
        throw 'User not authenticated';
      }

      final authRepository = Get.put(AuthenticationRepository());

      // Update user metadata to remove officer flag
      await authRepository.updateUserRole(isOfficer: false);
    } on PostgrestException catch (error) {
      throw TExceptions.fromCode(error.code!);
    } on AuthException catch (e) {
      throw TExceptions(e.message);
    } catch (e) {
      throw 'Failed to convert to regular user: ${e.toString()}';
    }
  }
}
