<?php

namespace App\Course\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * پارامترهای یک جلسه از پروتکل — «جلسهٔ ۳: انرژی ۱۶».
 *
 * `params` عمداً آزاد است چون هر تخصص پارامتر خودش را دارد (انرژی، دوز، ضخامت)، ولی
 * فقط اسکالر و **هیچ منطقی به مقدارش وابسته نیست**: فقط کپی و نمایش می‌شود. لحظه‌ای
 * که کدی روی `params['energy']` شرط بگذارد، این آزادی به بدهی تبدیل می‌شود.
 */
#[ORM\Entity]
#[ORM\Table(name: 'course_protocol_steps')]
#[ORM\UniqueConstraint(name: 'uniq_step', columns: ['protocol_id', 'session_number'])]
class CourseProtocolStep
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private ?int $id = null;

    #[ORM\ManyToOne(targetEntity: CourseProtocol::class, inversedBy: 'steps')]
    #[ORM\JoinColumn(name: 'protocol_id', nullable: false, onDelete: 'CASCADE')]
    private CourseProtocol $protocol;

    #[ORM\Column(name: 'session_number', type: 'smallint')]
    private int $sessionNumber;

    /** @var array<string, scalar> */
    #[ORM\Column(type: 'json', nullable: true)]
    private ?array $params = null;

    #[ORM\Column(name: 'override_duration_minutes', type: 'smallint', nullable: true)]
    private ?int $overrideDurationMinutes = null;

    /** @param array<string, mixed> $params */
    public function __construct(CourseProtocol $protocol, int $sessionNumber, array $params = [], ?int $overrideDuration = null)
    {
        $this->protocol      = $protocol;
        $this->sessionNumber = $sessionNumber;
        $this->params        = self::scalarsOnly($params);
        $this->overrideDurationMinutes = $overrideDuration;

        $protocol->addStep($this);
    }

    /** تودرتویی پذیرفته نمی‌شود: پارامتری که ساختار دارد، منطق پنهان دارد. */
    private static function scalarsOnly(array $params): array
    {
        return array_filter($params, static fn (mixed $v): bool => is_scalar($v) || $v === null);
    }

    public function getId(): ?int              { return $this->id; }
    public function getProtocol(): CourseProtocol { return $this->protocol; }
    public function getSessionNumber(): int    { return $this->sessionNumber; }
    public function getParams(): array         { return $this->params ?? []; }
    public function getOverrideDurationMinutes(): ?int { return $this->overrideDurationMinutes; }

    /** @return array<string, mixed> */
    public function toArray(): array
    {
        return [
            'session_number'            => $this->sessionNumber,
            'params'                    => (object) ($this->params ?? []),
            'override_duration_minutes' => $this->overrideDurationMinutes,
        ];
    }
}
