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

namespace ROLAC.API.Controllers;

// Snapshots are reusable vendor-payment templates — a finance tool. Every action requires
// Expenses:Write (super_admin bypasses), matching who can create vendor payments.
[ApiController]
[Route("api/expense-snapshots")]
[Authorize]
public class ExpenseSnapshotsController : ControllerBase
{
    private readonly IExpenseSnapshotService _svc;
    private readonly IPermissionService _perms;
    public ExpenseSnapshotsController(IExpenseSnapshotService svc, IPermissionService perms)
    {
        _svc = svc;
        _perms = perms;
    }

    private List<string> Roles() => User.FindAll("role").Select(claim => claim.Value).ToList();
    private bool IsSuperAdmin() => User.IsInRole(PermissionAuthorizationHandler.SuperAdminRole);
    private async Task<bool> CanManageAsync() =>
        IsSuperAdmin() || await _perms.HasPermissionAsync(Roles(), Modules.Expenses, PermissionActions.Write);

    [HttpGet]
    public async Task<IActionResult> GetAll()
    {
        if (!await CanManageAsync()) return Forbid();
        return Ok(await _svc.GetAllAsync());
    }

    [HttpGet("{id:int}")]
    public async Task<IActionResult> GetById(int id)
    {
        if (!await CanManageAsync()) return Forbid();
        var dto = await _svc.GetByIdAsync(id);
        return dto is null ? NotFound() : Ok(dto);
    }

    [HttpPost]
    public async Task<IActionResult> Create([FromBody] CreateExpenseSnapshotRequest r)
    {
        if (!await CanManageAsync()) return Forbid();
        try { return Ok(new { id = await _svc.CreateAsync(r) }); }
        catch (InvalidOperationException ex) { return Conflict(new { message = ex.Message }); }
    }

    [HttpPut("{id:int}")]
    public async Task<IActionResult> Update(int id, [FromBody] UpdateExpenseSnapshotRequest r)
    {
        if (!await CanManageAsync()) return Forbid();
        try { await _svc.UpdateAsync(id, r); return NoContent(); }
        catch (KeyNotFoundException) { return NotFound(); }
        catch (InvalidOperationException ex) { return Conflict(new { message = ex.Message }); }
    }

    [HttpDelete("{id:int}")]
    public async Task<IActionResult> Delete(int id)
    {
        if (!await CanManageAsync()) return Forbid();
        try { await _svc.DeleteAsync(id); return NoContent(); }
        catch (KeyNotFoundException) { return NotFound(); }
    }
}
