using Tabletop.Core.Constants;
using Tabletop.Core.Models;
using Tabletop.Core.Services;

namespace Tabletop.Core.Calculators
{
    public class Calculation
    {
        public static async Task<int> ForceAsync(Unit unit)
        {
            double unitForce = unit.Defense * 25 + unit.Moving * 5;
            double primaryWeaponForce = 0;
            double secondaryWeaponForce = 0;

            unit.PrimaryWeapon = AppdataService.Weapons.FirstOrDefault(x => x.WeaponId == unit.PrimaryWeaponId)?.DeepCopyByExpressionTree();
            unit.SecondaryWeapon = AppdataService.Weapons.FirstOrDefault(x => x.WeaponId == unit.SecondaryWeaponId)?.DeepCopyByExpressionTree();
            unit.FirstAbility = AppdataService.Abilities.FirstOrDefault(x => x.AbilityId == unit.FirstAbilityId)?.DeepCopyByExpressionTree();
            unit.SecondAbility = AppdataService.Abilities.FirstOrDefault(x => x.AbilityId == unit.SecondAbilityId)?.DeepCopyByExpressionTree();

            if (unit.PrimaryWeapon != null)
            {
                primaryWeaponForce = unit.PrimaryWeapon.Attack * (unit.PrimaryWeapon.Quality + (unit.FirstAbility?.Quality ?? 0) + (unit.SecondAbility?.Quality ?? 0)) * (unit.PrimaryWeapon.Range / 10) * unit.PrimaryWeapon.Dices;
            }

            if (unit.SecondaryWeapon != null)
            {
                secondaryWeaponForce = (unit.SecondaryWeapon.Attack * unit.SecondaryWeapon.Quality + (unit.FirstAbility?.Quality ?? 0) + (unit.SecondAbility?.Quality ?? 0)) * (unit.SecondaryWeapon.Range / 10) * unit.SecondaryWeapon.Dices;
            }

            return await Task.FromResult(Convert.ToInt32(Math.Round((unitForce + primaryWeaponForce + secondaryWeaponForce) / 25) + (unit.FirstAbility?.Force ?? 0) + (unit.SecondAbility?.Force ?? 0)));
        }

        public static Task<double> RandomNumberAsync()
        {
            Random random = new();
            double r = random.Next(1, 9);

            return Task.FromResult(r);
        }

        public static async Task<double> ProbabilityAsync(int attackerId, int defenderId, CoverTypes cover)
        {
            var (value0, value1) = await AttackValueTranslatorAsync(AppdataService.Weapons.FirstOrDefault(x => x.WeaponId == AppdataService.Units.FirstOrDefault(x => x.UnitId == attackerId)?.PrimaryWeaponId)?.Attack ?? 0, AppdataService.Units.FirstOrDefault(x => x.UnitId == defenderId)?.Defense ?? 0);
            double x = ((AppdataService.Weapons.FirstOrDefault(x => x.WeaponId == AppdataService.Units.FirstOrDefault(x => x.UnitId == attackerId)?.PrimaryWeaponId)?.Quality ?? 0) + ((AppdataService.Abilities.FirstOrDefault(x => x.AbilityId == AppdataService.Units.FirstOrDefault(x => x.UnitId == attackerId)?.FirstAbilityId)?.Quality ?? 0) + ((double)(AppdataService.Abilities.FirstOrDefault(x => x.AbilityId == AppdataService.Units.FirstOrDefault(x => x.UnitId == attackerId)?.SecondAbilityId)?.Quality ?? 0)))) / 8 * ((9 - (double)value0) / 8) * (AppdataService.Weapons.FirstOrDefault(x => x.WeaponId == AppdataService.Units.FirstOrDefault(x => x.UnitId == attackerId)?.PrimaryWeaponId)?.Dices ?? 1);

            if (AppdataService.Weapons.FirstOrDefault(x => x.WeaponId == AppdataService.Units.FirstOrDefault(x => x.UnitId == attackerId)?.PrimaryWeaponId) == AppdataService.Weapons.FirstOrDefault(x => x.WeaponId == AppdataService.Units.FirstOrDefault(x => x.UnitId == attackerId)?.SecondaryWeaponId))
            {
                x *= 2;
            }

            if (value1 != 0)
            {
                x *= (9 - (double)value1) / 8;
            }

            if (Convert.ToInt32(cover) == 1)
            {
                x *= 0.75;
            }
            else if (Convert.ToInt32(cover) == 2)
            {
                x *= 0.625;
            }

            return x;
        }

        public static Task<(int, int)> AttackValueTranslatorAsync(int attacker, int defender)
        {
            int x = 5;

            if (attacker > defender)
            {
                x -= attacker - defender;
            }
            else if (attacker < defender)
            {
                x += defender - attacker;
            }
            if (x > 8)
            {
                return Task.FromResult((8, x - 6));
            }
            if (x < 2)
            {
                x = 2;
            }
            return Task.FromResult((x, 0));
        }
    }
}