using Managing.Application.Abstractions;
using Managing.Application.Abstractions.Services;
using Managing.Application.ManageBot.Commands;
using MediatR;
using static Managing.Common.Enums;

namespace Managing.Application.ManageBot
{
    public class StartBotCommandHandler : IRequestHandler<StartBotCommand, string>
    {
        private readonly IBotFactory _botFactory;
        private readonly IBotService _botService;
        private readonly IMoneyManagementService _moneyManagementService;
        private readonly IExchangeService _exchangeService;
        private readonly IAccountService _accountService;

        public StartBotCommandHandler(IBotFactory botFactory, IBotService botService,
            IMoneyManagementService moneyManagementService, IExchangeService exchangeService,
            IAccountService accountService)
        {
            _botFactory = botFactory;
            _botService = botService;
            _moneyManagementService = moneyManagementService;
            _exchangeService = exchangeService;
            _accountService = accountService;
        }

        public async Task<string> Handle(StartBotCommand request, CancellationToken cancellationToken)
        {
            BotStatus botStatus = BotStatus.Down;

            var account = await _accountService.GetAccount(request.AccountName, true, true);

            if (account == null)
            {
                throw new Exception($"Account {request.AccountName} not found");
            }

            var usdcBalance = account.Balances.FirstOrDefault(b => b.TokenName == Ticker.USDC.ToString());

            if (usdcBalance == null || usdcBalance.Value < request.InitialTradingBalance)
            {
                throw new Exception($"Account {request.AccountName} has no USDC balance or not enough balance");
            }

            var moneyManagement =
                await _moneyManagementService.GetMoneyMangement(request.User, request.MoneyManagementName);
            switch (request.BotType)
            {
                case BotType.SimpleBot:
                    var bot = _botFactory.CreateSimpleBot(request.Name, null);
                    _botService.AddSimpleBotToCache(bot);
                    return bot.GetStatus();
                case BotType.ScalpingBot:
                    var sBot = _botFactory.CreateScalpingBot(request.AccountName, moneyManagement, request.Name,
                        request.Ticker, request.Scenario, request.Timeframe, request.IsForWatchingOnly,
                        request.InitialTradingBalance);
                    _botService.AddTradingBotToCache(sBot);
                    return sBot.GetStatus();
                case BotType.FlippingBot:
                    var fBot = _botFactory.CreateFlippingBot(request.AccountName, moneyManagement, request.Name,
                        request.Ticker, request.Scenario, request.Timeframe, request.IsForWatchingOnly,
                        request.InitialTradingBalance);
                    _botService.AddTradingBotToCache(fBot);
                    return fBot.GetStatus();
            }

            return botStatus.ToString();
        }
    }
}