using LSFE.MobApp.Services;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using System.Net.Http.Json;
using System.Diagnostics;
using LSFE.MobApp.Contracts;
using LSFE.Infrastructure.Model.Admin;

namespace LSFE.MobApp.ViewModels.Admin
{
    public class DeviceRegistrationVM : INotifyPropertyChanged
    {
        private readonly IApiClientFactory _apiClientFactory;
        private readonly IDeviceInfoService _deviceInfoService;
        private readonly Services.INavigationService _navigationService;

        private string _adminPassword;
        private string _adminUsername;
        private string _medRepUsername;
        private string _medRepPassword;
        private string _currentDeviceId;
        private string _currentDeviceModel;
        private string _currentDevicePlatform;
        private string _authErrorMessage;
        private string _registrationErrorMessage;
        private string _registeredUsername;
        private string _registeredDeviceModel;

        private bool _showAuthenticationForm = true;
        private bool _showRegistrationForm = false;
        private bool _showSuccessMessage = false;
        private bool _hasAuthError = false;
        private bool _hasRegistrationError = false;
        private bool _isAdminPasswordHidden = true;
        private bool _isMedRepPasswordHidden = true;
        private bool _isRegistering = false;
        private bool _isVerifying = false;
        private readonly IApiClient<DeviceRegistrationRequest> _deviceRegistrationApiClient;
        private readonly IApiClient<AdminVerificationRequest> _adminVerifyApiClient;
        public DeviceRegistrationVM(IApiClientFactory apiClientFactory, IDeviceInfoService deviceInfoService, 
            Services.INavigationService navigationService)
        {
            _apiClientFactory = apiClientFactory; 
            _deviceInfoService = deviceInfoService;
            _navigationService = navigationService;
            _deviceRegistrationApiClient= apiClientFactory.CreateClient<DeviceRegistrationRequest>("Admin/RegisterDevice");
            _adminVerifyApiClient = apiClientFactory.CreateClient<AdminVerificationRequest>("Admin/VerifyAdmin");

            VerifyAdminCommand = new Command(async () => await VerifyAdminAsync(), () => CanVerifyAdmin());
            RegisterDeviceCommand = new Command(async () => await RegisterDeviceAsync(), () => CanRegisterDevice());
            ToggleAdminPasswordVisibilityCommand = new Command(ToggleAdminPasswordVisibility);
            ToggleMedRepPasswordVisibilityCommand = new Command(ToggleMedRepPasswordVisibility);
            ResetFormCommand = new Command(ResetForm);
        }

        #region Properties

        public string AdminPassword
        {
            get => _adminPassword;
            set
            {
                _adminPassword = value;
                OnPropertyChanged();
                ((Command)VerifyAdminCommand).ChangeCanExecute();
            }
        }
        public string AdminUserName
        {
            get => _adminUsername;
            set
            {
                _adminUsername = value;
                OnPropertyChanged();
                ((Command)VerifyAdminCommand).ChangeCanExecute();
            }
        }
        public string MedRepUsername
        {
            get => _medRepUsername;
            set
            {
                _medRepUsername = value;
                OnPropertyChanged();
                ((Command)RegisterDeviceCommand).ChangeCanExecute();
            }
        }

        public string MedRepPassword
        {
            get => _medRepPassword;
            set
            {
                _medRepPassword = value;
                OnPropertyChanged();
                ((Command)RegisterDeviceCommand).ChangeCanExecute();
            }
        }

        public string CurrentDeviceId
        {
            get => _currentDeviceId;
            set
            {
                _currentDeviceId = value;
                OnPropertyChanged();
            }
        }

        public string CurrentDeviceModel
        {
            get => _currentDeviceModel;
            set
            {
                _currentDeviceModel = value;
                OnPropertyChanged();
            }
        }

        public string CurrentDevicePlatform
        {
            get => _currentDevicePlatform;
            set
            {
                _currentDevicePlatform = value;
                OnPropertyChanged();
            }
        }

        public string AuthErrorMessage
        {
            get => _authErrorMessage;
            set
            {
                _authErrorMessage = value;
                OnPropertyChanged();
            }
        }

        public string RegistrationErrorMessage
        {
            get => _registrationErrorMessage;
            set
            {
                _registrationErrorMessage = value;
                OnPropertyChanged();
            }
        }

        public string RegisteredUsername
        {
            get => _registeredUsername;
            set
            {
                _registeredUsername = value;
                OnPropertyChanged();
            }
        }

        public string RegisteredDeviceModel
        {
            get => _registeredDeviceModel;
            set
            {
                _registeredDeviceModel = value;
                OnPropertyChanged();
            }
        }

        public bool ShowAuthenticationForm
        {
            get => _showAuthenticationForm;
            set
            {
                _showAuthenticationForm = value;
                OnPropertyChanged();
            }
        }

        public bool ShowRegistrationForm
        {
            get => _showRegistrationForm;
            set
            {
                _showRegistrationForm = value;
                OnPropertyChanged();
            }
        }

        public bool ShowSuccessMessage
        {
            get => _showSuccessMessage;
            set
            {
                _showSuccessMessage = value;
                OnPropertyChanged();
            }
        }

        public bool HasAuthError
        {
            get => _hasAuthError;
            set
            {
                _hasAuthError = value;
                OnPropertyChanged();
            }
        }

        public bool HasRegistrationError
        {
            get => _hasRegistrationError;
            set
            {
                _hasRegistrationError = value;
                OnPropertyChanged();
            }
        }

        public bool IsAdminPasswordHidden
        {
            get => _isAdminPasswordHidden;
            set
            {
                _isAdminPasswordHidden = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(AdminPasswordIcon));
            }
        }

        public bool IsMedRepPasswordHidden
        {
            get => _isMedRepPasswordHidden;
            set
            {
                _isMedRepPasswordHidden = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(MedRepPasswordIcon));
            }
        }
        public bool IsRegistering
        {
            get => _isRegistering;
            set
            {
                _isRegistering = value;
                OnPropertyChanged();
                ((Command)RegisterDeviceCommand).ChangeCanExecute();
            }
        }
        public bool IsVerifying
        {
            get => _isVerifying;
            set
            {
                _isVerifying = value;
                OnPropertyChanged();
                ((Command)VerifyAdminCommand).ChangeCanExecute();
            }
        }
      
        public string AdminPasswordIcon => IsAdminPasswordHidden ? "\uf070" : "\uf06e";
        public string MedRepPasswordIcon => IsMedRepPasswordHidden ? "\uf070" : "\uf06e";

        #endregion

        #region Commands

        public ICommand VerifyAdminCommand { get; }
        public ICommand RegisterDeviceCommand { get; }
        public ICommand ToggleAdminPasswordVisibilityCommand { get; }
        public ICommand ToggleMedRepPasswordVisibilityCommand { get; }
        public ICommand ResetFormCommand { get; }

        #endregion

        #region Methods
        private async void LoadCurrentDeviceInfoAsync()
        {
            try
            {
                var deviceInfo = await _deviceInfoService.GetDeviceInfoAsync();
                CurrentDeviceId = deviceInfo.DeviceId;
                CurrentDeviceModel = deviceInfo.DeviceModel;
                CurrentDevicePlatform = deviceInfo.Platform;
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Error loading device info: {ex.Message}");
                CurrentDeviceId = "Error loading device ID";
                CurrentDeviceModel = "Unknown";
                CurrentDevicePlatform = "Unknown";
            }
        }

        private bool CanVerifyAdmin()
        {
            return !string.IsNullOrWhiteSpace(AdminPassword);
        }

        private async Task VerifyAdminAsync()
        {
            try
            {
                HasAuthError = false;
                AuthErrorMessage = string.Empty;
                IsVerifying = true;
                // Call API to verify admin password
                var verifyRequest = new AdminVerificationRequest
                {
                    AdminPassword = AdminPassword,
                    AdminUserName = AdminUserName,
                };

                var response = await _adminVerifyApiClient.CreateAsync(verifyRequest);

                if (response.Success)
                {
                    LoadCurrentDeviceInfoAsync();
                    ShowAuthenticationForm = false;
                    ShowRegistrationForm = true;
                }
                else
                    ShowAuthError($"{response.Message}" ?? "Admin verification failed. You are not authorized to register this device.");
            }
            catch (HttpRequestException)
            {
                ShowAuthError("Unable to connect to server. Check your internet connection.");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Admin verification error: {ex.Message}");
                ShowAuthError($"An error occurred: {ex.Message}");
            }
            finally
            {
                IsVerifying = false;
            }
        }

        private bool CanRegisterDevice()
        {
            return !string.IsNullOrWhiteSpace(MedRepUsername) &&
                   !string.IsNullOrWhiteSpace(MedRepPassword) &&
                   !IsRegistering;
        }

        private async Task RegisterDeviceAsync()
        {
            if (IsRegistering) return;

            try
            {
                IsRegistering = true;
                HasRegistrationError = false;
                RegistrationErrorMessage = string.Empty;

                // Get full device information
                var deviceInfo = await _deviceInfoService.GetDeviceInfoAsync();

                // Create registration request
                var registrationRequest = new DeviceRegistrationRequest
                {
                    MedRepUsername = MedRepUsername,
                    MedRepPassword = MedRepPassword,
                    DeviceId = deviceInfo.DeviceId,
                    DeviceModel = deviceInfo.DeviceModel,
                    DevicePlatform = deviceInfo.Platform,
                    DeviceVersion = deviceInfo.Version,
                    DeviceManufacturer = deviceInfo.Manufacturer,
                    AppVersion = AppInfo.Current.VersionString
                };

                // Call API to register device
                var response = await _deviceRegistrationApiClient.CreateAsync(registrationRequest);

                if (response != null && response.Success)
                {
                    // Registration successful
                    RegisteredUsername = MedRepUsername;
                    RegisteredDeviceModel = CurrentDeviceModel;

                    ShowRegistrationForm = false;
                    ShowSuccessMessage = true;

                    // Clear sensitive data
                    AdminPassword = string.Empty;
                    MedRepPassword = string.Empty;
                }
                else
                {
                    ShowRegistrationError("Registration failed. Please verify the MedRep username and password.");
                }                
            }
            catch (HttpRequestException)
            {
                ShowRegistrationError("Unable to connect to server. Check your internet connection.");
            }
            catch (Exception ex)
            {
                // Debug.WriteLine($"Device registration error: {ex.Message}");
                ShowRegistrationError("Registration failed. Please verify the MedRep username and password.");
            }
            finally
            {
                IsRegistering = false;
            }
        }

        private void ToggleAdminPasswordVisibility()
        {
            IsAdminPasswordHidden = !IsAdminPasswordHidden;
        }

        private void ToggleMedRepPasswordVisibility()
        {
            IsMedRepPasswordHidden = !IsMedRepPasswordHidden;
        }

        private void ResetForm()
        {
            ShowSuccessMessage = false;
            ShowAuthenticationForm = true;
            ShowRegistrationForm = false;

            AdminPassword = string.Empty;
            AdminUserName = string.Empty;
            MedRepUsername = string.Empty;
            MedRepPassword = string.Empty;

            HasAuthError = false;
            HasRegistrationError = false;
            AuthErrorMessage = string.Empty;
            RegistrationErrorMessage = string.Empty;

            _navigationService.NavigateToLoginPageAsync();
        }

        private void ShowAuthError(string message)
        {
            AuthErrorMessage = message;
            HasAuthError = true;
        }

        private void ShowRegistrationError(string message)
        {
            RegistrationErrorMessage = message;
            HasRegistrationError = true;
        }

        #endregion

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion
    }
}