using LSFE.MobApp.Contracts;
using LSFE.MobApp.Entities.Account;
using LSFE.MobApp.Models;
using LSFE.MobApp.Services;
using LSFE.MobApp.Services.Authentication;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Net.Http.Json;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace LSFE.MobApp.ViewModels.Authentication
{
    public class LoginVM : INotifyPropertyChanged
    {
        #region API client
        private readonly IApiClientFactory _apiClientFactory;
        private readonly IApiClient<Infrastructure.Dto.Admin.DeviceInfoDto> _checkDeviceApiClient;
        private readonly IApiClient<LoginRequest> _userApiClient;
        #endregion

        #region Properties
        private string _username;
        private string _password;
        private string _errorMessage;
        private bool _hasError;
        private bool _isLoading;
        private bool _rememberMe;
        private bool _isPasswordHidden = true;
        #endregion

        #region Services
        private readonly Services.INavigationService _navigationService;
        private readonly IDeviceInfoService _deviceInfoService;
        private readonly IRepository<User> _userRepository;
        private readonly ISyncService _syncService;
        #endregion

        private readonly IConfiguration _configuration;
        public LoginVM(IApiClientFactory apiClientFactory, 
            Services.INavigationService navigationService, IConfiguration configuration, 
            IRepository<User> userRepository,ISyncService syncService, IDeviceInfoService deviceInfoService)
        {
            _apiClientFactory = apiClientFactory;
            _navigationService = navigationService;
            _userRepository = userRepository;
            _syncService = syncService;
            _deviceInfoService = deviceInfoService;
            _configuration = configuration;
            _checkDeviceApiClient = apiClientFactory.CreateClient<Infrastructure.Dto.Admin.DeviceInfoDto>("Admin/CheckDevice");
            _userApiClient = apiClientFactory.CreateClient<LoginRequest>(_configuration["ApiSettings:Login"] ?? "AnonAccount/Login/");

            LoginCommand = new Command(async () => await LoginAsync(), () => CanLogin());
            ForgotPasswordCommand = new Command(async () => await NavigateToForgotPasswordAsync());
            ContactSupportCommand = new Command(async () => await ContactSupportAsync());
            TogglePasswordVisibilityCommand = new Command(TogglePasswordVisibility);
        }

        #region Properties
        public string UserName
        {
            get => _username;
            set
            {
                _username = value;
                OnPropertyChanged();
                ((Command)LoginCommand).ChangeCanExecute();
            }
        }

        public string Password
        {
            get => _password;
            set
            {
                _password = value;
                OnPropertyChanged();
                ((Command)LoginCommand).ChangeCanExecute();
            }
        }

        public string ErrorMessage
        {
            get => _errorMessage;
            set
            {
                _errorMessage = value;
                OnPropertyChanged();
            }
        }

        public bool HasError
        {
            get => _hasError;
            set
            {
                _hasError = value;
                OnPropertyChanged();
            }
        }

        public bool IsLoading
        {
            get => _isLoading;
            set
            {
                _isLoading = value;
                OnPropertyChanged();
            }
        }

        public bool IsPasswordHidden
        {
            get => _isPasswordHidden;
            set
            {
                _isPasswordHidden = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(PasswordIcon));
            }
        }

        public string PasswordIcon => IsPasswordHidden ? "\uf06e" : "\uf070"; // eye / eye-slash
        public bool RememberMe
        {
            get => _rememberMe;
            set
            {
                _rememberMe = value;
                OnPropertyChanged();
            }
        }
        #endregion

        #region Commands

        public ICommand LoginCommand { get; }
        public ICommand ForgotPasswordCommand { get; }
        public ICommand ContactSupportCommand { get; }
        public ICommand TogglePasswordVisibilityCommand { get; }

        #endregion

        #region Methods
        private bool CanLogin()
        {
            return !string.IsNullOrWhiteSpace(UserName) &&
                   !string.IsNullOrWhiteSpace(Password) &&
                   !IsLoading;
        }

        private async Task LoginAsync()
        {
            if (IsLoading) return;

            try
            {
                IsLoading = true;
                HasError = false;
                ErrorMessage = string.Empty;

                var loginRequest = new LoginRequest
                {
                    UserName = UserName,
                    Password = Password
                };

                var user = await _userRepository.GetAllAsync();
                if (user.Count > 0)
                {
                    var filtered = user.FirstOrDefault(u => u.UserName.ToLower() == loginRequest.UserName.ToLower()
                                    && u.Password == loginRequest.Password);
                    if (filtered == null) {
                        ShowError("This device has been registered with other medrep. Please contact your administrator.");
                    }
                    else if (!filtered.IsDeviceRegister)
                    {
                        ShowError("This device is not yet registered. Please contact your administrator.");
                    }
                    else
                    {
                        await SecureStorage.SetAsync("device_registered", "true");

                        var credResponse = new LoginResponse()
                        {
                            FullName = filtered.UserName,
                            UserId = filtered.UserId,
                            Company = filtered.Company,
                            EmployeeId = filtered.EmployeeId,
                            LockoutEnabled = filtered.LockoutEnabled,
                            Email = filtered.Email,
                            Password = loginRequest.Password,
                            UserName = filtered.UserName,
                            IsDeviceRegister = true,
                        };
                        // Store token securely
                        await UserCred.SetUserCred(credResponse);

                        await _navigationService.NavigateToMainPageAsync();
                    }
                }
                else//No record yet on local Users table
                {
                    // Get device information
                    var deviceInfo = await _deviceInfoService.GetDeviceInfoAsync();

                    //var deviceId = deviceInfo.DeviceId;
                    var device = new Infrastructure.Dto.Admin.DeviceInfoDto()
                    {
                        DeviceId = deviceInfo.DeviceId,
                        UserName = loginRequest.UserName
                    };

                    var checkDevice = await _checkDeviceApiClient.CreateAsync(device);

                    if (!checkDevice.Success)
                    {
                        ShowError("This device is not yet registered. Please contact your administrator.");
                    }
                    else
                    {
                        var response = await _userApiClient.LoginAsync(loginRequest);

                        if (response.Success)
                        {

                            response.Password = loginRequest.Password;
                            response.IsDeviceRegister = true;
                            await UserCred.SetUserCred(response);

                            var credResponse = new User()
                            {
                                FullName = response.UserName,
                                UserId = response.UserId,
                                Company = response.Company,
                                EmployeeId = response.EmployeeId,
                                LockoutEnabled = response.LockoutEnabled,
                                PhoneNumber=response.PhoneNumber,
                                Email = response.Email,
                                Password = loginRequest.Password,
                                UserName = response.UserName,
                                IsDeviceRegister = true
                            };

                            await _syncService.SyncPullUsersAsync(credResponse);

                            await _navigationService.NavigateToMainPageAsync();
                        }
                        else
                        {
                            if (!response.Success)
                            {
                                ShowError("Invalid username or password");
                            }
                            else
                            {
                                ShowError("Login failed. Please try again.");
                            }
                        }
                    }
                }
            }
            catch (HttpRequestException ex)
            {
                ShowError("Unable to connect to server. Check your internet connection.");
            }
            catch (Exception ex)
            {
                ShowError($"An error occurred: {ex.Message}");
            }
            finally
            {
                IsLoading = false;
            }
        }

        private async Task NavigateToForgotPasswordAsync()
        {
            await _navigationService.NavigateToForgotPasswordAsync();
        }

        private async Task ContactSupportAsync()
        {
            try
            {
                await Launcher.OpenAsync("rmsoriano@lloydlab.com?subject=Login Support");
            }
            catch (Exception ex)
            {
                ShowError("Unable to open support contact");
            }
        }

        private void TogglePasswordVisibility()
        {
            IsPasswordHidden = !IsPasswordHidden;
        }

        private void ShowError(string message)
        {
            ErrorMessage = message;
            HasError = true;
        }

        #endregion

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

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

        #endregion
    }
}
