using LightlessSync.API.Data.Enum;
using LightlessSync.API.Dto.User;
using LightlessSync.PlayerData.Pairs;
using LightlessSync.Services.Mediator;
using LightlessSync.Services.ServerConfiguration;
using LightlessSync.UI.Models;
using Microsoft.Extensions.Logging;
using LightlessSync.WebAPI;

namespace LightlessSync.PlayerData.Factories;

public class PairFactory
{
    private readonly PairLedger _pairLedger;
    private readonly ILoggerFactory _loggerFactory;
    private readonly LightlessMediator _lightlessMediator;
    private readonly Lazy<ServerConfigurationManager> _serverConfigurationManager;
    private readonly Lazy<ApiController> _apiController;

    public PairFactory(
        ILoggerFactory loggerFactory,
        PairLedger pairLedger,
        LightlessMediator lightlessMediator,
        Lazy<ServerConfigurationManager> serverConfigurationManager,
        Lazy<ApiController> apiController)
    {
        _loggerFactory = loggerFactory;
        _pairLedger = pairLedger;
        _lightlessMediator = lightlessMediator;
        _serverConfigurationManager = serverConfigurationManager;
        _apiController = apiController;
    }

    public Pair Create(UserFullPairDto userPairDto)
    {
        return CreateInternal(userPairDto);
    }

    public Pair Create(UserPairDto userPairDto)
    {
        var full = new UserFullPairDto(
            userPairDto.User,
            userPairDto.IndividualPairStatus,
            new List<string>(),
            userPairDto.OwnPermissions,
            userPairDto.OtherPermissions);

        return CreateInternal(full);
    }

    public Pair? Create(PairDisplayEntry entry)
    {
        var dto = new UserFullPairDto(
            entry.User,
            entry.PairStatus ?? IndividualPairStatus.None,
            entry.Groups.Select(g => g.Group.GID).Distinct(StringComparer.Ordinal).ToList(),
            entry.SelfPermissions,
            entry.OtherPermissions);

        return CreateInternal(dto);
    }

    public Pair? Create(PairUniqueIdentifier ident)
    {
        if (!_pairLedger.TryGetEntry(ident, out var entry) || entry is null)
        {
            return null;
        }

        return Create(entry);
    }

    private Pair CreateInternal(UserFullPairDto dto)
    {
        return new Pair(
            _loggerFactory.CreateLogger<Pair>(),
            dto,
            _pairLedger,
            _lightlessMediator,
            _serverConfigurationManager.Value,
            _apiController);
    }
}
