using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using MealPlanner.Services; namespace MealPlanner.Controllers; [ApiController] [Route("api/mealplans")] [Authorize] public class MealPlanController(MealPlanService mealPlanService) : ControllerBase { private string UserId => User.FindFirst("sub")?.Value ?? throw new UnauthorizedAccessException(); public record GenerateRequest(string? WeekStart); public record SwapRequest(Guid RecipeId); [HttpPost("generate")] public async Task Generate([FromBody] GenerateRequest? body) { DateOnly weekStart; if (body?.WeekStart is not null && DateOnly.TryParse(body.WeekStart, out var parsed)) { weekStart = MealPlanService.GetWeekStart(parsed); } else { weekStart = MealPlanService.GetWeekStart(DateOnly.FromDateTime(DateTime.UtcNow)); } var plan = await mealPlanService.GenerateWeekPlanAsync(UserId, weekStart); return Ok(plan); } [HttpGet("current")] public async Task GetCurrent() { var plan = await mealPlanService.GetCurrentPlanAsync(UserId); if (plan is null) return NotFound(); return Ok(plan); } [HttpGet("{weekStart}")] public async Task GetByWeek(string weekStart) { if (!DateOnly.TryParse(weekStart, out var date)) return BadRequest("Invalid date format."); var plan = await mealPlanService.GetPlanAsync(UserId, date); if (plan is null) return NotFound(); return Ok(plan); } [HttpPut("entries/{entryId:guid}/swap")] public async Task SwapEntry(Guid entryId, [FromBody] SwapRequest body) { try { var updated = await mealPlanService.SwapEntryAsync(entryId, body.RecipeId, UserId); if (updated is null) return NotFound(); return Ok(updated); } catch (UnauthorizedAccessException) { return Forbid(); } } [HttpPost("entries/{entryId:guid}/reroll")] public async Task RerollEntry(Guid entryId) { try { var updated = await mealPlanService.RerollEntryAsync(entryId, UserId); if (updated is null) return StatusCode(503, "Could not fetch a new recipe. Try again."); return Ok(updated); } catch (UnauthorizedAccessException) { return Forbid(); } } }