using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using ROLAC.API.Authorization;
using ROLAC.API.DTOs.Expense;
using ROLAC.API.Services;
using ROLAC.API.Services.Ai;

namespace ROLAC.API.Controllers;

[ApiController]
[Route("api/expense-categories")]
[Authorize]   // read (GetAll) is open to any authenticated user — the member self-service
              // reimbursement form needs the category list. Write actions are finance-only below.
public class ExpenseCategoriesController : ControllerBase
{
    private readonly IExpenseCategoryService _svc;
    private readonly IExpenseCategoryAiServiceFactory _aiFactory;
    public ExpenseCategoriesController(IExpenseCategoryService svc, IExpenseCategoryAiServiceFactory aiFactory)
    {
        _svc = svc;
        _aiFactory = aiFactory;
    }

    [HttpGet]
    public async Task<IActionResult> GetAll([FromQuery] bool includeInactive = false)
        => Ok(await _svc.GetAllAsync(includeInactive));

    // Suggest an English name + Form 990 line for a category being defined. Write-gated: category
    // editing is finance/admin-only, unlike the member-facing expense-ai/assist endpoint.
    [HttpPost("ai-suggest")]
    [HasPermission(Modules.ExpenseCategories, PermissionActions.Write)]
    public async Task<IActionResult> AiSuggest([FromBody] ExpenseCategoryAiRequest r, CancellationToken ct)
    {
        if (string.IsNullOrWhiteSpace(r.Name_zh) && string.IsNullOrWhiteSpace(r.Name_en))
            return BadRequest("A name is required.");

        var svc = await _aiFactory.ResolveAsync(ct);
        return Ok(await svc.SuggestAsync(r, ct));
    }

    [HttpPost("groups")]
    [HasPermission(Modules.ExpenseCategories, PermissionActions.Write)]
    public async Task<IActionResult> CreateGroup([FromBody] CreateExpenseGroupRequest r)
        => Ok(new { id = await _svc.CreateGroupAsync(r) });

    [HttpPut("groups/{id:int}")]
    [HasPermission(Modules.ExpenseCategories, PermissionActions.Write)]
    public async Task<IActionResult> UpdateGroup(int id, [FromBody] UpdateExpenseGroupRequest r)
    { try { await _svc.UpdateGroupAsync(id, r); return NoContent(); } catch (KeyNotFoundException) { return NotFound(); } }

    [HttpDelete("groups/{id:int}")]
    [HasPermission(Modules.ExpenseCategories, PermissionActions.Delete)]
    public async Task<IActionResult> DeactivateGroup(int id)
    { try { await _svc.DeactivateGroupAsync(id); return NoContent(); } catch (KeyNotFoundException) { return NotFound(); } }

    [HttpPost("subcategories")]
    [HasPermission(Modules.ExpenseCategories, PermissionActions.Write)]
    public async Task<IActionResult> CreateSub([FromBody] CreateExpenseSubCategoryRequest r)
    { try { return Ok(new { id = await _svc.CreateSubCategoryAsync(r) }); } catch (KeyNotFoundException) { return NotFound(); } }

    [HttpPut("subcategories/{id:int}")]
    [HasPermission(Modules.ExpenseCategories, PermissionActions.Write)]
    public async Task<IActionResult> UpdateSub(int id, [FromBody] UpdateExpenseSubCategoryRequest r)
    { try { await _svc.UpdateSubCategoryAsync(id, r); return NoContent(); } catch (KeyNotFoundException) { return NotFound(); } }

    [HttpDelete("subcategories/{id:int}")]
    [HasPermission(Modules.ExpenseCategories, PermissionActions.Delete)]
    public async Task<IActionResult> DeactivateSub(int id)
    { try { await _svc.DeactivateSubCategoryAsync(id); return NoContent(); } catch (KeyNotFoundException) { return NotFound(); } }
}
