<?php

declare(strict_types=1);

namespace App\Administration\Infrastructure\Api\Resource;

use ApiPlatform\Metadata\ApiProperty;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use App\Administration\Domain\Model\SchoolCalendar\SchoolCalendar;
use App\Administration\Infrastructure\Api\Processor\AddPedagogicalDayProcessor;
use App\Administration\Infrastructure\Api\Processor\ConfigureCalendarProcessor;
use App\Administration\Infrastructure\Api\Provider\CalendarProvider;
use App\Administration\Infrastructure\Api\Provider\IsSchoolDayProvider;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * API Resource pour la gestion du calendrier scolaire.
 *
 * @see FR80 - Configurer jours fériés et vacances scolaires
 */
#[ApiResource(
    shortName: 'Calendar',
    operations: [
        new Get(
            uriTemplate: '/academic-years/{academicYearId}/calendar',
            provider: CalendarProvider::class,
            name: 'get_calendar',
        ),
        new Put(
            uriTemplate: '/academic-years/{academicYearId}/calendar',
            read: false,
            processor: ConfigureCalendarProcessor::class,
            name: 'configure_calendar',
        ),
        new Post(
            uriTemplate: '/academic-years/{academicYearId}/calendar/import-official',
            read: false,
            processor: ConfigureCalendarProcessor::class,
            name: 'import_official_holidays',
        ),
        new Post(
            uriTemplate: '/academic-years/{academicYearId}/calendar/pedagogical-day',
            read: false,
            processor: AddPedagogicalDayProcessor::class,
            name: 'add_pedagogical_day',
        ),
        new Get(
            uriTemplate: '/academic-years/{academicYearId}/calendar/is-school-day/{date}',
            provider: IsSchoolDayProvider::class,
            name: 'is_school_day',
        ),
    ],
)]
final class CalendarResource
{
    #[ApiProperty(identifier: true)]
    public ?string $academicYearId = null;

    #[Assert\Choice(choices: ['A', 'B', 'C'], message: 'La zone scolaire doit être A, B ou C.')]
    public ?string $zone = null;

    /** @var CalendarEntryItem[]|null */
    public ?array $entries = null;

    // Write-only for import-official
    #[ApiProperty(readable: false)]
    public ?string $importZone = null;

    // Write-only for pedagogical-day
    #[ApiProperty(readable: false)]
    #[Assert\Date(message: 'La date doit être au format YYYY-MM-DD.')]
    public ?string $date = null;

    #[ApiProperty(readable: false)]
    #[Assert\Length(min: 2, max: 100)]
    public ?string $label = null;

    #[ApiProperty(readable: false)]
    public ?string $description = null;

    // Read-only for is-school-day
    #[ApiProperty(writable: false)]
    public ?bool $isSchoolDay = null;

    #[ApiProperty(writable: false)]
    public ?string $reason = null;

    public static function fromCalendar(SchoolCalendar $calendar, string $academicYearId): self
    {
        $resource = new self();
        $resource->academicYearId = $academicYearId;
        $resource->zone = $calendar->zone?->value;
        $resource->entries = [];

        foreach ($calendar->entries() as $entry) {
            $item = new CalendarEntryItem();
            $item->id = (string) $entry->id;
            $item->type = $entry->type->value;
            $item->startDate = $entry->startDate->format('Y-m-d');
            $item->endDate = $entry->endDate->format('Y-m-d');
            $item->label = $entry->label;
            $item->description = $entry->description;
            $resource->entries[] = $item;
        }

        return $resource;
    }
}
