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 ElementModelsController(MapEditorDbContext MapDb, MapEditorStorageRepository MapStorage, LoggerController<ElementModelsController> Logger) : ControllerBase
{
    [HttpGet]
    [Route("map/{mapId}")]
    public async Task<MessageResult<IEnumerable<ElementModelDto>>> Gets(Guid mapId)
    {
        try
        {
            return new(true)
            {
                Data = await (from elm in MapDb.ElementModels
                              where !string.IsNullOrEmpty(elm.Name) && elm.MapId == mapId
                              select new ElementModelDto()
                              {
                                  Id = elm.Id,
                                  MapId = elm.MapId,
                                  Name = elm.Name,
                                  Height = elm.Height,
                                  Width = elm.Width,
                                  Image1Height = elm.Image1Height,
                                  Image2Height = elm.Image2Height,
                                  Image1Width = elm.Image1Width,
                                  Image2Width = elm.Image2Width,
                                  Content = elm.Content,
                              }).ToListAsync()
            };

        }
        catch (Exception ex)
        {
            Logger.Warning($"Gets: Hệ thống có lỗi xảy ra - {ex.Message}");
            return new(false, $"Gets: Hệ thống có lỗi xảy ra - {ex.Message}");
        }
    }

    [HttpGet]
    [Route("{id}")]
    public async Task<MessageResult<ElementModelDto>> Get(Guid id)
    {
        try
        {
            var elmodel = await MapDb.ElementModels.FindAsync(id);
            if (elmodel is null) return new(false, $"Element Model {id} không tồn tại");
            return new(true)
            {
                Data = new ElementModelDto()
                {
                    Id = elmodel.Id,
                    Name = elmodel.Name,
                    MapId = elmodel.MapId,
                    Height = elmodel.Height,
                    Width = elmodel.Width,
                    Content = elmodel.Content,
                }
            };
        }
        catch (Exception ex)
        {
            Logger.Warning($"Get {id}: Hệ thống có lỗi xảy ra - {ex.Message}");
            return new(false, $"Get {id}: Hệ thống có lỗi xảy ra - {ex.Message}");
        }
    }

    [HttpPost]
    public async Task<MessageResult<ElementModelDto>> CreateElementModel([FromForm] ElementModelCreateModel model, [FromForm(Name = "imageOpen")] IFormFile imageOpen, [FromForm(Name = "imageClose")] IFormFile imageClose)
    {
        try
        {
            if (model == null || imageOpen == null || imageClose == null) return new(false, "Dữ liệu đầu vào 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}");
            if (MapDb.ElementModels.Any(elm => elm.Name == model.Name && elm.MapId == model.MapId)) return new(false, $"Tên Model {model.Name} đã tồn tại");

            var image1 = SixLabors.ImageSharp.Image.Load(imageOpen.OpenReadStream());
            var image2 = SixLabors.ImageSharp.Image.Load(imageClose.OpenReadStream());
            var entity = MapDb.ElementModels.Add(new()
            {
                Name = model.Name,
                MapId = model.MapId,
                Width = model.Width,
                Height = model.Height,
                Image1Height = (ushort)image1.Height,
                Image1Width = (ushort)image1.Width,
                Image2Height = (ushort)image2.Height,
                Image2Width = (ushort)image2.Width,
                Content = "",
            });

            await MapDb.SaveChangesAsync();

            var (isSuccess, message) = await MapStorage.UploadAsync("ElementOpenModels", $"{entity.Entity.Id}", imageOpen.OpenReadStream(), imageOpen.Length, imageOpen.ContentType, CancellationToken.None);
            if (!isSuccess)
            {
                MapDb.ElementModels.Remove(entity.Entity);
                await MapDb.SaveChangesAsync();
                return new(false, message);
            }
            (isSuccess, message) = await MapStorage.UploadAsync("ElementCloseModels", $"{entity.Entity.Id}", imageClose.OpenReadStream(), imageClose.Length, imageClose.ContentType, CancellationToken.None);
            if (!isSuccess)
            {
                MapDb.ElementModels.Remove(entity.Entity);
                await MapDb.SaveChangesAsync();
                await MapStorage.DeleteAsync("ElementOpenModels", $"{entity.Entity.Id}", CancellationToken.None);
                return new(false, message);
            }

            return new(true)
            {
                Data = new()
                {
                    Id = entity.Entity.Id,
                    Name = entity.Entity.Name,
                    MapId = entity.Entity.MapId,
                    Width = entity.Entity.Width,
                    Height = entity.Entity.Height,
                    Image1Height = entity.Entity.Image1Height,
                    Image1Width = entity.Entity.Image1Width,
                    Image2Height = entity.Entity.Image2Height,
                    Image2Width = entity.Entity.Image2Width,
                    Content = entity.Entity.Content
                }
            };
        }
        catch (Exception ex)
        {
            Logger.Warning($"CreateElementModel: Hệ thống có lỗi xảy ra - {ex.Message}");
            return new(false, $"CreateElementModel: Hệ thống có lỗi xảy ra - {ex.Message}");
        }
    }

    [HttpPut]
    public async Task<MessageResult<ElementModelDto>> Update([FromBody] ElementModelUpdateModel model)
    {
        try
        {
            var elModel = await MapDb.ElementModels.FindAsync(model.Id);
            if (elModel is null) return new(false, $"Model {model.Id} không tồn tại");
            if (MapDb.ElementModels.Any(elm => elm.Name == model.Name && elm.MapId == elModel.MapId && model.Id != elModel.Id)) return new(false, $"Tên Model {model.Name} đã tồn tại");

            elModel.Name = model.Name;
            elModel.Width = model.Width;
            elModel.Height = model.Height;
            elModel.Content = model.Content;
            await MapDb.SaveChangesAsync();
            return new(true)
            {
                Data = new()
                {
                    Id = elModel.Id,
                    Name = elModel.Name,
                    MapId = elModel.MapId,
                    Width = elModel.Width,
                    Height = elModel.Height,
                    Image1Height = elModel.Image1Height,
                    Image1Width = elModel.Image1Width,
                    Image2Height = elModel.Image2Height,
                    Image2Width = elModel.Image2Width,
                    Content = elModel.Content
                }
            };
        }
        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 elModel = await MapDb.ElementModels.FindAsync(id);
            if (elModel is null) return new(false, $"Model {id} không tồn tại");

            await MapStorage.DeleteAsync("ElementOpenModels", id.ToString(), CancellationToken.None);
            await MapStorage.DeleteAsync("ElementCloseModels", id.ToString(), CancellationToken.None);
            MapDb.Elements.RemoveRange(MapDb.Elements.Where(e => e.ModelId == id));
            MapDb.ElementModels.Remove(elModel);
            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}");
        }
    }

    [HttpPut]
    [Route("openimage/{id}")]
    public async Task<MessageResult> UpdateOpenImage(Guid id, [FromForm(Name = "image")] IFormFile image)
    {
        try
        {
            var elModel = await MapDb.ElementModels.FindAsync(id);
            if (elModel is null) return new(false, $"Model {id} không tồn tại");

            var imageStream = image.OpenReadStream();
            var (isSuccess, message) = await MapStorage.UploadAsync("ElementOpenModels", $"{elModel.Id}", imageStream, image.Length, image.ContentType, CancellationToken.None);
            if (!isSuccess) return new(false, message);

            var imageUpdate = SixLabors.ImageSharp.Image.Load(image.OpenReadStream());
            elModel.Image1Width = (ushort)imageUpdate.Width;
            elModel.Image1Height = (ushort)imageUpdate.Height;
            await MapDb.SaveChangesAsync();

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

    [HttpPut]
    [Route("closeimage/{id}")]
    public async Task<MessageResult> UpdateCloseImage(Guid id, [FromForm(Name = "image")] IFormFile image)
    {
        try
        {
            var elModel = await MapDb.ElementModels.FindAsync(id);
            if (elModel is null) return new(false, $"Model {id} không tồn tại");

            var imageStream = image.OpenReadStream();
            var (isSuccess, message) = await MapStorage.UploadAsync("ElementCloseModels", $"{elModel.Id}", imageStream, image.Length, image.ContentType, CancellationToken.None);
            if (!isSuccess) return new(false, message);

            var imageUpdate = SixLabors.ImageSharp.Image.Load(image.OpenReadStream());
            elModel.Image2Width = (ushort)imageUpdate.Width;
            elModel.Image2Height = (ushort)imageUpdate.Height;
            await MapDb.SaveChangesAsync();

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