using Apollinare.API.Modules.Warehouse.Services;
using Apollinare.Domain.Entities.Warehouse;
using Microsoft.AspNetCore.Mvc;

namespace Apollinare.API.Modules.Warehouse.Controllers;

/// <summary>
/// Controller per la gestione delle categorie articoli
/// </summary>
[ApiController]
[Route("api/warehouse/categories")]
public class WarehouseCategoriesController : ControllerBase
{
    private readonly IWarehouseService _warehouseService;
    private readonly ILogger<WarehouseCategoriesController> _logger;

    public WarehouseCategoriesController(
        IWarehouseService warehouseService,
        ILogger<WarehouseCategoriesController> logger)
    {
        _warehouseService = warehouseService;
        _logger = logger;
    }

    /// <summary>
    /// Ottiene la lista delle categorie
    /// </summary>
    [HttpGet]
    public async Task<ActionResult<List<CategoryDto>>> GetCategories([FromQuery] bool includeInactive = false)
    {
        var categories = await _warehouseService.GetCategoriesAsync(includeInactive);
        return Ok(categories.Select(MapToDto));
    }

    /// <summary>
    /// Ottiene le categorie in formato albero
    /// </summary>
    [HttpGet("tree")]
    public async Task<ActionResult<List<CategoryTreeDto>>> GetCategoryTree()
    {
        var categories = await _warehouseService.GetCategoryTreeAsync();
        return Ok(categories.Select(MapToTreeDto));
    }

    /// <summary>
    /// Ottiene una categoria per ID
    /// </summary>
    [HttpGet("{id}")]
    public async Task<ActionResult<CategoryDto>> GetCategory(int id)
    {
        var category = await _warehouseService.GetCategoryByIdAsync(id);
        if (category == null)
            return NotFound();

        return Ok(MapToDto(category));
    }

    /// <summary>
    /// Crea una nuova categoria
    /// </summary>
    [HttpPost]
    public async Task<ActionResult<CategoryDto>> CreateCategory([FromBody] CreateCategoryDto dto)
    {
        try
        {
            var category = new WarehouseArticleCategory
            {
                Code = dto.Code,
                Name = dto.Name,
                Description = dto.Description,
                ParentCategoryId = dto.ParentCategoryId,
                Icon = dto.Icon,
                Color = dto.Color,
                DefaultValuationMethod = dto.DefaultValuationMethod,
                SortOrder = dto.SortOrder,
                Notes = dto.Notes,
                IsActive = true
            };

            var created = await _warehouseService.CreateCategoryAsync(category);
            return CreatedAtAction(nameof(GetCategory), new { id = created.Id }, MapToDto(created));
        }
        catch (ArgumentException ex)
        {
            return NotFound(new { error = ex.Message });
        }
        catch (InvalidOperationException ex)
        {
            return BadRequest(new { error = ex.Message });
        }
    }

    /// <summary>
    /// Aggiorna una categoria esistente
    /// </summary>
    [HttpPut("{id}")]
    public async Task<ActionResult<CategoryDto>> UpdateCategory(int id, [FromBody] UpdateCategoryDto dto)
    {
        try
        {
            var existing = await _warehouseService.GetCategoryByIdAsync(id);
            if (existing == null)
                return NotFound();

            existing.Code = dto.Code;
            existing.Name = dto.Name;
            existing.Description = dto.Description;
            existing.Icon = dto.Icon;
            existing.Color = dto.Color;
            existing.DefaultValuationMethod = dto.DefaultValuationMethod;
            existing.SortOrder = dto.SortOrder;
            existing.IsActive = dto.IsActive;
            existing.Notes = dto.Notes;

            var updated = await _warehouseService.UpdateCategoryAsync(existing);
            return Ok(MapToDto(updated));
        }
        catch (InvalidOperationException ex)
        {
            return BadRequest(new { error = ex.Message });
        }
    }

    /// <summary>
    /// Elimina una categoria
    /// </summary>
    [HttpDelete("{id}")]
    public async Task<ActionResult> DeleteCategory(int id)
    {
        try
        {
            await _warehouseService.DeleteCategoryAsync(id);
            return NoContent();
        }
        catch (ArgumentException ex)
        {
            return NotFound(new { error = ex.Message });
        }
        catch (InvalidOperationException ex)
        {
            return BadRequest(new { error = ex.Message });
        }
    }

    #region DTOs

    public record CategoryDto(
        int Id,
        string Code,
        string Name,
        string? Description,
        int? ParentCategoryId,
        string? ParentCategoryName,
        int Level,
        string? FullPath,
        string? Icon,
        string? Color,
        ValuationMethod? DefaultValuationMethod,
        int SortOrder,
        bool IsActive,
        string? Notes,
        DateTime? CreatedAt,
        DateTime? UpdatedAt
    );

    public record CategoryTreeDto(
        int Id,
        string Code,
        string Name,
        string? Description,
        int Level,
        string? FullPath,
        string? Icon,
        string? Color,
        bool IsActive,
        List<CategoryTreeDto> Children
    );

    public record CreateCategoryDto(
        string Code,
        string Name,
        string? Description,
        int? ParentCategoryId,
        string? Icon,
        string? Color,
        ValuationMethod? DefaultValuationMethod,
        int SortOrder,
        string? Notes
    );

    public record UpdateCategoryDto(
        string Code,
        string Name,
        string? Description,
        string? Icon,
        string? Color,
        ValuationMethod? DefaultValuationMethod,
        int SortOrder,
        bool IsActive,
        string? Notes
    );

    #endregion

    #region Mapping

    private static CategoryDto MapToDto(WarehouseArticleCategory category) => new(
        category.Id,
        category.Code,
        category.Name,
        category.Description,
        category.ParentCategoryId,
        category.ParentCategory?.Name,
        category.Level,
        category.FullPath,
        category.Icon,
        category.Color,
        category.DefaultValuationMethod,
        category.SortOrder,
        category.IsActive,
        category.Notes,
        category.CreatedAt,
        category.UpdatedAt
    );

    private static CategoryTreeDto MapToTreeDto(WarehouseArticleCategory category) => new(
        category.Id,
        category.Code,
        category.Name,
        category.Description,
        category.Level,
        category.FullPath,
        category.Icon,
        category.Color,
        category.IsActive,
        category.ChildCategories.Select(MapToTreeDto).ToList()
    );

    #endregion
}
