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 (!_scenarioService.DeleteScenarios())
        {
            throw new Exception("Cannot delete scenarios");
        }

        if (!_scenarioService.DeleteStrategies())
        {
            throw new Exception("Cannot delete all strategies");
        }


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

        return await Task.FromResult(true);
    }

    public bool SetupSettings()
    {
        try
        {
            // SetupMoneyManagementsSeed(Timeframe.FiveMinutes);
            // SetupMoneyManagementsSeed(Timeframe.FifteenMinutes);
            // SetupMoneyManagementsSeed(Timeframe.OneHour);
            // SetupMoneyManagementsSeed(Timeframe.OneDay);
            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 void SetupScenariosSeed()
    {
        SetupMacd();
        SetupRsiDiv();
        SetupRsiDivConfirm();
        SetupSuperTrend();
        SetupChandelierExit();
        SetupStochRsiTrend();
        SetupStochSTCTrend();
        SetupEmaTrend();
        SetupEmaCross();
    }

    private void SetupStochSTCTrend()
    {
        var name = "STCTrend";
        var strategy = _scenarioService.CreateStrategy(StrategyType.Stc,
            name,
            fastPeriods: 23,
            slowPeriods: 50,
            cyclePeriods: 10);
        _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private void SetupMacd()
    {
        var name = "MacdCross";
        var strategy = _scenarioService.CreateStrategy(StrategyType.MacdCross,
            name,
            fastPeriods: 12,
            slowPeriods: 26,
            signalPeriods: 9);
        _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private void SetupRsiDiv()
    {
        var name = "RsiDiv6";
        var strategy = _scenarioService.CreateStrategy(StrategyType.RsiDivergence,
            name,
            period: 6);
        _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private void SetupRsiDivConfirm()
    {
        var name = "RsiDivConfirm6";
        var strategy = _scenarioService.CreateStrategy(StrategyType.RsiDivergenceConfirm,
            name,
            period: 6);
        _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private void SetupSuperTrend()
    {
        var name = "SuperTrend";
        var strategy = _scenarioService.CreateStrategy(StrategyType.SuperTrend,
            name,
            period: 10,
            multiplier: 3);
        _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private void SetupChandelierExit()
    {
        var name = "ChandelierExit";
        var strategy = _scenarioService.CreateStrategy(StrategyType.ChandelierExit,
            name,
            period: 22,
            multiplier: 3);
        _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private void SetupStochRsiTrend()
    {
        var name = "StochRsiTrend";
        var strategy = _scenarioService.CreateStrategy(StrategyType.StochRsiTrend,
            name,
            period: 14,
            stochPeriods: 14,
            signalPeriods: 3,
            smoothPeriods: 1);
        _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private void SetupEmaTrend()
    {
        var name = "Ema200Trend";
        var strategy = _scenarioService.CreateStrategy(StrategyType.EmaTrend,
            name,
            period: 200);
        _scenarioService.CreateScenario(name, new List<string> { strategy.Name });
    }

    private void SetupEmaCross()
    {
        var name = "Ema200Cross";
        var strategy = _scenarioService.CreateStrategy(StrategyType.EmaCross,
            name,
            period: 200);
        _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 = _scenarioService.CreateStrategyForUser(
                user,
                StrategyType.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 = _scenarioService.CreateScenarioForUser(
                user,
                "STC Scenario",
                strategyNames
            );

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