using Microsoft.AspNetCore.Mvc;
using TrajetKmTracker.Api.Models.DTOs;
using TrajetKmTracker.Api.Services;
using TrajetKmTracker.Api.Services.Exceptions;
namespace TrajetKmTracker.Api.Controllers;
///
/// Endpoints de gestion du barème kilométrique : consultation par année et CRUD des tranches.
/// La validation du non-chevauchement des tranches ([KmMin, KmMax]) par (année, puissance fiscale)
/// est appliquée à l'ajout et à la modification (Exigences 13.1–13.2).
///
[ApiController]
[Route("api/bareme")]
public class BaremeController : ControllerBase
{
private readonly IBaremeService _baremeService;
public BaremeController(IBaremeService baremeService)
{
_baremeService = baremeService;
}
/// Retourne toutes les tranches du barème pour l'année indiquée.
[HttpGet("{annee:int}")]
[ProducesResponseType(typeof(IReadOnlyList), StatusCodes.Status200OK)]
public async Task>> GetBareme(
int annee, CancellationToken cancellationToken)
{
var tranches = await _baremeService.GetBaremeAsync(annee, cancellationToken);
return Ok(tranches);
}
///
/// Ajoute une tranche du barème. Rejette (400) si l'intervalle chevauche une tranche existante
/// pour la même (année, puissance fiscale).
///
[HttpPost]
[ProducesResponseType(typeof(TrancheBaremeDto), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task> AddTranche(
[FromBody] SaveTrancheBaremeDto dto, CancellationToken cancellationToken)
{
try
{
var tranche = await _baremeService.AddTrancheAsync(dto, cancellationToken);
return CreatedAtAction(nameof(GetBareme), new { annee = tranche.Annee }, tranche);
}
catch (TranchesBaremeChevauchantesException ex)
{
return Problem(detail: ex.Message, statusCode: StatusCodes.Status400BadRequest);
}
}
///
/// Met à jour une tranche existante. Rejette (400) en cas de chevauchement, 404 si la tranche est absente.
///
[HttpPut("{id:int}")]
[ProducesResponseType(typeof(TrancheBaremeDto), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task> UpdateTranche(
int id, [FromBody] SaveTrancheBaremeDto dto, CancellationToken cancellationToken)
{
try
{
var tranche = await _baremeService.UpdateTrancheAsync(id, dto, cancellationToken);
return Ok(tranche);
}
catch (TrancheBaremeNotFoundException ex)
{
return Problem(detail: ex.Message, statusCode: StatusCodes.Status404NotFound);
}
catch (TranchesBaremeChevauchantesException ex)
{
return Problem(detail: ex.Message, statusCode: StatusCodes.Status400BadRequest);
}
}
/// Années pour lesquelles un barème (au moins une tranche) est défini, triées croissantes.
[HttpGet("annees-disponibles")]
[ProducesResponseType(typeof(IReadOnlyList), StatusCodes.Status200OK)]
public async Task>> GetAnneesDisponibles(CancellationToken cancellationToken)
{
var annees = await _baremeService.GetAnneesAvecBaremeAsync(cancellationToken);
return Ok(annees);
}
///
/// Copie le dernier barème connu (année la plus récente antérieure ayant un barème) vers
/// l'année cible. Remplace les tranches existantes de l'année cible (annule et remplace).
/// Retourne le nombre de tranches copiées (0 si aucun barème antérieur n'existe).
///
[HttpPost("copier/{anneeCible:int}")]
[ProducesResponseType(typeof(CopieBaremeResultDto), StatusCodes.Status200OK)]
public async Task> CopierDernierBareme(
int anneeCible, CancellationToken cancellationToken)
{
var nombre = await _baremeService.CopierDernierBaremeAsync(anneeCible, cancellationToken);
return Ok(new CopieBaremeResultDto(nombre));
}
/// Supprime une tranche du barème. Retourne 404 si la tranche est absente.
[HttpDelete("{id:int}")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task DeleteTranche(int id, CancellationToken cancellationToken)
{
try
{
await _baremeService.DeleteTrancheAsync(id, cancellationToken);
return NoContent();
}
catch (TrancheBaremeNotFoundException ex)
{
return Problem(detail: ex.Message, statusCode: StatusCodes.Status404NotFound);
}
}
}