using Microsoft.AspNetCore.Mvc;
using Model;
using StubLib;
using DTO;
using DTO.Mapper;
using System.CodeDom.Compiler;
using System.Drawing;
using System;
using API_LoL.Mapper;
using System.Xml.Linq;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System.Reflection.PortableExecutable;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace API_LoL.Controllers
{
    //[Route("api/[controller]")]
    [ApiVersion("1.0")]
    [Route("api/v{version:apiVersion}/[controller]")]
    [ApiController]
    public class ChampionsController : ControllerBase
    {

       public ChampionsController(IDataManager Manager) {
            this._logger = LoggerFactory.Create(builder => builder.AddConsole()).CreateLogger<ChampionsController>();
            this.ChampionsManager = Manager.ChampionsMgr;
            this.SkinsManager = Manager.SkinsMgr;
       }


        private IChampionsManager ChampionsManager;
        private ISkinsManager SkinsManager;
        //private StubData stubData;
        private ILogger logger;
        private readonly ILogger _logger;

        // GET api/<ChampionController>/5

        [HttpGet("count")]
        public async Task<IActionResult> GetCount()
        {
            _logger.LogInformation(message: "count returned", "Get", "/Champion/Count", 200, DateTime.Now);
            return Ok(ChampionsManager.GetNbItems());
        }

        [HttpGet]
        public async Task<IActionResult> Get(string? name = null,String? skill = null, String? characteristic = null,int index = 0,int size =10)
        {
            if (size - index > 10)
            {
                _logger.LogError(message : "Oversized","Get","/Champion",400,"name : "+name,"skill : "+skill,"characteristics : "+characteristic,"index : "+index,"size : "+size,DateTime.Now);
                return BadRequest();
            }
            if (!string.IsNullOrEmpty(name))
            {
                var list = await ChampionsManager.GetItemsByName(name, index, size);
                if (list.Count() != 0)
                {
                    _logger.LogInformation(message: "Champion returned by name", "Get", "/Champion", 200, "name : " + name, "skill : " + skill, "characteristic : " + characteristic, "index : " + index, "size : " + size, DateTime.Now);
                    return Ok(list.Select(champion => champion?.ToDTO()));
                }
                else {
                    _logger.LogInformation(message: "No Champion found by name", "Get", "/Champion", 204, "name : " + name, "skill : " + skill, "characteristic : " + characteristic, "index : " + index, "size : " + size, DateTime.Now);
                    return NoContent(); }
            }
            else if(!string.IsNullOrEmpty(skill)) {
                var list = await ChampionsManager.GetItemsBySkill(skill, index, size);
                if (list.Count() != 0)
                {
                    _logger.LogInformation(message: "Champion returned by skill", "Get", "/Champion", 200, "name : " + name, "skill : " + skill, "characteristic : " + characteristic, "index : " + index, "size : " + size, DateTime.Now);
                    return Ok(list.Select(champion => champion?.ToDTO()));
                }
                else {
                    _logger.LogInformation(message: "No Champion found by skill", "Get", "/Champion", 204, "name : " + name, "skill : " + skill, "characteristic : " + characteristic, "index : " + index, "size : " + size, DateTime.Now);
                    return NoContent(); }
            }
            else if(!string.IsNullOrEmpty (characteristic)) {
                var list = await ChampionsManager.GetItems(index, size);
                if (list.Count() != 0)
                {
                    _logger.LogInformation(message: "Champion returned by characteristic", "Get", "/Champion", 200, "name : " + name, "skill : " + skill, "characteristic : " + characteristic, "index : " + index, "size : " + size, DateTime.Now);
                    return Ok(list.Select(champion => champion?.ToDTO()));
                }
                else {
                    _logger.LogInformation(message: "No Champion found by char", "Get", "/Champion", 204, "name : " + name, "skill : " + skill, "characteristic : " + characteristic, "index : " + index, "size : " + size, DateTime.Now);
                    return NoContent(); }
            }
            else {
                var list = await ChampionsManager.GetItems(index, size);
                if (list.Count() != 0)
                {
                    _logger.LogInformation(message: "Champion returned default", "Get", "/Champion", 200, "name : " + name, "skill : " + skill, "characteristic : " + characteristic, "index : " + index, "size : " + size, DateTime.Now);
                    return Ok(list.Select(champion => champion?.ToDTO()));
                }
                else {
                    _logger.LogInformation(message: "No Champion found Default", "Get", "/Champion", 204, "name : " + name,"skill : " + skill,"characteristic : "+ characteristic,"index : "+index,"size : "+size,  DateTime.Now);
                    return NoContent(); 
                }
            }
        }

        [HttpGet("name")]
        public async Task<IActionResult> GetByName(String name)
        {
            if (string.IsNullOrEmpty(name))
            {
                _logger.LogError(message: "No paramater given", "Get", "/Champion/Name", 400, "name : " + name, DateTime.Now);
                return BadRequest();
            }
            var list = await ChampionsManager.GetItemsByName(name, 0, 1);
            if (list.Count() == 1)
            {
                _logger.LogInformation(message: "Champion found", "Get", "/Champion/Name", 20, "name : " + name, DateTime.Now);
                return Ok(list.Select(champion => champion?.ToDTO()).First());
            }
            else {
                _logger.LogInformation(message: "No Champion found", "Get", "/Champion/Name", 204, "name : " + name, DateTime.Now);
                return NoContent(); 
            }

        }

        [HttpGet("name/skins")]
        public async Task<IActionResult> GetSkinsByName(String name)
        {
            if (string.IsNullOrEmpty(name))
            {
                _logger.LogError(message: "No paramater given", "Get", "/Champion/Name/Skins", 400, "name : " + name, DateTime.Now);
                return BadRequest();
            }
            var list = await ChampionsManager.GetItemsByName(name, 0, 1);
            if (list.Count() == 1)
            {
                var nb = await SkinsManager.GetNbItemsByChampion(list.First());
                if (nb != 0)
                {
                    var skins = await SkinsManager.GetItemsByChampion(list.First(), 0, nb);
                    return Ok(skins.Select(skin => skin?.ToDTO()));
                }
                else {
                    _logger.LogInformation(message: "No Skin found found", "Get", "/Champion/Name/Skins", 204, "name : " + name, DateTime.Now);
                    return NoContent(); }
            }
            else {
                _logger.LogInformation(message: "No Champion found", "Get", "/Champion/Name/Skins", 204, "name : " + name, DateTime.Now);
               
                return NoContent(); 
            }

        }

        //[HttpGet("name/skills")]
        //public async Task<IActionResult> GetSkillsByName(String name)
        //{
        //    if (string.IsNullOrEmpty(name)) return BadRequest();
        //    var list = await ChampionsManager.GetItemsByName(name, 0, 1);
        //    if (list.Count() == 1)
        //    {
        //        var skins = await SkinsManager.GetItemsByChampion(list.First(), 0, await SkinsManager.GetNbItemsByChampion(list.First()));
        //        if (skins.Count() != 0)
        //        {
        //            return Ok(skins.Select(skin => skin?.ToDTO()));
        //        }
        //        else { return NoContent(); }
        //    }
        //    else { return NoContent(); }
        //}



        // POST api/<ChampionController>
        [HttpPost]
        public async Task<IActionResult> Post(ChampionDTO champion)
        {
            if (champion == null)
            {
                _logger.LogError(message: "Null paramater given", "Post", "/Champion", 422, "champion : " + champion.toString, DateTime.Now);
                return UnprocessableEntity();
            }
            else
            {
                var list = await ChampionsManager.GetItemsByName(champion.Name, 0, 1);
                Champion champ = list.FirstOrDefault();
                if (champ != null)
                {
                    if(champ.Name == champion.Name)
                    {
                        _logger.LogError(message: "Champion with this id already exists", "Post", "/Champion", 409, "champion : " + champion.toString, DateTime.Now);
                        return Conflict(champion);
                    }
                }
                await ChampionsManager.AddItem(champion.ToChampion());
                _logger.LogInformation(message: "Champion created", "Post", "Champion/Name", 201, "champion : " + champion.toString, DateTime.Now);
                return CreatedAtAction("Post",champion);
            
            }
        }

        // PUT api/<ChampionController>/5
        [HttpPut("name")]
        public async Task<IActionResult> Put(string name, ChampionDTO championDTO)
        {
            if (string.IsNullOrEmpty(name))
            {
                _logger.LogError(message: "Null paramater given for Name", "Put", "/Champion/Name", 400,"name : "+name, "champion : " + championDTO.toString, DateTime.Now);
                return BadRequest();
            }
            if(championDTO == null)
            {
                _logger.LogError(message: "Null paramater given for Champion", "Put", "/Champion/Name", 422, "name : " + name, "champion : " + championDTO.toString, DateTime.Now);
                return UnprocessableEntity();
            }
            var list = await ChampionsManager.GetItemsByName(name, 0, 1);
            if (list.Count() == 1)
            {
                _logger.LogInformation(message: "Champion updated", "Put", "Champion/Name", 200, "name : " + name, "champion : " + championDTO.toString, DateTime.Now);
                return Ok(ChampionsManager.UpdateItem(list.First(), championDTO.ToChampion()));
            }
            else {
                _logger.LogInformation(message: "No champion Found", "Put", "/Champion/Name", 204, "name : " + name, "champion : " + championDTO.toString, DateTime.Now);
                return NoContent(); 
            }
        }

        // DELETE api/<ChampionController>/5
        [HttpDelete("name")]
        public async Task<IActionResult> Delete(string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                _logger.LogError(message: "Null paramater given for Name", "Delete", "/Champion/Name", 400, "name : " + name, DateTime.Now);
            return BadRequest();
            }
            var list = await ChampionsManager.GetItemsByName(name, 0, 1);
            if(list.Count() == 1){
                _logger.LogInformation(message: "Champion Deleted", "Delete", "/Champion/Name", 200, "name : " + name, DateTime.Now);
                return Ok(await ChampionsManager.DeleteItem(list.First()));
            }else {
                _logger.LogInformation(message: "No champion Found", "Delete", "/Champion/Name", 204, "name : " + name, DateTime.Now);
                return NoContent(); }
        }
    }
}
