using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Repositories;
using Managing.Domain.MoneyManagements;
using Managing.Domain.Users;
using Microsoft.Extensions.Logging;

namespace Managing.Application.MoneyManagements;

public class MoneyManagementService : IMoneyManagementService
{
    private readonly ISettingsRepository _settingsRepository;
    private readonly ILogger<MoneyManagementService> _logger;

    public MoneyManagementService(
        ILogger<MoneyManagementService> logger,
        ISettingsRepository settingsRepository)
    {
        _logger = logger;
        _settingsRepository = settingsRepository;
    }

    public async Task<MoneyManagement> CreateOrUpdateMoneyManagement(User user, MoneyManagement request)
    {
        // Try to get user-specific strategy first
        var moneyManagement = await _settingsRepository.GetMoneyManagementByUser(user, request.Name);

        // Fall back to regular lookup if user-specific endpoint is not implemented
        if (moneyManagement == null)
        {
            moneyManagement = await _settingsRepository.GetMoneyManagement(request.Name);

            // If found by name but doesn't belong to this user, treat as new
            if (moneyManagement != null && moneyManagement.User?.Name != user.Name)
            {
                moneyManagement = null;
            }
        }

        if (moneyManagement == null)
        {
            request.User = user;
            await _settingsRepository.InsertMoneyManagement(request);
            return request;
        }
        else
        {
            // Additional check to ensure user's ownership
            if (moneyManagement.User?.Name != user.Name)
            {
                throw new UnauthorizedAccessException(
                    "You do not have permission to update this money management strategy.");
            }

            moneyManagement.StopLoss = request.StopLoss;
            moneyManagement.TakeProfit = request.TakeProfit;
            moneyManagement.Leverage = request.Leverage;
            moneyManagement.Timeframe = request.Timeframe;
            moneyManagement.User = user;

            _settingsRepository.UpdateMoneyManagement(moneyManagement);
            return moneyManagement;
        }
    }

    public async Task<MoneyManagement> GetMoneyMangement(string name)
    {
        return await _settingsRepository.GetMoneyManagement(name);
    }

    public IEnumerable<MoneyManagement> GetMoneyMangements(User user)
    {
        try
        {
            // Try to use user-specific repository method first
            return _settingsRepository.GetMoneyManagementsByUser(user);
        }
        catch
        {
            // Fall back to filtering if user-specific endpoint is not implemented
            return _settingsRepository.GetMoneyManagements()
                .Where(mm => mm.User?.Name == user.Name);
        }
    }

    public async Task<MoneyManagement> GetMoneyMangement(User user, string name)
    {
        MoneyManagement moneyManagement;

        try
        {
            // Try to use user-specific repository method first
            moneyManagement = await _settingsRepository.GetMoneyManagementByUser(user, name);
        }
        catch
        {
            // Fall back to regular lookup if user-specific endpoint is not implemented
            moneyManagement = await _settingsRepository.GetMoneyManagement(name);

            // Filter by user
            if (moneyManagement != null && moneyManagement.User?.Name != user.Name)
            {
                moneyManagement = null;
            }
        }

        return moneyManagement;
    }

    public bool DeleteMoneyManagement(User user, string name)
    {
        try
        {
            try
            {
                // Try to use user-specific repository method first
                _settingsRepository.DeleteMoneyManagementByUser(user, name);
            }
            catch
            {
                // Fall back to verifying user ownership before deletion
                var moneyManagement = _settingsRepository.GetMoneyManagement(name).Result;

                if (moneyManagement != null && moneyManagement.User?.Name != user.Name)
                {
                    throw new UnauthorizedAccessException(
                        "You do not have permission to delete this money management strategy.");
                }

                _settingsRepository.DeleteMoneyManagement(name);
            }

            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex.Message);
            return false;
        }
    }

    public bool DeleteMoneyManagements(User user)
    {
        try
        {
            try
            {
                // Try to use user-specific repository method first
                _settingsRepository.DeleteMoneyManagementsByUser(user);
            }
            catch
            {
                // This fallback is not ideal as it would delete all money managements regardless of user
                // In a real implementation, we would need a filtered repository method
                _logger.LogWarning(
                    "DeleteMoneyManagementsByUser not implemented, cannot delete user-specific money managements");
            }

            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex.Message);
            return false;
        }
    }
}