import 'dart:io';

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:logger/logger.dart';
import 'package:sigap/src/features/auth/data/repositories/authentication_repository.dart';
import 'package:sigap/src/features/onboarding/presentasion/controllers/role_selection_controller.dart';
import 'package:sigap/src/features/personalization/data/models/index.dart';
import 'package:sigap/src/features/personalization/data/models/models/user_metadata_model.dart';
import 'package:sigap/src/features/personalization/data/repositories/roles_repository.dart';
import 'package:sigap/src/utils/constants/app_routes.dart';
import 'package:sigap/src/utils/helpers/network_manager.dart';
import 'package:sigap/src/utils/popups/loaders.dart';
import 'package:sigap/src/utils/validators/validation.dart';
import 'package:supabase_flutter/supabase_flutter.dart';

// Define the role types
enum RoleType { viewer, officer }

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

  // Variables
  final storage = GetStorage();
  final signupFormKey = GlobalKey<FormState>();
  final roleRepository = Get.find<RolesRepository>();

  // Role type (Viewer or Officer)
  final Rx<RoleType> roleType = RoleType.viewer.obs;

  // Controllers for signup form fields
  final emailController = TextEditingController();
  final passwordController = TextEditingController();
  final confirmPasswordController = TextEditingController();

  // Observable error messages
  final emailError = ''.obs;
  final passwordError = ''.obs;
  final confirmPasswordError = ''.obs;

  // Role related
  final RxList<RoleModel> availableRoles = <RoleModel>[].obs;
  final RxString selectedRoleId = ''.obs;
  final Rx<RoleModel?> selectedRole = Rx<RoleModel?>(null);

  // Observable states
  final isPasswordVisible = false.obs;
  final isConfirmPasswordVisible = false.obs;
  final privacyPolicy = false.obs;
  final isLoading = false.obs;
  final currentTabIndex = 0.obs;

  // Check if Apple Sign In is available (only on iOS)
  final RxBool isAppleSignInAvailable = RxBool(Platform.isIOS);

  @override
  void onClose() {
    emailController.dispose();
    passwordController.dispose();
    confirmPasswordController.dispose();
    super.onClose();
  }

  // Validators
  String? validateEmail(String? value) {
    final error = TValidators.validateEmail(value);
    emailError.value = error ?? '';
    return error;
  }

  String? validatePassword(String? value) {
    final error = TValidators.validatePassword(value);
    passwordError.value = error ?? '';
    return error;
  }

  String? validateConfirmPassword(String? value) {
    final error = TValidators.validateConfirmPassword(
      passwordController.text,
      value,
    );
    confirmPasswordError.value = error ?? '';
    return error;
  }

  // Toggle password visibility
  void togglePasswordVisibility() {
    isPasswordVisible.value = !isPasswordVisible.value;
  }

  // Toggle confirm password visibility
  void toggleConfirmPasswordVisibility() {
    isConfirmPasswordVisible.value = !isConfirmPasswordVisible.value;
  }

  // Validate signup form
  bool validateSignupForm() {
    if (!signupFormKey.currentState!.validate()) {
      return false;
    }

    // Check privacy policy
    if (!privacyPolicy.value) {
      TLoaders.warningSnackBar(
        title: 'Privacy Policy',
        message: 'Please accept the privacy policy to continue.',
      );
      return false;
    }

    return true;
  }

  // Sign up function
  /// Updated signup function with better error handling and argument passing
  void signUp() async {
    try {
      isLoading.value = true;
      Logger().i('SignUp process started');

      // Check network connection
      final isConnected = await NetworkManager.instance.isConnected();
      if (!isConnected) {
        TLoaders.errorSnackBar(
          title: 'No Internet Connection',
          message: 'Please check your internet connection and try again.',
        );
        return;
      }

      if (!signupFormKey.currentState!.validate()) {
        return;
      }

      // Check privacy policy
      if (!privacyPolicy.value) {
        TLoaders.warningSnackBar(
          title: 'Privacy Policy',
          message: 'Please accept the privacy policy to continue.',
        );
        return;
      }

      // Get selected role info before authentication

      final roleController = RoleSelectionController.instance;
      final isOfficer = roleController.isOfficer.value;
      final roleId = roleController.selectedRole.value!.id;

      Logger().i('Is officer: $isOfficer');

      // Validate role selection
      if (roleId.isEmpty) {
        TLoaders.errorSnackBar(
          title: 'Role Required',
          message: 'Please select a role before continuing.',
        );
        return;
      }

      // Create comprehensive initial user metadata
      final initialMetadata = UserMetadataModel(
        email: emailController.text.trim(),
        roleId: roleId,
        isOfficer: isOfficer,
        profileStatus: 'incomplete',
      );

      Logger().i('Initial metadata: ${initialMetadata.toJson()}');

      // Create the account
      final authResponse = await AuthenticationRepository.instance
          .initialSignUp(
            email: emailController.text.trim(),
            password: passwordController.text.trim(),
            initialData: initialMetadata,
          );

      // Validate response
      if (authResponse.session == null || authResponse.user == null) {
        TLoaders.errorSnackBar(
          title: 'Registration Failed',
          message: 'Failed to create account. Please try again.',
        );
        return;
      }

      final user = authResponse.user!;
      Logger().d('Account created successfully for user: ${user.id}');

      AuthenticationRepository.instance.screenRedirect();
    } catch (e) {
      Logger().e('Error during signup: $e');
      String errorMessage = _getReadableErrorMessage(e.toString());

      // Handle AuthException specifically
      if (e is AuthException && e.message.contains('email')) {
        emailError.value = 'Invalid email or already in use';
        errorMessage =
            'Email validation failed. Please check your email address.';
      }

      TLoaders.errorSnackBar(
        title: 'Registration Failed',
        message: errorMessage,
      );
    } finally {
      isLoading.value = false;
    }
  }

  // Sign in with Google
  Future<void> signInWithGoogle() async {
    try {
      isLoading.value = true;

      // Check network connection
      final isConnected = await NetworkManager.instance.isConnected();
      if (!isConnected) {
        TLoaders.errorSnackBar(
          title: 'No Internet Connection',
          message: 'Please check your internet connection and try again.',
        );
        return;
      }

      // Get selected role from local storage
      final roleController = RoleSelectionController.instance;
      final isOfficer = roleController.isOfficer.value;
      final roleId = roleController.selectedRole.value!.id;

      // Authenticate with Google
      final authResponse =
          await AuthenticationRepository.instance.signInWithGoogle();

      // Check if authResponse has a user property
      final userId = AuthenticationRepository.instance.currentUserId;

      if (userId == null) {
        throw Exception("Failed to authenticate. Please try again.");
      }

      // Create or update user metadata with role information
      final userMetadata = UserMetadataModel(
        isOfficer: isOfficer,
        roleId: roleId,
      );

      // Update user metadata in the database
      await AuthenticationRepository.instance.updateUserRoleOAuth(
        userId: userId,
        metadata: userMetadata,
      );

      // Navigate to registration form to complete profile
      Get.offNamed(
        AppRoutes.registrationForm,
        arguments: {
          'role': selectedRole.value,
          'userId': userId,
          'initialData': userMetadata,
        },
      );
    } catch (e) {
      Logger().e('Error during Google Sign-In: $e');
      TLoaders.errorSnackBar(
        title: 'Authentication Failed',
        message: e.toString(),
      );
    } finally {
      isLoading.value = false;
    }
  }

  // Sign in with Apple
  Future<void> signInWithApple() async {
    try {
      if (!Platform.isIOS) {
        TLoaders.warningSnackBar(
          title: 'Not Supported',
          message: 'Apple Sign-In is only available on iOS devices.',
        );
        return;
      }

      isLoading.value = true;

      // Check network connection
      final isConnected = await NetworkManager.instance.isConnected();
      if (!isConnected) {
        TLoaders.errorSnackBar(
          title: 'No Internet Connection',
          message: 'Please check your internet connection and try again.',
        );
        return;
      }

      final roleController = RoleSelectionController.instance;
      final isOfficer = roleController.isOfficer.value;
      final roleId = roleController.selectedRole.value!.id;

      // Authenticate with Apple
      final authResponse =
          await AuthenticationRepository.instance.signInWithApple();

      // Check if authResponse has a user property
      final userId = AuthenticationRepository.instance.currentUserId;

      if (userId == null) {
        throw Exception(
          "Failed to authenticate with Apple ID. Please try again.",
        );
      }

      // Create or update user metadata with role information
      final userMetadata = UserMetadataModel(
        isOfficer: isOfficer,
        roleId: roleId,
      );

      // Update user metadata in the database
      await AuthenticationRepository.instance.updateUserRoleOAuth(
        userId: userId,
        metadata: userMetadata,
      );

      // Navigate to registration form to complete profile
      Get.offNamed(
        AppRoutes.registrationForm,
        arguments: {
          'role': selectedRole.value,
          'userId': userId,
          'initialData': userMetadata,
        },
      );
    } catch (e) {
      Logger().e('Error during Apple Sign-In: $e');
      TLoaders.errorSnackBar(
        title: 'Authentication Failed',
        message: e.toString(),
      );
      // No redirection on error - user stays on current page
    } finally {
      isLoading.value = false;
    }
  }

  // Sign in with facebook
  Future<void> signInWithFacebook() async {
    try {
      isLoading.value = true;

      // Check network connection
      final isConnected = await NetworkManager.instance.isConnected();
      if (!isConnected) {
        TLoaders.errorSnackBar(
          title: 'No Internet Connection',
          message: 'Please check your internet connection and try again.',
        );
        return;
      }

      // Get selected role from local storage
      final roleController = RoleSelectionController.instance;
      final isOfficer = roleController.isOfficer.value;
      final roleId = roleController.selectedRole.value!.id;

      // Authenticate with Facebook
      final authResponse =
          await AuthenticationRepository.instance.signInWithFacebook();

      // Check if authResponse has a user property
      final userId = AuthenticationRepository.instance.currentUserId;

      if (userId == null) {
        throw Exception(
          "Failed to authenticate with Facebook. Please try again.",
        );
      }

      // Create or update user metadata with role information
      final userMetadata = UserMetadataModel(
        isOfficer: isOfficer,
        roleId: roleId,
      );

      // Update user metadata in the database
      await AuthenticationRepository.instance.updateUserRoleOAuth(
        userId: userId,
        metadata: userMetadata,
      );

      // Navigate to registration form to complete profile
      Get.offNamed(
        AppRoutes.registrationForm,
        arguments: {
          'role': selectedRole.value,
          'userId': userId,
          'initialData': userMetadata,
        },
      );
    } catch (e) {
      Logger().e('Error during Facebook Sign-In: $e');
      TLoaders.errorSnackBar(
        title: 'Authentication Failed',
        message: e.toString(),
      );
      // No redirection on error - user stays on current page
    } finally {
      isLoading.value = false;
    }
  }

  // Sign in with email and password
  Future<void> signInWithEmail() async {
    try {
      isLoading.value = true;

      // Check network connection
      final isConnected = await NetworkManager.instance.isConnected();
      if (!isConnected) {
        TLoaders.errorSnackBar(
          title: 'No Internet Connection',
          message: 'Please check your internet connection and try again.',
        );
        return;
      }

      // Get selected role from local storage
      final roleController = RoleSelectionController.instance;
      final isOfficer = roleController.isOfficer.value;
      final roleId = roleController.selectedRole.value!.id;

      // Authenticate with email and password
      final authResponse = await AuthenticationRepository.instance
          .signInWithEmailPassword(
            email: emailController.text.trim(),
            password: passwordController.text.trim(),
          );

      // Check if authResponse has a user property
      final userId = AuthenticationRepository.instance.currentUserId;

      if (userId == null) {
        throw Exception(
          "Failed to sign in with email. Please check your credentials and try again.",
        );
      }

      // Create or update user metadata with role information
      final userMetadata = UserMetadataModel(
        isOfficer: isOfficer,
        roleId: roleId,
      );

      // Update user metadata in the database
      await AuthenticationRepository.instance.updateUserRoleOAuth(
        userId: userId,
        metadata: userMetadata,
      );

      // Navigate to registration form to complete profile
      Get.offNamed(
        AppRoutes.emailVerification,
        arguments: {
          'role': selectedRole.value,
          'userId': userId,
          'initialData': userMetadata,
        },
      );
    } catch (e) {
      Logger().e('Error during Email Sign-In: $e');
      TLoaders.errorSnackBar(
        title: 'Authentication Failed',
        message: e.toString(),
      );
      // No redirection on error - user stays on current page
    } finally {
      isLoading.value = false;
    }
  }

  // Navigate to forgot password screen
  void goToForgotPassword() {
    Get.toNamed(AppRoutes.forgotPassword);
  }

  // Navigate to sign in screen
  void goToSignIn() {
    Get.offNamed(AppRoutes.signIn);
  }

  /// Convert technical error messages to user-friendly messages
  String _getReadableErrorMessage(String error) {
    if (error.contains('email')) {
      return 'Please check your email address and try again.';
    } else if (error.contains('password')) {
      return 'Password must be at least 6 characters long.';
    } else if (error.contains('network') || error.contains('connection')) {
      return 'Network error. Please check your connection and try again.';
    } else if (error.contains('already registered') ||
        error.contains('already exists')) {
      return 'This email is already registered. Please try signing in instead.';
    }
    return 'Registration failed. Please try again.';
  }
}
