using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Services;
using Managing.Domain.MoneyManagements;
using Managing.Domain.Users;
using Microsoft.Extensions.Logging;
using static Managing.Common.Enums;

namespace Managing.Application.Shared;

public class SettingsService : ISettingsService
{
    private readonly IMoneyManagementService _moneyManagementService;
    private readonly IScenarioService _scenarioService;
    private readonly IBacktester _backtester;
    private readonly ILogger<SettingsService> _logger;

    public SettingsService(IMoneyManagementService moneyManagementService,
        IScenarioService scenarioService,
        IBacktester backtester,
        ILogger<SettingsService> logger)
    {
        _moneyManagementService = moneyManagementService;
        _scenarioService = scenarioService;
        _backtester = backtester;
        _logger = logger;
    }

    public async Task<bool> ResetSettings()
    {
        if (!_backtester.DeleteBacktests())
        {
            throw new Exception("Cannot delete all backtests");
        }

        if (!await SetupSettings())
        {
            throw new Exception("Cannot setup settings");
        }

        return await Task.FromResult(true);
    }

    public async Task<bool> SetupSettings()
    {
        try
        {
            // SetupMoneyManagementsSeed(Timeframe.FiveMinutes);
            // SetupMoneyManagementsSeed(Timeframe.FifteenMinutes);
            // SetupMoneyManagementsSeed(Timeframe.OneHour);
            // SetupMoneyManagementsSeed(Timeframe.OneDay);
            await SetupScenariosSeed();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex.Message);
            return false;
        }

        return true;
    }

    // private async void SetupMoneyManagementsSeed(Timeframe timeframe)
    // {
    //     var moneyManagement = new MoneyManagement()
    //     {
    //         Timeframe = timeframe,
    //         BalanceAtRisk = 0.05m,
    //         Leverage = 1,
    //         StopLoss = 0.021m,
    //         TakeProfit = 0.042m,
    //         Name = $"{timeframe}-MediumRisk",
    //     };
    //
    //     await _moneyManagementService.CreateOrUpdateMoneyManagement(moneyManagement);
    // }

    private async Task SetupScenariosSeed()
    {
        await SetupMacd();
        await SetupRsiDiv();
        await SetupRsiDivConfirm();
        await SetupSuperTrend();
        await SetupChandelierExit();
        await SetupStochRsiTrend();
        await SetupStochSTCTrend();
        await SetupEmaTrend();
        await SetupEmaCross();
    }

    private async Task SetupStochSTCTrend()
    {
        var name = "STCTrend";
        var strategy = await _scenarioService.CreateIndicatorForUser(null, IndicatorType.Stc,
            name,
            fastPeriods: 23,
            slowPeriods: 50,
            cyclePeriods: 10);
        await _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private async Task SetupMacd()
    {
        var name = "MacdCross";
        var strategy = await _scenarioService.CreateIndicatorForUser(null, IndicatorType.MacdCross,
            name,
            fastPeriods: 12,
            slowPeriods: 26,
            signalPeriods: 9);
        await _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private async Task SetupRsiDiv()
    {
        var name = "RsiDiv6";
        var strategy = await _scenarioService.CreateIndicatorForUser(null, IndicatorType.RsiDivergence,
            name,
            period: 6);
        await _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private async Task SetupRsiDivConfirm()
    {
        var name = "RsiDivConfirm6";
        var strategy = await _scenarioService.CreateIndicatorForUser(null, IndicatorType.RsiDivergenceConfirm,
            name,
            period: 6);
        await _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private async Task SetupSuperTrend()
    {
        var name = "SuperTrend";
        var strategy = await _scenarioService.CreateIndicatorForUser(null, IndicatorType.SuperTrend,
            name,
            period: 10,
            multiplier: 3);
        await _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private async Task SetupChandelierExit()
    {
        var name = "ChandelierExit";
        var strategy = await _scenarioService.CreateIndicatorForUser(null, IndicatorType.ChandelierExit,
            name,
            period: 22,
            multiplier: 3);
        await _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private async Task SetupStochRsiTrend()
    {
        var name = "StochRsiTrend";
        var strategy = await _scenarioService.CreateIndicatorForUser(null, IndicatorType.StochRsiTrend,
            name,
            period: 14,
            stochPeriods: 14,
            signalPeriods: 3,
            smoothPeriods: 1);
        await _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private async Task SetupEmaTrend()
    {
        var name = "Ema200Trend";
        var strategy = await _scenarioService.CreateIndicatorForUser(null, IndicatorType.EmaTrend,
            name,
            period: 200);
        await _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private async Task SetupEmaCross()
    {
        var name = "Ema200Cross";
        var strategy = await _scenarioService.CreateIndicatorForUser(null, IndicatorType.EmaCross,
            name,
            period: 200);
        await _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    public async Task<bool> CreateDefaultConfiguration(User user)
    {
        try
        {
            if (user == null)
                throw new ArgumentNullException(nameof(user), "User cannot be null");

            // Create default Money Management
            var defaultMoneyManagement = new MoneyManagement
            {
                Name = "Personal-Hourly",
                Timeframe = Timeframe.OneHour,
                StopLoss = 2, // 2%
                TakeProfit = 4, // 4%
                Leverage = 1,
                User = user
            };

            // Format the percentage values correctly 
            defaultMoneyManagement.FormatPercentage();

            await _moneyManagementService.CreateOrUpdateMoneyManagement(user, defaultMoneyManagement);

            // Create default Strategy (StcTrend)
            var defaultStrategy = await _scenarioService.CreateIndicatorForUser(
                user,
                IndicatorType.Stc,
                "Stc",
                period: null,
                fastPeriods: 23,
                slowPeriods: 50,
                null,
                null,
                cyclePeriods: 10
            );

            // Create default Scenario containing the strategy
            var strategyNames = new List<string> { defaultStrategy.Name };
            var defaultScenario = await _scenarioService.CreateScenarioForUser(
                user,
                "STC Scenario",
                strategyNames
            );

            return true;
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error creating default configuration");
            return false;
        }
    }
}