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

namespace Managing.Application.ManageBot
{
    public class StartBotCommandHandler : IRequestHandler<StartBotCommand, BotStatus>
    {
        private readonly IAccountService _accountService;
        private readonly IGrainFactory _grainFactory;

        public StartBotCommandHandler(
            IAccountService accountService, IGrainFactory grainFactory)
        {
            _accountService = accountService;
            _grainFactory = grainFactory;
        }

        public async Task<BotStatus> Handle(StartBotCommand request, CancellationToken cancellationToken)
        {
            // Validate the configuration
            if (request.Config == null)
            {
                throw new ArgumentException("Bot configuration is required");
            }

            if (request.Config.Scenario == null || !request.Config.Scenario.Indicators.Any())
            {
                throw new InvalidOperationException(
                    "Scenario or indicators not loaded properly in constructor. This indicates a configuration error.");
            }

            if (request.Config.BotTradingBalance <= Constants.GMX.Config.MinimumPositionAmount)
            {
                throw new ArgumentException(
                    $"Bot trading balance must be greater than {Constants.GMX.Config.MinimumPositionAmount}");
            }

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

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

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

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

            try
            {
                var botGrain = _grainFactory.GetGrain<ILiveTradingBotGrain>(Guid.NewGuid());
                await botGrain.CreateAsync(request.Config, request.User);
                
                // Only start the bot if createOnly is false
                if (!request.CreateOnly)
                {
                    await botGrain.StartAsync();
                }
            }
            catch (Exception ex)
            {
                throw new Exception($"Failed to start bot: {ex.Message}, {ex.StackTrace}");
            }

            return request.CreateOnly ? BotStatus.Saved : BotStatus.Running;
        }
    }
}