using ERPCore.Domain.Enums;
using ERPCore.Dtos.Categories;
using ERPCore.Dtos.Common;
using ERPCore.Services.Interfaces;
using Microsoft.AspNetCore.Mvc;

namespace ERPCore.Controllers;

/// <summary>
/// Category endpoints (docs/11-BACKEND-PHASE1.md §2.3), including the subcategories
/// nested beneath each category. The hierarchy is exactly two levels deep — the old
/// <c>?tree=true</c> parameter is gone along with the self-nesting model.
/// </summary>
[Route("api/v1/categories")]
public sealed class CategoriesController : ApiControllerBase
{
    private readonly ICategoryService _categories;

    public CategoriesController(ICategoryService categories) => _categories = categories;

    [HttpGet]
    [ProducesResponseType(typeof(PagedResponse<CategoryDto>), StatusCodes.Status200OK)]
    public async Task<ActionResult<PagedResponse<CategoryDto>>> List(
        [FromQuery] PageQuery query, [FromQuery] EntityStatus? status, CancellationToken ct)
        => Ok(await _categories.ListAsync(query, status, ct));

    [HttpGet("{categoryId:int}")]
    [ProducesResponseType(typeof(CategoryDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<CategoryDto>> GetById(int categoryId, CancellationToken ct)
    {
        var result = await _categories.GetAsync(categoryId, ct);
        if (result is null) return NotFound();

        SetETag(result.RowVersion);
        return Ok(result.Value);
    }

    [HttpPost]
    [ProducesResponseType(typeof(CategoryDto), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    public async Task<ActionResult<CategoryDto>> Create([FromBody] CreateCategoryRequest request, CancellationToken ct)
    {
        var result = await _categories.CreateAsync(request, ct);
        SetETag(result.RowVersion);
        return Created($"/api/v1/categories/{result.Value.CategoryId}", result.Value);
    }

    [HttpPut("{categoryId:int}")]
    [ProducesResponseType(typeof(CategoryDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    [ProducesResponseType(StatusCodes.Status412PreconditionFailed)]
    public async Task<ActionResult<CategoryDto>> Update(
        int categoryId, [FromBody] UpdateCategoryRequest request, CancellationToken ct)
    {
        var expected = RequireIfMatch();
        var result = await _categories.UpdateAsync(categoryId, request, expected, ct);
        SetETag(result.RowVersion);
        return Ok(result.Value);
    }

    /// <summary>Deactivate/reactivate. Masters are never hard-deleted (FR-MD-08).</summary>
    [HttpPatch("{categoryId:int}/status")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> SetStatus(
        int categoryId, [FromBody] UpdateCategoryStatusRequest request, CancellationToken ct)
    {
        await _categories.SetStatusAsync(categoryId, request.Status, ct);
        return NoContent();
    }

    // Subcategories — nested under their parent category (docs/11 §2.3).
    // Updates live on SubCategoriesController at /api/v1/subcategories/{id}.

    [HttpGet("{categoryId:int}/subcategories")]
    [ProducesResponseType(typeof(PagedResponse<SubCategoryDto>), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<ActionResult<PagedResponse<SubCategoryDto>>> ListSubCategories(
        int categoryId, [FromQuery] PageQuery query, [FromQuery] EntityStatus? status, CancellationToken ct)
        => Ok(await _categories.ListSubCategoriesAsync(categoryId, query, status, ct));

    [HttpPost("{categoryId:int}/subcategories")]
    [ProducesResponseType(typeof(SubCategoryDto), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status409Conflict)]
    [ProducesResponseType(StatusCodes.Status422UnprocessableEntity)]
    public async Task<ActionResult<SubCategoryDto>> CreateSubCategory(
        int categoryId, [FromBody] CreateSubCategoryRequest request, CancellationToken ct)
    {
        var result = await _categories.CreateSubCategoryAsync(categoryId, request, ct);
        SetETag(result.RowVersion);
        return Created($"/api/v1/subcategories/{result.Value.SubCategoryId}", result.Value);
    }
}
