using Blazor.Pagination;
using DbController;
using DbController.SqlServer;
using Microsoft.AspNetCore.Components;
using Tabletop.Core;
using Tabletop.Core.Calculators;
using Tabletop.Core.Filters;
using Tabletop.Core.Models;
using Tabletop.Core.Services;

namespace Tabletop.Pages.Tools
{
    public partial class ArmyBuilder : IHasPagination
    {
        private int _page = 1;
        private User? _loggedInUser;
        public TemplateFilter Filter { get; set; } = new();

        public Unit? SelectedUnit { get; set; }
        public int Page { get => _page; set => _page = value < 1 ? 1 : value; }
        public int TotalItems { get; set; }
        public bool OpenFilter { get; set; }
        public bool ShowArmy { get; set; }

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

            if (_loggedInUser != null)
            {
                using IDbController dbController = new SqlController(AppdataService.ConnectionString);
                _loggedInUser.Units = await UnitService.GetUserUnitsAsync(_loggedInUser.UserId, dbController);

                OpenFilter = false;
                ShowArmy = false;

                Filter = new()
                {
                    Limit = AppdataService.PageLimit,
                    UserId = _loggedInUser.UserId
                };
            }

            await LoadAsync();
        }

        protected override async Task SaveAsync()
        {
            if (Input is null)
            {
                return;
            }

            Input.Units.RemoveAll(unit => unit.Quantity == 0);

            await base.SaveAsync();
            await LoadAsync();
        }

        public async Task LoadAsync(bool navigateToPage1 = false)
        {
            Filter.PageNumber = navigateToPage1 ? 1 : Page;
            using IDbController dbController = new SqlController(AppdataService.ConnectionString);
            TotalItems = await Service.GetTotalAsync(Filter, dbController);
            Data = await Service.GetAsync(Filter, dbController);
        }

        protected override async Task DeleteAsync()
        {
            await base.DeleteAsync();
            await LoadAsync();
        }

        protected override async Task EditAsync(Template input)
        {
            await base.EditAsync(input);
            await CalculateTotalForceAsync();
            await CalculateTotalCountAsync();
            await CalculateForceAsync();
        }

        protected override Task NewAsync()
        {
            if (_loggedInUser != null)
            {
                Input = new Template
                {
                    UserId = _loggedInUser.UserId
                };
            }

            return Task.CompletedTask;
        }

        private async Task CalculateTotalForceAsync()
        {
            int totalForce = 0;
            if (Input is not null)
            {
                foreach (var unit in Input.Units)
                {
                    int unitForce = await Calculation.ForceAsync(unit);
                    totalForce += unitForce * unit.Quantity;
                }
                Input.UsedForce = totalForce;
            }
        }

        private async Task CalculateForceAsync()
        {
            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 Task ClearUnitsAsync()
        {
            if (Input is not null)
            {
                Input.Units.Clear();
                Input.UsedForce = 0;
                Input.TotalUnits = 0;
            }

            return Task.CompletedTask;
        }

        private Task<int> CalculateTotalCountAsync()
        {
            if (Input != null)
            {
                Input.TotalUnits = Input.Units.Sum(unit => unit.Quantity);
            }
            return Task.FromResult(0);
        }
    }
}