<?php

namespace Functional\Programs\Http\Controllers;

use Functional\Programs\Http\Requests\StoreProgramRequest;
use Functional\Programs\Http\Requests\UpdateProgramRequest;
use Functional\Programs\Http\Resources\ProgramResource;
use Functional\Programs\Models\Program;
use Functional\Programs\Services\ProgramService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
use Illuminate\Http\Response as HttpResponse;
use Symfony\Component\HttpFoundation\Response;

/**
 * CRUD des programmes de l'utilisateur authentifié, strictement scopés par auth()->id().
 */
class ProgramsController
{
    public function __construct(
        private readonly ProgramService $programService,
    ) {
    }

    /** GET /api/programs */
    public function index(): AnonymousResourceCollection
    {
        $programs = Program::query()
            ->where('user_id', auth()->id())
            ->with('programSlots')
            ->orderBy('name')
            ->paginate();

        return ProgramResource::collection($programs);
    }

    /** POST /api/programs */
    public function store(StoreProgramRequest $request): JsonResponse
    {
        $program = $this->programService->create($request->user(), $request->validated());

        return (new ProgramResource($program))
            ->response()
            ->setStatusCode(Response::HTTP_CREATED);
    }

    /** GET /api/programs/{program} */
    public function show(int $program): ProgramResource
    {
        return new ProgramResource($this->findForUser($program));
    }

    /** PUT /api/programs/{program} */
    public function update(UpdateProgramRequest $request, int $program): ProgramResource
    {
        $updated = $this->programService->update($this->findForUser($program), $request->validated());

        return new ProgramResource($updated);
    }

    /** DELETE /api/programs/{program} */
    public function destroy(int $program): HttpResponse
    {
        $this->findForUser($program)->delete();

        return response()->noContent();
    }

    /** Charge le programme (avec son planning) en le scopant strictement à l'utilisateur courant. */
    private function findForUser(int $programId): Program
    {
        return Program::query()
            ->where('user_id', auth()->id())
            ->with('programSlots')
            ->findOrFail($programId);
    }
}
