import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sigap/src/features/daily-ops/data/models/models/officers_model.dart';
import 'package:sigap/src/features/personalization/data/models/models/profile_model.dart';
import 'package:sigap/src/features/personalization/data/models/models/users_model.dart';
import 'package:sigap/src/features/personalization/data/repositories/officers_repository.dart';
import 'package:sigap/src/features/personalization/data/repositories/profile_repository.dart';
import 'package:sigap/src/features/personalization/data/repositories/users_repository.dart';
import 'package:sigap/src/features/personalization/presentasion/controllers/profile/base_profile_controller.dart';

class ProfileController extends BaseProfileController {
  // Repositories using Get.find() instead of direct initialization
  final UserRepository _userRepository = Get.find<UserRepository>();
  final ProfileRepository _profileRepository = Get.find<ProfileRepository>();
  final OfficerRepository _officerRepository = Get.find<OfficerRepository>();

  // Observable state variables
  final Rx<UserModel?> user = Rx<UserModel?>(null);
  final Rx<ProfileModel?> profile = Rx<ProfileModel?>(null);
  final Rx<OfficerModel?> officer = Rx<OfficerModel?>(null);
  final RxBool isOfficer = false.obs;
  final RxBool isInitialized = false.obs;
  final RxBool isEditMode = false.obs;
  final RxBool isFetching = false.obs; // Track initial data loading

  // Form controllers for edit mode
  late TextEditingController firstNameController;
  late TextEditingController lastNameController;
  late TextEditingController bioController;
  late TextEditingController phoneController;
  late TextEditingController birthPlaceController;
  late Rx<DateTime?> birthDate = Rx<DateTime?>(null);

  // Original data for comparison
  ProfileModel? originalProfile;
  
  @override
  void onInit() {
    super.onInit();
    
    // Initialize text controllers
    firstNameController = TextEditingController();
    lastNameController = TextEditingController();
    bioController = TextEditingController();
    phoneController = TextEditingController();
    birthPlaceController = TextEditingController();
    
    // Load initial data
    loadData();
  }

  @override
  void onClose() {
    // Dispose controllers
    firstNameController.dispose();
    lastNameController.dispose();
    bioController.dispose();
    phoneController.dispose();
    birthPlaceController.dispose();
    super.onClose();
  }

  // Load data from repositories
  @override
  Future<void> loadData() async {
    await fetchUserProfile();
    if (isEditMode.value) {
      _loadDataToFormFields();
    }
  }
  
  // Reload profile data
  Future<void> refreshProfile() async {
    await fetchUserProfile();
  }

  // Fetch the user profile data
  Future<void> fetchUserProfile() async {
    try {
      isFetching.value = true; // Start fetching
      setLoading(true);
      clearError();

      // Check if user is an officer
      isOfficer.value = await _userRepository.isCurrentUserOfficer();

      // Fetch the appropriate data based on the user type
      if (isOfficer.value) {
        await fetchOfficerData();
      } else {
        await fetchRegularUserData();
      }

      isInitialized.value = true;
    } catch (e) {
      setError('Failed to load profile: ${e.toString()}');
      showError(
        'Profile Error',
        'Could not load profile data. ${e.toString()}',
      );
    } finally {
      setLoading(false);
      isFetching.value = false; // Done fetching
    }
  }

  // Fetch data for regular users
  Future<void> fetchRegularUserData() async {
    try {
      // Get user and profile data
      final userData = await _userRepository.getCurrentUserData();
      user.value = userData;
      
      // If profile exists in user data, use it
      if (userData.profile != null) {
        profile.value = userData.profile;
        originalProfile = userData.profile;
      } else {
        // Otherwise, fetch profile separately
        final profileData = await _profileRepository.getProfileData();
        profile.value = profileData;
        originalProfile = profileData;
      }
    } catch (e) {
      setError('Failed to load user data: ${e.toString()}');
    }
  }

  // Fetch data for officers
  Future<void> fetchOfficerData() async {
    try {
      // Get officer data
      final officerData = await _officerRepository.getOfficerData();
      officer.value = officerData;
      
      // Get additional user data
      final userData = await _userRepository.getCurrentUserData();
      user.value = userData;
      profile.value = userData.profile;
      originalProfile = userData.profile;
    } catch (e) {
      setError('Failed to load officer data: ${e.toString()}');
    }
  }
  
  // Toggle edit mode
  void toggleEditMode() {
    isEditMode.value = !isEditMode.value;
    if (isEditMode.value) {
      _loadDataToFormFields();
    } else {
      hasChanges.value = false;
    }
  }
  
  // Load current data into form fields
  void _loadDataToFormFields() {
    if (profile.value != null) {
      firstNameController.text = profile.value!.firstName ?? '';
      lastNameController.text = profile.value!.lastName ?? '';
      bioController.text = profile.value!.bio ?? '';
      birthPlaceController.text = profile.value!.placeOfBirth ?? '';
      birthDate.value = profile.value!.birthDate;
    }

    if (user.value != null) {
      phoneController.text = user.value!.phone ?? '';
    }
    
    // Setup listeners to track changes
    _setupTextChangeListeners();
  }
  
  // Setup listeners for text controllers to track changes
  void _setupTextChangeListeners() {
    void onTextChanged() {
      _checkForChanges();
    }
    
    firstNameController.addListener(onTextChanged);
    lastNameController.addListener(onTextChanged);
    bioController.addListener(onTextChanged);
    phoneController.addListener(onTextChanged);
    birthPlaceController.addListener(onTextChanged);
  }
  
  // Check for changes in form data
  void _checkForChanges() {
    if (profile.value == null) {
      hasChanges.value = false;
      return;
    }
    
    // Check profile fields
    bool profileChanged =
        firstNameController.text != (profile.value!.firstName ?? '') ||
        lastNameController.text != (profile.value!.lastName ?? '') ||
        bioController.text != (profile.value!.bio ?? '') ||
        birthPlaceController.text != (profile.value!.placeOfBirth ?? '') ||
        birthDate.value != profile.value!.birthDate;
      
    // Check phone
    bool phoneChanged = false;
    if (user.value != null) {
      phoneChanged = phoneController.text != (user.value!.phone ?? '');
    }
    
    hasChanges.value = profileChanged || phoneChanged;
  }
  
  // Set birth date
  void setBirthDate(DateTime? date) {
    birthDate.value = date;
    _checkForChanges();
  }
  
  // Fetch profile by user ID
  Future<void> fetchProfileByUserId(String userId) async {
    try {
      isFetching.value = true;
      setLoading(true);
      clearError();

      // Get user data
      final userData = await _userRepository.getUserById(userId);
      user.value = userData;
      profile.value = userData.profile;
      originalProfile = userData.profile;

      // Check if user is an officer
      final isUserOfficer = userData.isOfficer;
      isOfficer.value = isUserOfficer;

      // If user is an officer, fetch officer data
      if (isUserOfficer) {
        try {
          final officerData = await _officerRepository.getOfficerById(userId);
          officer.value = officerData;
        } catch (e) {
          // Handle case when officer data doesn't exist yet
          officer.value = null;
        }
      }

      isInitialized.value = true;
    } catch (e) {
      setError('Failed to load profile: ${e.toString()}');
      showError(
        'Profile Error',
        'Could not load user profile. ${e.toString()}',
      );
    } finally {
      setLoading(false);
      isFetching.value = false;
    }
  }

  // Upload avatar
  Future<String?> uploadAvatar(String imagePath) async {
    try {
      setLoading(true);
      final avatarUrl = await _profileRepository.uploadAvatar(imagePath);
      await refreshProfile(); // Reload profile to get the new avatar
      return avatarUrl;
    } catch (e) {
      setError('Failed to upload avatar: ${e.toString()}');
      showError(
        'Upload Failed',
        'Could not upload profile picture. ${e.toString()}',
      );
      return null;
    } finally {
      setLoading(false);
    }
  }
  
  // Save changes
  @override
  Future<bool> saveChanges() async {
    if (!formKey.currentState!.validate()) {
      return false;
    }
    
    try {
      setLoading(true);
      
      // Update profile data
      if (profile.value != null) {
        final updatedProfile = profile.value!.copyWith(
          firstName: firstNameController.text.trim(),
          lastName: lastNameController.text.trim(),
          bio: bioController.text.trim(),
          placeOfBirth: birthPlaceController.text.trim(),
          birthDate: birthDate.value,
        );
        
        await _profileRepository.updateProfile(updatedProfile);
        profile.value = updatedProfile;
      }
      
      // Update phone if changed
      final phone = phoneController.text.trim();
      if (user.value != null && phone != user.value!.phone) {
        await _userRepository.updateUserPhone(phone);
      }
      
      await refreshProfile();
      hasChanges.value = false;
      isEditMode.value = false;
      showSuccess('Success', 'Profile updated successfully');
      return true;
    } catch (e) {
      setError('Failed to save changes: ${e.toString()}');
      showError('Error', 'Could not save profile changes. ${e.toString()}');
      return false;
    } finally {
      setLoading(false);
    }
  }
  
  // Discard changes
  @override
  void discardChanges() {
    _loadDataToFormFields();
    hasChanges.value = false;
    isEditMode.value = false;
  }
}
