<?php

namespace App\Branch\Entity;

use App\Branch\Repository\RoomRepository;
use App\Doctor\Entity\DoctorAddress;
use App\Shared\Tenant\TenantOwnedTrait;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;

/**
 * اتاق یک شعبه. برخلاف {@see BranchWorkingHours} جفت محیط دارد، چون uuidش از request
 * می‌آید و بدون جفت، TenantFilter نمی‌تواند اتاق محیط دیگر را پنهان کند.
 *
 * جفت در سازنده از خودِ آدرس مشتق می‌شود نه از بدنهٔ درخواست — پس هیچ نقطهٔ ساختی
 * نمی‌تواند فراموشش کند و کلاینت هم نمی‌تواند اتاقی را به محیط دیگری بچسباند.
 *
 * capacity یعنی چند بیمار هم‌زمان: اتاق تزریق سه‌تخته «یک منبع با ظرفیت ۳» است، نه
 * سه منبع (بند ۶ مستند). تسک ۰۲ همین معنا را روی Resource تکرار می‌کند.
 */
#[ORM\Entity(repositoryClass: RoomRepository::class)]
#[ORM\Table(name: 'rooms')]
#[ORM\Index(columns: ['entity_type', 'entity_id', 'active'], name: 'idx_rooms_tenant')]
#[ORM\Index(columns: ['address_id', 'active'], name: 'idx_rooms_address')]
class Room
{
    use TenantOwnedTrait;

    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private ?int $id = null;

    #[ORM\Column(type: 'string', length: 36, unique: true)]
    private string $uuid;

    #[ORM\ManyToOne(targetEntity: DoctorAddress::class)]
    #[ORM\JoinColumn(name: 'address_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
    private DoctorAddress $address;

    #[ORM\Column(type: 'string', length: 120)]
    private string $name;

    /** متن آزاد — نوع اتاق را خود کلینیک تعریف می‌کند، نه یک enum سراسری */
    #[ORM\Column(name: 'room_type', type: 'string', length: 60, nullable: true)]
    private ?string $roomType = null;

    #[ORM\Column(type: 'smallint', options: ['default' => 1])]
    private int $capacity = 1;

    #[ORM\Column(type: 'string', length: 20, nullable: true)]
    private ?string $floor = null;

    #[ORM\Column(type: 'boolean', options: ['default' => true])]
    private bool $active = true;

    #[ORM\Column(name: 'created_at', type: 'integer')]
    private int $createdAt;

    #[ORM\Column(name: 'updated_at', type: 'integer')]
    private int $updatedAt;

    public function __construct(DoctorAddress $address, string $name)
    {
        $this->uuid      = Uuid::v4()->toRfc4122();
        $this->address   = $address;
        $this->name      = $name;
        $this->createdAt = time();
        $this->updatedAt = time();

        $this->assignTenantPair($address->tenantEntityType(), $address->tenantEntityId());
    }

    public function getId(): ?int                { return $this->id; }
    public function getUuid(): string            { return $this->uuid; }
    public function getAddress(): DoctorAddress  { return $this->address; }
    public function getName(): string            { return $this->name; }
    public function getRoomType(): ?string       { return $this->roomType; }
    public function getCapacity(): int           { return $this->capacity; }
    public function getFloor(): ?string          { return $this->floor; }
    public function isActive(): bool             { return $this->active; }
    public function getCreatedAt(): int          { return $this->createdAt; }
    public function getUpdatedAt(): int          { return $this->updatedAt; }

    public function setName(string $v): self      { $this->name = $v; $this->touch(); return $this; }
    public function setRoomType(?string $v): self { $this->roomType = $v; $this->touch(); return $this; }
    public function setFloor(?string $v): self    { $this->floor = $v; $this->touch(); return $this; }
    public function setActive(bool $v): self      { $this->active = $v; $this->touch(); return $this; }

    /** @throws \InvalidArgumentException روی ظرفیت کمتر از ۱ */
    public function setCapacity(int $v): self
    {
        if ($v < 1) {
            throw new \InvalidArgumentException('Room capacity must be at least 1.');
        }

        $this->capacity = $v;
        $this->touch();

        return $this;
    }

    private function touch(): void { $this->updatedAt = time(); }

    public function toArray(): array
    {
        return [
            'uuid'         => $this->uuid,
            'address_uuid' => $this->address->getUuid(),
            'address_name' => $this->address->getName(),
            'name'         => $this->name,
            'room_type'    => $this->roomType,
            'capacity'     => $this->capacity,
            'floor'        => $this->floor,
            'active'       => $this->active,
            'created_at'   => $this->createdAt,
            'updated_at'   => $this->updatedAt,
        ];
    }
}
