using DbController.SqlServer;
using DbController;
using Microsoft.AspNetCore.Components;
using Tabletop.Core.Models;
using Tabletop.Core.Services;
using Microsoft.JSInterop;
using Microsoft.AspNetCore.Components.Forms;
using Tabletop.Core.Calculators;
using Tabletop.Core;

namespace Tabletop.Pages.Games
{
    public partial class GamePage
    {
        [Parameter]
        public int GameId { get; set; }
        public Game? Game { get; set; }

        #nullable disable
        [Inject] public IJSRuntime JSRuntime { get; set; }
        #nullable enable

        private User? _loggedInUser;

        public Player? Player { get; set; } //Input Model for Army Builder Modal

        protected EditForm? _formArmy;

        public int SelectedTemplate { get; set; }

        public bool PlayersReady { get; set; }
        public Player? PlayerModal { get; set; }
        public List<Template> Templates { get; set; } = [];

        protected override async Task OnParametersSetAsync()
        {
            _loggedInUser = await authService.GetUserAsync();

            using IDbController dbController = new SqlController(AppdataService.ConnectionString);
            Game = await gameService.GetAsync(GameId, dbController);

            if (_loggedInUser is not null && Game is not null)
            {
                _loggedInUser.Units = await UnitService.GetUserUnitsAsync(_loggedInUser.UserId, dbController);
                Templates = await TemplateService.GetTemplateOnForceAsync(_loggedInUser.UserId, dbController);
            }

            PlayersReady = false;

            await CheckPlayersAreReady();
        }

        protected async Task UpdateOrdersAsync(List<Player> player)
        {
            using IDbController dbController = new SqlController(AppdataService.ConnectionString);

            foreach (var item in player)
            {
                await playerService.UpdatePlayerOrderAsync(item, dbController);
            }
        }

        protected Task LoadTemplateAsync()
        {
            if (Player is not null)
            {
                var templateUnits = Templates.FirstOrDefault(x => x.TemplateId == SelectedTemplate)?.Units ?? [];

                Player.Units = [.. templateUnits.Select(unit => unit.DeepCopyByExpressionTree())];
            }

            return Task.CompletedTask;
        }

        protected async Task SaveArmyAsync()
        {
            if (_formArmy is null || _formArmy.EditContext is null || Player is null || Game is null)
            {
                return;
            }

            if (!await _formArmy.EditContext.ValidateAsync())
            {
                using IDbController dbController = new SqlController(AppdataService.ConnectionString);
                await dbController.StartTransactionAsync();
                try
                {
                    var InputUnitsToUpdate = Game.Players.FirstOrDefault(x => x.PlayerId == Player.PlayerId)?.Units;
                    InputUnitsToUpdate = Player.Units;

                    await playerService.UpdatePlayerArmyAsync(Player, dbController);
                    await dbController.CommitChangesAsync();
                }
                catch (Exception)
                {
                    await dbController.RollbackChangesAsync();
                    throw;
                }


                await JSRuntime.ShowToastAsync(ToastType.success, $"Save item");

                var InputToUpdate = Game?.Players.FirstOrDefault(x => x.PlayerId == Player.PlayerId);
                if (InputToUpdate != null)
                {
                    InputToUpdate.Units = Player.Units;
                    InputToUpdate.FractionId = Player.FractionId;
                }

                Player = null;
            }
        }

        private Task CheckPlayersAreReady()
        {
            if (Game is not null)
            {
                int count = 0;

                foreach (var player in Game.Players)
                {
                    if (player.Units.Count != 0)
                    {
                        count++;
                    }
                }

                if (Game.Players.Count == count && Game.Players.Count > 0)
                {
                    PlayersReady = true;
                }
            }

            return Task.CompletedTask;
        }

        private static async Task CalculateTotalForceAsync(Player Input)
        {
            if (Input is not null)
            {
                int totalForce = 0;

                foreach (var unit in Input.Units)
                {
                    int unitForce = await Calculation.ForceAsync(unit);
                    totalForce += unitForce * unit.Quantity;
                }
                Input.UsedForce = totalForce;
            }
        }

        private static async Task CalculateForceAsync(Player Input)
        {
            if (Input is not null)
            {
                foreach (var unit in Input.Units)
                {
                    int force = await Calculation.ForceAsync(unit);

                    unit.Force = force;
                    unit.ForceOfQuantity = force * unit.Quantity;
                }
            }
        }

        private static async Task CalculateArmyDataAsync(Player Input)
        {
            await CalculateForceAsync(Input);
            await CalculateTotalForceAsync(Input);
            await CountTotalUnitsAsync(Input);
        }

        private static Task CountTotalUnitsAsync(Player Input)
        {
            if (Input is not null)
            {
                int count = 0;

                foreach (Unit unit in Input.Units)
                {
                    count += unit.Quantity;
                }

                Input.TotalUnits = count;
            }

            return Task.CompletedTask;
        }
    }
}