<?php

namespace App\Patient\Entity;

use App\Auth\Entity\User;
use App\Patient\Repository\PatientRecordRepository;
use App\Tag\Entity\TenantTag;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;

#[ORM\Entity(repositoryClass: PatientRecordRepository::class)]
#[ORM\Table(name: 'patient_records')]
#[ORM\UniqueConstraint(name: 'uniq_patient_record', columns: ['entity_type', 'entity_id', 'user_id'])]
class PatientRecord
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column(type: 'integer')]
    private ?int $id = null;

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

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

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

    #[ORM\ManyToOne(targetEntity: User::class)]
    #[ORM\JoinColumn(nullable: false, onDelete: 'RESTRICT')]
    private User $user;

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

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

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

    // Clinic-scoped case-file number. Patient identity/demographics (gender,
    // date_of_birth, referral_source, description, insurance, …) live on the
    // patient's UserProfile and are set via PATCH /patient/{uuid}.
    #[ORM\Column(name: 'record_number', type: 'string', length: 40, nullable: true)]
    private ?string $recordNumber = null;

    /**
     * @var Collection<int, TenantTag> record labels. EAGER so the typed
     * collection is always hydrated (see ServiceItem for the same pitfall).
     */
    #[ORM\ManyToMany(targetEntity: TenantTag::class, fetch: 'EAGER')]
    #[ORM\JoinTable(name: 'patient_record_tags')]
    private Collection $tags;

    #[ORM\OneToMany(targetEntity: PatientSession::class, mappedBy: 'record', cascade: ['remove'])]
    private Collection $sessions;

    public function __construct(string $entityType, int $entityId, User $user, string $createdByType, int $createdById)
    {
        $this->uuid          = Uuid::v4()->toRfc4122();
        $this->entityType    = $entityType;
        $this->entityId      = $entityId;
        $this->user          = $user;
        $this->createdByType = $createdByType;
        $this->createdById   = $createdById;
        $this->createdAt     = time();
        $this->sessions      = new ArrayCollection();
        $this->tags          = new ArrayCollection();
    }

    public function getId(): ?int          { return $this->id; }
    public function getUuid(): string      { return $this->uuid; }
    public function getEntityType(): string { return $this->entityType; }
    public function getEntityId(): int     { return $this->entityId; }
    public function getUser(): User        { return $this->user; }
    public function getCreatedByType(): string { return $this->createdByType; }
    public function getCreatedById(): int  { return $this->createdById; }
    public function getCreatedAt(): int    { return $this->createdAt; }

    public function getRecordNumber(): ?string   { return $this->recordNumber; }
    public function setRecordNumber(?string $v): self   { $this->recordNumber = $v; return $this; }

    /** @return Collection<int, TenantTag> */
    public function getTags(): Collection
    {
        // Doctrine hydrates without the constructor; guard the typed property.
        return $this->tags ??= new ArrayCollection();
    }

    /** @param TenantTag[] $tags */
    public function setTags(array $tags): self
    {
        $collection = $this->getTags();
        $collection->clear();
        foreach ($tags as $t) {
            if (!$collection->contains($t)) {
                $collection->add($t);
            }
        }
        return $this;
    }

    public function toArray(): array
    {
        return [
            'uuid'             => $this->uuid,
            'entity_type'      => $this->entityType,
            'entity_id'        => $this->entityId,
            'user_uuid'        => $this->user->getUuid(),
            'user_name'          => $this->user->getRealName(),
            'user_mobile'        => $this->user->getMobileNumber(),
            'user_national_code' => $this->user->getNationalCode(),
            'record_number'    => $this->recordNumber,
            'tags'             => array_map(
                fn(TenantTag $t) => $t->toArray(),
                array_values($this->getTags()->toArray())
            ),
            'created_by_type'  => $this->createdByType,
            'created_at'       => $this->createdAt,
        ];
    }
}
