using AyCode.Core;
using FruitBank.Common.Services;
using Mango.Nop.Core.Dtos;
using Mango.Nop.Core.Models;
using Nop.Core.Domain.Customers;

namespace FruitBank.Common.Models;

public class LoggedInModel
{
    private readonly ISecureCredentialService? _secureCredentialService;

    public bool IsLoggedIn => CustomerDto != null;
    public bool IsRevisor => IsLoggedIn && CustomerRoles.Any(x => x.SystemName.ToLowerInvariant() == "measuringrevisor");
    public bool IsAdministrator => IsLoggedIn && CustomerRoles.Any(x => x.SystemName.ToLowerInvariant() == "administrators");

    public bool IsDeveloper => IsAdministrator && (CustomerDto!.Email.Contains("@aycode.com") || CustomerDto!.Email.Contains("wsdservers@") ||
                                                   CustomerDto!.Email.Contains("@dsserver.com"));

    public CustomerDto? CustomerDto { get; private set; }
    public List<CustomerRole> CustomerRoles { get; private set; } = [];
    public List<CustomerDto> MeasuringUsers { get; set; } = [];

    public Func<string, string, Task<MgLoginModelResponse?>>? LoginFunc { get; set; }
    public Func<int, Task<List<CustomerRole>?>>? GetRolesFunc { get; set; }

    public LoggedInModel()
    {
    }

    public LoggedInModel(ISecureCredentialService secureCredentialService)
    {
        _secureCredentialService = secureCredentialService;
    }

    /// <summary>
    /// Tries to login - first checks if already logged in, then checks for stored credentials.
    /// Call this on app startup. Only attempts auto-login once per session.
    /// </summary>
    public async Task<bool> TryAutoLoginAsync()
    {
        if (IsLoggedIn) return IsLoggedIn;

        var credentials = await GetStoredCredentialsAsync();
        if (credentials == null) return IsLoggedIn;

        await LoginAsync(credentials.Email, credentials.Password, true);

        return IsLoggedIn;
    }

    /// <summary>
    /// Performs manual login with the provided credentials.
    /// </summary>
    public async Task<bool> LoginAsync(string email, string password, bool saveCredentials = true)
    {
        if (IsLoggedIn || LoginFunc == null) return IsLoggedIn;

        var loginResponse = await LoginFunc(email, password);

        if (loginResponse is { IsSuccesLogin: true })
        {
            await SetupLoggedInUser(loginResponse.CustomerDto!);

            if (saveCredentials)
            {
                await SaveCredentialsAsync(email, password);
            }
        }

        return IsLoggedIn;
    }

    /// <summary>
    /// Logs out the user and clears stored credentials.
    /// </summary>
    public async Task LogOutAsync()
    {
        await ClearCredentialsAsync();
        ClearCustomer();
    }

    public void SetCustomer(CustomerDto? customerDto)
    {
        ClearCustomer();
        if (customerDto != null) CustomerDto = customerDto;
    }

    public void SetCustomerRoles(List<CustomerRole> customerRoles)
    {
        CustomerRoles.Clear();
        CustomerRoles.AddRange(customerRoles);
    }

    public void ClearCustomer()
    {
        CustomerDto = null;
        CustomerRoles.Clear();
    }

    public void LogOut() => ClearCustomer();

    #region Credential Management

    public async Task<StoredCredentials?> GetStoredCredentialsAsync()
    {
        if (_secureCredentialService == null) return null;
        return await _secureCredentialService.GetCredentialsAsync();
    }

    public async Task SaveCredentialsAsync(string email, string password)
    {
        if (_secureCredentialService == null) return;
        await _secureCredentialService.SaveCredentialsAsync(email, password);
    }

    public async Task ClearCredentialsAsync()
    {
        if (_secureCredentialService == null) return;
        await _secureCredentialService.ClearCredentialsAsync();
    }

    #endregion

    #region Private Methods

    private async Task SetupLoggedInUser(CustomerDto customerDto)
    {
        SetCustomer(customerDto);

        if (GetRolesFunc != null)
        {
            var customerRoles = await GetRolesFunc(customerDto.Id);
            if (customerRoles != null)
            {
                SetCustomerRoles(customerRoles);
            }
        }
    }
    #endregion
}