<?php

namespace App\Rating\Entity;

use App\Auth\Entity\User;
use App\Doctor\Entity\Doctor;
use Doctrine\ORM\Mapping as ORM;
use App\Rating\Repository\RateRepository;
use Symfony\Component\Uid\Uuid;

#[ORM\Entity(repositoryClass: RateRepository::class)]
#[ORM\Table(name: 'rates')]
#[ORM\UniqueConstraint(name: 'idx_rates_user_doctor', columns: ['user_id', 'doctor_id'])]
class Rate
{
    /** Dimension column => Persian label. Drives the public aggregate response. */
    public const DIMENSIONS = [
        'waiting_time_at_clinic' => 'زمان انتظار در مطب',
        'accuracy_of_diagnosis'  => 'تشخیص درست',
        'doctor_behavior'        => 'برخورد مناسب پزشک',
        'clinic_cleanliness'     => 'نظافت مطب',
        'doctor_expertise'       => 'مهارت پزشک',
    ];

    #[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: User::class)]
    #[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id', nullable: false, onDelete: 'CASCADE')]
    private User $user;

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

    #[ORM\Column(name: 'waiting_time_at_clinic', type: 'smallint')]
    private int $waitingTimeAtClinic = 0;

    #[ORM\Column(name: 'accuracy_of_diagnosis', type: 'smallint')]
    private int $accuracyOfDiagnosis = 0;

    #[ORM\Column(name: 'doctor_behavior', type: 'smallint')]
    private int $doctorBehavior = 0;

    #[ORM\Column(name: 'clinic_cleanliness', type: 'smallint')]
    private int $clinicCleanliness = 0;

    #[ORM\Column(name: 'doctor_expertise', type: 'smallint')]
    private int $doctorExpertise = 0;

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

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

    /** @param array<string,int> $dimensions keyed by DIMENSIONS keys (0–100) */
    public function __construct(User $user, Doctor $doctor, array $dimensions)
    {
        $this->uuid      = Uuid::v4()->toRfc4122();
        $this->user      = $user;
        $this->doctor    = $doctor;
        $this->createdAt = time();
        $this->updatedAt = time();
        $this->setDimensions($dimensions);
    }

    public function getId(): ?int       { return $this->id; }
    public function getUuid(): string   { return $this->uuid; }
    public function getUser(): User     { return $this->user; }
    public function getDoctor(): Doctor { return $this->doctor; }

    public function getWaitingTimeAtClinic(): int { return $this->waitingTimeAtClinic; }
    public function getAccuracyOfDiagnosis(): int { return $this->accuracyOfDiagnosis; }
    public function getDoctorBehavior(): int      { return $this->doctorBehavior; }
    public function getClinicCleanliness(): int   { return $this->clinicCleanliness; }
    public function getDoctorExpertise(): int     { return $this->doctorExpertise; }

    /** @param array<string,int> $dimensions keyed by DIMENSIONS keys (0–100) */
    public function setDimensions(array $dimensions): self
    {
        $clamp = static fn($v) => max(0, min(100, (int) $v));
        $this->waitingTimeAtClinic = $clamp($dimensions['waiting_time_at_clinic'] ?? $this->waitingTimeAtClinic);
        $this->accuracyOfDiagnosis = $clamp($dimensions['accuracy_of_diagnosis'] ?? $this->accuracyOfDiagnosis);
        $this->doctorBehavior      = $clamp($dimensions['doctor_behavior'] ?? $this->doctorBehavior);
        $this->clinicCleanliness   = $clamp($dimensions['clinic_cleanliness'] ?? $this->clinicCleanliness);
        $this->doctorExpertise     = $clamp($dimensions['doctor_expertise'] ?? $this->doctorExpertise);
        $this->updatedAt           = time();
        return $this;
    }

    /** Overall percentage (0–100): mean of the five dimensions. */
    public function overallPercent(): float
    {
        return (
            $this->waitingTimeAtClinic
            + $this->accuracyOfDiagnosis
            + $this->doctorBehavior
            + $this->clinicCleanliness
            + $this->doctorExpertise
        ) / 5;
    }
}
