using DbFirst.Application.Repositories;
using DbFirst.Contracts.Layouts;
using DbFirst.Domain.Entities;
using Microsoft.AspNetCore.Mvc;
using System.Text;

namespace DbFirst.API.Controllers;

[ApiController]
[Route("api/[controller]")]
public class LayoutsController : ControllerBase
{
    private readonly ILayoutRepository _repository;

    public LayoutsController(ILayoutRepository repository)
    {
        _repository = repository;
    }

    [HttpGet]
    public async Task<ActionResult<LayoutDto>> Get([FromQuery] string layoutType, [FromQuery] string layoutKey, [FromQuery] string userName, CancellationToken cancellationToken)
    {
        if (string.IsNullOrWhiteSpace(layoutType) || string.IsNullOrWhiteSpace(layoutKey) || string.IsNullOrWhiteSpace(userName))
        {
            return BadRequest("layoutType, layoutKey und userName sind erforderlich.");
        }

        var entity = await _repository.GetAsync(layoutType, layoutKey, userName, cancellationToken);
        if (entity == null)
        {
            return NotFound();
        }

        return Ok(Map(entity));
    }

    [HttpPost]
    public async Task<ActionResult<LayoutDto>> Upsert(LayoutDto dto, CancellationToken cancellationToken)
    {
        if (string.IsNullOrWhiteSpace(dto.LayoutType) || string.IsNullOrWhiteSpace(dto.LayoutKey) || string.IsNullOrWhiteSpace(dto.UserName))
        {
            return BadRequest("LayoutType, LayoutKey und UserName sind erforderlich.");
        }

        var data = string.IsNullOrWhiteSpace(dto.LayoutData)
            ? Array.Empty<byte>()
            : Encoding.UTF8.GetBytes(dto.LayoutData);

        try
        {
            var entity = await _repository.UpsertAsync(dto.LayoutType, dto.LayoutKey, dto.UserName, data, cancellationToken);
            return Ok(Map(entity));
        }
        catch (Exception ex)
        {
            var detail = ex.InnerException?.Message ?? ex.Message;
            return Problem(detail: detail, statusCode: StatusCodes.Status500InternalServerError);
        }
    }

    [HttpDelete]
    public async Task<IActionResult> Delete([FromQuery] string layoutType, [FromQuery] string layoutKey, [FromQuery] string userName, CancellationToken cancellationToken)
    {
        if (string.IsNullOrWhiteSpace(layoutType) || string.IsNullOrWhiteSpace(layoutKey) || string.IsNullOrWhiteSpace(userName))
        {
            return BadRequest("layoutType, layoutKey und userName sind erforderlich.");
        }

        var deleted = await _repository.DeleteAsync(layoutType, layoutKey, userName, cancellationToken);
        return deleted ? NoContent() : NotFound();
    }

    private static LayoutDto Map(SmfLayout entity)
    {
        var layoutData = entity.LayoutData.Length == 0
            ? string.Empty
            : Encoding.UTF8.GetString(entity.LayoutData);

        return new LayoutDto
        {
            LayoutType = entity.LayoutType,
            LayoutKey = entity.LayoutKey,
            UserName = entity.UserName,
            LayoutData = layoutData
        };
    }
}
