using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using RobotNet.RobotManager.Data;
using RobotNet.RobotManager.Services;
using RobotNet.RobotShares.Dtos;
using RobotNet.Shares;

namespace RobotNet.RobotManager.Controllers;

[Route("api/[controller]")]
[ApiController]
[Authorize]
public class RobotModelsController(RobotEditorDbContext RobotDb, RobotEditorStorageRepository RobotStorage, IHttpClientFactory HttpClientFactory, LoggerController<RobotManagerController> Logger) : ControllerBase
{
    [HttpGet]
    public async Task<IEnumerable<RobotModelDto>> GetRobotModels([FromQuery(Name = "txtSearch")] string? txtSearch)
    {
        try
        {
            if (string.IsNullOrWhiteSpace(txtSearch))
            {
                return await (from robotmodel in RobotDb.RobotModels
                              select new RobotModelDto()
                              {
                                  Id = robotmodel.Id,
                                  ModelName = robotmodel.ModelName,
                                  OriginX = robotmodel.OriginX,
                                  OriginY = robotmodel.OriginY,
                                  ImageWidth = robotmodel.ImageWidth,
                                  ImageHeight = robotmodel.ImageHeight,
                                  Width = Math.Round(robotmodel.Width, 2),
                                  Length = Math.Round(robotmodel.Length, 2),
                                  NavigationType = robotmodel.NavigationType,
                              }).ToListAsync();
            }
            else
            {
                return await (from robotmodel in RobotDb.RobotModels
                              where !string.IsNullOrEmpty(robotmodel.ModelName) && robotmodel.ModelName.Contains(txtSearch)
                              select new RobotModelDto()
                              {
                                  Id = robotmodel.Id,
                                  ModelName = robotmodel.ModelName,
                                  OriginX = robotmodel.OriginX,
                                  OriginY = robotmodel.OriginY,
                                  ImageWidth = robotmodel.ImageWidth,
                                  ImageHeight = robotmodel.ImageHeight,
                                  Width = Math.Round(robotmodel.Width, 2),
                                  Length = Math.Round(robotmodel.Length, 2),
                                  NavigationType = robotmodel.NavigationType,
                              }).ToListAsync();
            }
        }
        catch (Exception ex)
        {
            Logger.Warning($"GetRobotModels: Hệ thống có lỗi xảy ra - {ex.Message}");
            return [];
        }
    }

    [HttpGet]
    [Route("{robotModelId}")]
    public async Task<MessageResult<RobotModelDto?>> GetRobotModel(Guid robotModelId)
    {
        try
        {
            var robotmodel = await RobotDb.RobotModels.FirstOrDefaultAsync(model => model.Id == robotModelId);
            var robotmodelDto = robotmodel is null ? null : new RobotModelDto()
            {
                Id = robotmodel.Id,
                ModelName = robotmodel.ModelName,
                OriginX = robotmodel.OriginX,
                OriginY = robotmodel.OriginY,
                ImageWidth = robotmodel.ImageWidth,
                ImageHeight = robotmodel.ImageHeight,
                Width = Math.Round(robotmodel.Width, 2),
                Length = Math.Round(robotmodel.Length, 2),
                NavigationType = robotmodel.NavigationType,
            };
            return new(true) { Data = robotmodelDto };
        }
        catch (Exception ex)
        {
            Logger.Warning($"GetRobotModel {robotModelId}: Hệ thống có lỗi xảy ra - {ex.Message}");
            return new(false, $"Hệ thống có lỗi xảy ra");
        }
    }

    [HttpGet]
    [AllowAnonymous]
    [Route("image/{robotmodelId}")]
    public async Task<IActionResult> GetImage(Guid robotmodelId)
    {
        try
        {
            var (usingLocal, url) = RobotStorage.GetUrl("RobotModels", robotmodelId.ToString());
            if (!usingLocal)
            {
                var http = HttpClientFactory.CreateClient();
                var imageBytes = await http.GetByteArrayAsync(url);
                if (imageBytes != null && imageBytes.Length > 0) return File(imageBytes, "image/png");
                else return NotFound("Không thể lấy được ảnh map.");
            }
            if (System.IO.File.Exists(url)) return PhysicalFile(url, "image/png");
            else return NotFound();
        }
        catch (Exception ex)
        {
            Logger.Warning($"GetImage {robotmodelId}: Hệ thống có lỗi xảy ra - {ex.Message}");
            return NotFound();
        }
    }

    [HttpPost]
    public async Task<MessageResult<RobotModelDto>> CreateRobotModel([FromForm] RobotModelCreateModel robotmodel, [FromForm(Name = "Image")] IFormFile imageUpload)
    {
        try
        {
            if (imageUpload.ContentType != "image/png") return new(false, "Robot image format chỉ hỗ trợ định dạng image/png");
            if (await RobotDb.RobotModels.AnyAsync(model => model.ModelName == robotmodel.ModelName)) return new(false, "Tên của robot model đã tồn tại, Hãy đặt tên khác!");

            var image = SixLabors.ImageSharp.Image.Load(imageUpload.OpenReadStream());
            var entityRobotModel = await RobotDb.RobotModels.AddAsync(new RobotModel()
            {
                ModelName = robotmodel.ModelName,
                OriginX = robotmodel.OriginX,
                OriginY = robotmodel.OriginY,
                ImageHeight = image.Height,
                ImageWidth = image.Width,
                Length = robotmodel.Length,
                Width = robotmodel.Width,
                NavigationType = robotmodel.NavigationType,
            });

            await RobotDb.SaveChangesAsync();

            var (isSuccess, message) = await RobotStorage.UploadAsync("RobotModels", $"{entityRobotModel.Entity.Id}", imageUpload.OpenReadStream(), imageUpload.Length, imageUpload.ContentType, CancellationToken.None);
            if (!isSuccess)
            {
                RobotDb.RobotModels.Remove(entityRobotModel.Entity);
                await RobotDb.SaveChangesAsync();
                return new(false, message);
            }

            return new(true)
            {
                Data = new()
                {
                    Id = entityRobotModel.Entity.Id,
                    ModelName = entityRobotModel.Entity.ModelName,
                    OriginX = entityRobotModel.Entity.OriginX,
                    OriginY = entityRobotModel.Entity.OriginY,
                    ImageWidth = entityRobotModel.Entity.ImageWidth,
                    ImageHeight = entityRobotModel.Entity.ImageHeight,
                    Width = Math.Round(entityRobotModel.Entity.Width, 2),
                    Length = Math.Round(entityRobotModel.Entity.Length, 2),
                    NavigationType = entityRobotModel.Entity.NavigationType,
                }
            };
        }
        catch (Exception ex)
        {
            Logger.Warning($"CreateRobotModel : Hệ thống có lỗi xảy ra - {ex.Message}");
            return new(false, "Hệ thống có lỗi xảy ra");
        }
    }

    [HttpPut]
    public async Task<MessageResult<RobotModelDto>> UpdateRobotModel([FromBody] RobotModelUpdateModel robotmodel)
    {
        try
        {
            var robotModelDb = await RobotDb.RobotModels.FindAsync(robotmodel.Id);
            if (robotModelDb == null) return new(false, $"Không tồn tại robot model id = {robotmodel.Id}");

            if (robotmodel.ModelName != robotModelDb.ModelName && await RobotDb.RobotModels.AnyAsync(m => m.ModelName == robotmodel.ModelName))
            {
                return new(false, "Tên của robot model đã tồn tại, Hãy đặt tên khác!");
            }

            robotModelDb.ModelName = robotmodel.ModelName;
            robotModelDb.OriginX = robotmodel.OriginX;
            robotModelDb.OriginY = robotmodel.OriginY;
            robotModelDb.Length = robotmodel.Length;
            robotModelDb.Width = robotmodel.Width;

            await RobotDb.SaveChangesAsync();
            return new(true)
            {
                Data = new()
                {
                    ModelName = robotModelDb.ModelName,
                    OriginX = robotModelDb.OriginX,
                    OriginY = robotModelDb.OriginY,
                    NavigationType = robotModelDb.NavigationType,
                    ImageWidth = robotModelDb.ImageWidth,
                    ImageHeight = robotModelDb.ImageHeight,
                    Width = Math.Round(robotModelDb.Width, 2),
                    Length = Math.Round(robotModelDb.Length, 2),
                }
            };
        }
        catch (Exception ex)
        {
            Logger.Warning($"UpdateRobotModel : Hệ thống có lỗi xảy ra - {ex.Message}");
            return new(false, $"Hệ thống có lỗi xảy ra");
        }
    }

    [HttpDelete]
    [Route("{robotModelId}")]
    public async Task<MessageResult> DeleteRobotModel(Guid robotModelId)
    {
        try
        {
            var robotModelDb = await RobotDb.RobotModels.FindAsync(robotModelId);
            if (robotModelDb == null) return new(false, $"Không tồn tại robot model id = {robotModelId}");

            if (RobotDb.Robots.Any(r => r.ModelId == robotModelId)) return new(false, "Tồn tại robot đang sử dụng model này");

            await RobotStorage.DeleteAsync("RobotModels", robotModelId.ToString(), CancellationToken.None);
            RobotDb.RobotModels.Remove(robotModelDb);
            await RobotDb.SaveChangesAsync();
            return new(true, "");
        }
        catch (Exception ex)
        {
            Logger.Warning($"DeleteRobotModel {robotModelId} : Hệ thống có lỗi xảy ra - {ex.Message}");
            return new(false, $"Hệ thống có lỗi xảy ra");
        }
    }

    [HttpPut]
    [Route("image/{robotModelId}")]
    public async Task<MessageResult> UpdateImage(Guid robotModelId, [FromForm(Name = "image")] IFormFile image)
    {
        try
        {
            var robotModel = await RobotDb.RobotModels.FindAsync(robotModelId);
            if (robotModel == null) return new(false, $"Không tồn tại robot model id = {robotModelId}");

            var imageStream = image.OpenReadStream();
            var imageUpdate = SixLabors.ImageSharp.Image.Load(imageStream);
            robotModel.ImageWidth = imageUpdate.Width;
            robotModel.ImageHeight = imageUpdate.Height;
            await RobotDb.SaveChangesAsync();

            var (isSuccess, message) = await RobotStorage.UploadAsync("RobotModels", robotModelId.ToString(), image.OpenReadStream(), image.Length, image.ContentType, CancellationToken.None);
            return new(true, "");
        }
        catch (Exception ex)
        {
            Logger.Warning($"UpdateImage: Hệ thống có lỗi xảy ra - {ex.Message}");
            return new(false, $"Hệ thống có lỗi xảy ra");
        }
    }
}
