using DbController;
using Tabletop.Core.Models;

namespace Tabletop.Core.Services
{
    public class PlayerService(UserService userService, UnitService unitService) : IModelService<Player, int>
    {
        private readonly UserService _userService = userService;
        private readonly UnitService _unitService = unitService;

        public async Task CreateAsync(Player input, IDbController dbController, CancellationToken cancellationToken = default)
        {
            string sql = $@"INSERT INTO Players 
                (
                UserId,
                GameId,
                FractionId,
                Team,
                Color,
                UsedForce
                )
                VALUES
                (
                @USER_ID,
                @GAME_ID,
                @FRACTION_ID,
                @TEAM,
                @COLOR,
                @USED_FORCE
                ); {dbController.GetLastIdSql()}";

            input.PlayerId = await dbController.GetFirstAsync<int>(sql, input.GetParameters(), cancellationToken);
        }

        public async Task DeleteAsync(Player Input, IDbController dbController, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
            string sql = "DELETE FROM Players WHERE PlayerId = @PLAYER_ID";

            await dbController.QueryAsync(sql, new
            {
                Input_ID = Input.PlayerId
            }, cancellationToken);
        }

        public static async Task DeleteByGameAsync(int gameId, IDbController dbController, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
            string sql = "DELETE FROM Players WHERE GameId = @GAME_ID";

            await dbController.QueryAsync(sql, new
            {
                GAME_ID = gameId
            }, cancellationToken);
        }

        public Task<Player?> GetAsync(int identifier, IDbController dbController, CancellationToken cancellationToken = default)
        {
            throw new NotImplementedException();
        }

        public async Task<List<Player>> GetGamePlayersAsync(int gameId, IDbController dbController, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();
            string sql = ("SELECT * FROM Players WHERE GameId = @GAME_ID");

            List<Player> list = await dbController.SelectDataAsync<Player>(sql, new
            {
                GAME_ID = gameId
            }, cancellationToken);

            if (list.Count != 0)
            {
                foreach (var item in list)
                {
                    item.Units = await _unitService.GetPlayerUnitsAsync(item.PlayerId, dbController, cancellationToken);
                    item.User = await _userService.GetUserInformationAsync(item.UserId, dbController, cancellationToken) ?? new();
                }
            }

            return list;
        }

        public async Task UpdateAsync(Player player, IDbController dbController, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            await UnitService.DeletePlayerUnitsAsync(player.PlayerId, dbController, cancellationToken);

            string sql = @"UPDATE Players SET
                Points = @POINTS
                WHERE PlayerId = @PLAYER_ID";

            await dbController.QueryAsync(sql, player.GetParameters(), cancellationToken);
        }

        public async Task UpdatePlayerOrderAsync(Player player, IDbController dbController, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            string sql = @"UPDATE Players SET
                OrderNr = @ORDER_NR,
                StartZone = @START_ZONE
                WHERE PlayerId = @PLAYER_ID";

            await dbController.QueryAsync(sql, player.GetParameters(), cancellationToken);
        }

        public async Task UpdatePlayerArmyAsync(Player player, IDbController dbController, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            await UnitService.DeletePlayerUnitsAsync(player.PlayerId, dbController, cancellationToken);

            string sql = @"UPDATE Players SET
                UsedForce = @USED_FORCE
                WHERE PlayerId = @PLAYER_ID";

            await dbController.QueryAsync(sql, player.GetParameters(), cancellationToken);

            foreach (var unit in player.Units)
            {
                await _unitService.CreatePlayerUnitAsync(player, unit, dbController, cancellationToken);
            }
        }
    }
}