using MealPlan.Api.DTOs.IngredientCatalog;
using MealPlan.Api.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace MealPlan.Api.Controllers;

[ApiController]
[Route("api/ingredient-catalog")]
[Authorize]
public class IngredientCatalogController : ControllerBase
{
    private readonly IIngredientCatalogService _catalogService;

    public IngredientCatalogController(IIngredientCatalogService catalogService) =>
        _catalogService = catalogService;

    [HttpGet("categories")]
    [ProducesResponseType(typeof(IReadOnlyList<IngredientCategoryDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetCategories(CancellationToken ct)
    {
        var categories = await _catalogService.GetCategoriesAsync(ct);
        return Ok(categories);
    }

    [HttpGet]
    [ProducesResponseType(typeof(IReadOnlyList<IngredientNutritionItemDto>), StatusCodes.Status200OK)]
    public async Task<IActionResult> GetItems(
        [FromQuery] string? category,
        [FromQuery] string? search,
        CancellationToken ct)
    {
        var items = await _catalogService.GetItemsAsync(category, search, ct);
        return Ok(items);
    }

    [HttpGet("{id:int}")]
    [ProducesResponseType(typeof(IngredientNutritionItemDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> GetItem(int id, CancellationToken ct)
    {
        var item = await _catalogService.GetItemByIdAsync(id, ct);
        return item is null ? NotFound(new { error = $"Ingredient catalog item {id} was not found." }) : Ok(item);
    }

    [HttpPost]
    [ProducesResponseType(typeof(IngredientNutritionItemDto), StatusCodes.Status201Created)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    public async Task<IActionResult> CreateItem([FromBody] UpsertIngredientNutritionItemDto dto, CancellationToken ct)
    {
        var item = await _catalogService.CreateItemAsync(dto, ct);
        return item is null
            ? BadRequest(new { error = "Invalid category or payload." })
            : CreatedAtAction(nameof(GetItem), new { id = item.Id }, item);
    }

    [HttpPut("{id:int}")]
    [ProducesResponseType(typeof(IngredientNutritionItemDto), StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> UpdateItem(int id, [FromBody] UpsertIngredientNutritionItemDto dto, CancellationToken ct)
    {
        var item = await _catalogService.UpdateItemAsync(id, dto, ct);
        return item is null
            ? NotFound(new { error = $"Ingredient catalog item {id} was not found." })
            : Ok(item);
    }

    [HttpDelete("{id:int}")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    public async Task<IActionResult> DeleteItem(int id, CancellationToken ct)
    {
        var deleted = await _catalogService.DeleteItemAsync(id, ct);
        return deleted ? NoContent() : NotFound(new { error = $"Ingredient catalog item {id} was not found." });
    }
}
