using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using RobotNet.MapManager.Data;
using RobotNet.MapManager.Services;
using RobotNet.MapShares.Dtos;
using RobotNet.Shares;

namespace RobotNet.MapManager.Controllers;

[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ElementsController(MapEditorDbContext MapDb, LoggerController<ElementsController> Logger) : ControllerBase
{

    [HttpGet]
    public async Task<MessageResult<ElementDto>> GetElement([FromQuery] string mapName, [FromQuery] string elementName)
    {
        try
        {
            var map = await MapDb.Maps.FirstOrDefaultAsync(m => m.Name == mapName);
            if (map is null) return new(false, $"Không tồn tại map tên = {mapName}");

            var el = await MapDb.Elements.FirstOrDefaultAsync(e => e.MapId == map.Id && e.Name == elementName);
            if (el is null) return new(false, $"Không tồn tại element name = {elementName}");

            var elNode = await MapDb.Nodes.FindAsync(el.NodeId);
            if (elNode is null) return new(false, $"Không tồn tại node id = {el.NodeId}");

            return new(true)
            {
                Data = new()
                {
                    Id = el.Id,
                    Name = el.Name,
                    MapId = el.MapId,
                    IsOpen = el.IsOpen,
                    NodeId = el.NodeId,
                    OffsetX = el.OffsetX,
                    OffsetY = el.OffsetY,
                    ModelId = el.ModelId,
                    Content = el.Content,
                    NodeName = elNode.Name,
                    X = elNode.X,
                    Y = elNode.Y,
                    Theta = elNode.Theta
                }
            };
        }
        catch (Exception ex)
        {
            Logger.Warning($"GetElement: Hệ thống có lỗi xảy ra - {ex.Message}");
            return new(false, $"GetElement: Hệ thống có lỗi xảy ra - {ex.Message}");
        }
    }

    [HttpGet]
    [Route("{modelId}")]
    public async Task<MessageResult<IEnumerable<ElementDto>>> GetElementsByModelId([FromRoute] Guid modelId)
    {
        try
        {
            var elModel = await MapDb.ElementModels.FindAsync(modelId);
            if (elModel is null) return new(false, $"Không tồn tại model id = {modelId}");

            return new(true)
            {
                Data = await (from el in MapDb.Elements
                              where el.ModelId == modelId
                              select new ElementDto()
                              {
                                  Id = el.Id,
                                  MapId = el.MapId,
                                  Name = el.Name,
                                  ModelId = el.ModelId,
                                  ModelName = elModel.Name,
                                  IsOpen = el.IsOpen,
                                  NodeId = el.NodeId,
                                  OffsetX = el.OffsetX,
                                  OffsetY = el.OffsetY,
                                  Content = el.Content,
                              }).ToListAsync()
            };
        }
        catch (Exception ex)
        {
            Logger.Warning($"GetElementsByModelId: Hệ thống có lỗi xảy ra - {ex.Message}");
            return new(false, $"GetElementsByModelId: Hệ thống có lỗi xảy ra - {ex.Message}");
        }
    }

    [HttpPost]
    public async Task<MessageResult<ElementDto>> Create([FromBody] ElementCreateModel model)
    {
        try
        {
            if (model == null || string.IsNullOrEmpty(model.Name)) return new(false, "Dữ liệu không hợp lệ");
            var map = await MapDb.Maps.FindAsync(model.MapId);
            if (map == null) return new(false, $"Không tồn tại map id = {model.MapId}");

            var node = await MapDb.Nodes.FindAsync(model.NodeId);
            if (node == null) return new(false, $"Không tồn tại node id = {model.NodeId}");

            var elModel = await MapDb.ElementModels.FindAsync(model.ModelId);
            if (elModel is null) return new(false, $"Không tồn tại element model id = {model.ModelId}");

            if (MapDb.Elements.Any(el => el.Name == model.Name && el.MapId == model.MapId)) return new(false, $"Tên Element đã tồn tại");

            if (MapDb.Elements.Any(el => el.NodeId == model.NodeId)) return new(false, $"Node này đã có Element");

            var entity = await MapDb.Elements.AddAsync(new()
            {
                Name = model.Name,
                MapId = model.MapId,
                NodeId = model.NodeId,
                ModelId = model.ModelId,
                OffsetX = model.OffsetX,
                OffsetY = model.OffsetY,
                Content = elModel.Content,
            });

            await MapDb.SaveChangesAsync();

            return new(true)
            {
                Data = new()
                {
                    Id = entity.Entity.Id,
                    MapId = entity.Entity.MapId,
                    NodeId = entity.Entity.NodeId,
                    ModelName = elModel.Name,
                    Name = entity.Entity.Name,
                    ModelId = entity.Entity.ModelId,
                    OffsetX = entity.Entity.OffsetX,
                    OffsetY = entity.Entity.OffsetY,
                    Content = entity.Entity.Content,
                    IsOpen = entity.Entity.IsOpen,
                }
            };
        }
        catch (Exception ex)
        {
            Logger.Warning($"Create: Hệ thống có lỗi xảy ra - {ex.Message}");
            return new(false, $"Create: Hệ thống có lỗi xảy ra - {ex.Message}");
        }
    }

    [HttpPut]
    public async Task<MessageResult<ElementDto>> Update([FromBody] ElementUpdateModel model)
    {
        try
        {
            var element = await MapDb.Elements.FindAsync(model.Id);
            if (element == null) return new(false, $"Không tồn tại element id = {model.Id}");

            var map = await MapDb.Maps.FindAsync(element.MapId);
            if (map == null) return new(false, $"Không tồn tại map id = {element.MapId}");

            if (MapDb.Elements.Any(el => el.Name == model.Name && el.MapId == element.MapId && el.Id != model.Id)) return new(false, $"Tên Element đã tồn tại");

            element.Name = model.Name;
            element.OffsetX = model.OffsetX;
            element.OffsetY = model.OffsetY;
            element.Content = model.Content;
            element.IsOpen = model.IsOpen;
            await MapDb.SaveChangesAsync();

            return new(true)
            {
                Data = new()
                {
                    Id = element.Id,
                    MapId = element.MapId,
                    NodeId = element.NodeId,
                    Name = element.Name,
                    ModelId = element.ModelId,
                    OffsetX = element.OffsetX,
                    OffsetY = element.OffsetY,
                    Content = element.Content,
                    IsOpen = element.IsOpen,
                }
            };
        }
        catch (Exception ex)
        {
            Logger.Warning($"Update: Hệ thống có lỗi xảy ra - {ex.Message}");
            return new(false, $"Update: Hệ thống có lỗi xảy ra - {ex.Message}");
        }
    }

    [HttpDelete]
    [Route("{id}")]
    public async Task<MessageResult> Delete(Guid id)
    {
        try
        {
            var element = await MapDb.Elements.FindAsync(id);
            if (element == null) return new(false, $"Không tồn tại element id = {id}");

            MapDb.Elements.Remove(element);
            await MapDb.SaveChangesAsync();
            return new(true);
        }
        catch (Exception ex)
        {
            Logger.Warning($"Delete {id}: Hệ thống có lỗi xảy ra - {ex.Message}");
            return new(false, $"Delete {id}: Hệ thống có lỗi xảy ra - {ex.Message}");
        }
    }
}
