using DbConnectionLibrairie;
using Entities;
using ManagerInterfaces;
using Microsoft.EntityFrameworkCore;
using Model;
using OrderCriterias;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EntityManagers
{
    public class PlayerEntityManager(MyDbContext dbContext) : IPlayerManager<PlayerEntity>
    {
        MyDbContext dbContext = dbContext;

        public async Task<PlayerEntity> addPlayer(PlayerEntity player)
        {
            var tmp = await dbContext.Players.Where(p => p.Equals(player)).FirstOrDefaultAsync();
            if (tmp != null) // <=> he already exist
            {
                return tmp;
            }
            dbContext.Players.Add(player);
            await dbContext.SaveChangesAsync();
            return await dbContext.Players.Where(p => p.Equals(player)).FirstAsync();
        }

        public async Task<uint?> getMaxScorePlayer(uint id, uint idChapter)
        {
            var tmp = await dbContext.Play.Where(p => p.IdPlayer == id && p.IdChapter == idChapter).FirstOrDefaultAsync();
            return await Task.FromResult(tmp?.MaxScore);
        }

        public async Task<uint?> getMaxScorePlayer(uint id)
        {
            var tmp = dbContext.Play.Where(p => p.IdPlayer == id).Select(p => p.MaxScore);
            if (!tmp.AnyAsync().Result) return await Task.FromResult<uint?>(null);
            return await Task.FromResult<uint?>(tmp?.MaxAsync().Result);
        }

        public int getNbElements()
        {
            return dbContext.Players.CountAsync().Result;
        }

        public async Task<PlayerEntity?> getPlayer(uint id)
        {
            return await dbContext.Players.Where(p => p.Id == id).FirstOrDefaultAsync();
        }

        public async Task<PlayerEntity?> getPlayer(string nickname)
        {
            return await dbContext.Players.Where(p => p.Nickname == nickname).FirstOrDefaultAsync();
        }

        public async Task<(int nbPages, IEnumerable<PlayerEntity>? players)> getPlayers(int nb, int count, PlayerOrderCriteria orderCriteria = PlayerOrderCriteria.ById)
        {
            int nbEl = getNbElements();
            if (nb < 0 || count < 0 || nb > nbEl / count) return await Task.FromResult<(int nbPages, IEnumerable<PlayerEntity>? players)>((nbEl / count, null));
            var tmp = dbContext.Players;
            switch (orderCriteria)
            {
                case PlayerOrderCriteria.ById:
                    tmp.OrderBy(p => p.Id);
                    break;
                case PlayerOrderCriteria.ByNickname:
                    tmp.OrderBy(p => p.Nickname);
                    break;
            }
            return await Task.FromResult<(int nbPages, IEnumerable<PlayerEntity>? players)>((nbEl / count, tmp.Skip((nb - 1) * count).Take(count)));
        }

        public async Task<IEnumerable<PlayerEntity>?> getPlayersInALobby(uint idLobby)
        {
            if (!await dbContext.Lobbies.Where(l => l.Id == idLobby).AnyAsync())
                return await Task.FromResult<IEnumerable<PlayerEntity>?>(null);
            return await Task.FromResult<IEnumerable<PlayerEntity>?>(dbContext.Use
                .Where(u => u.IdLobby == idLobby)
                .Select(u => u.Player));
        }

        public async Task<PlayerEntity?> removePlayer(PlayerEntity player)
        {
            var tmp = dbContext.Players.Where(p => p.Equals(player)).FirstOrDefaultAsync().Result;
            if (tmp == null) return await Task.FromResult<PlayerEntity?>(tmp);
            dbContext.Players.Remove(tmp);
            await dbContext.SaveChangesAsync();
            return await Task.FromResult<PlayerEntity?>(tmp);
        }

        public async Task<PlayerEntity?> removePlayer(uint id)
        {
            var tmp = getPlayer(id).Result;
            if (tmp == null) return await Task.FromResult<PlayerEntity?>(tmp);
            dbContext.Players.Remove(tmp);
            await dbContext.SaveChangesAsync();
            return await Task.FromResult<PlayerEntity?>(tmp);
        }
    }
}
