<?php

namespace App\Secretary\Entity;

use App\Auth\Entity\User;
use App\Clinic\Entity\Clinic;
use App\Doctor\Entity\Doctor;
use App\Secretary\Repository\DoctorSecretaryRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;

#[ORM\Entity(repositoryClass: DoctorSecretaryRepository::class)]
#[ORM\Table(name: 'doctor_secretaries')]
#[ORM\UniqueConstraint(name: 'idx_doctor_secretary_scope', columns: ['doctor_id', 'secretary_id', 'owner_type'])]
class DoctorSecretary
{
    public const OWNER_DOCTOR = 'doctor';
    public const OWNER_CLINIC = 'clinic';

    public const DEFAULT_PERMISSIONS = [
        'version'   => 1,
        'resources' => [
            'appointments' => ['view' => true,  'create' => true,  'cancel' => false, 'update_status' => true],
            'addresses'    => ['view' => true,  'create' => false, 'update' => false, 'delete' => false],
            'clinic_info'  => ['view' => true,  'update' => false],
            'insurances'   => ['view' => true,  'create' => false, 'update' => false, 'delete' => false],
        ],
    ];

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

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

    #[ORM\Column(name: 'owner_type', type: 'string', length: 10, options: ['default' => 'doctor'])]
    private string $ownerType;

    #[ORM\ManyToOne(targetEntity: Clinic::class)]
    #[ORM\JoinColumn(name: 'clinic_id', referencedColumnName: 'id', nullable: true, onDelete: 'CASCADE')]
    private ?Clinic $clinic = null;

    #[ORM\Column(name: 'permission', type: 'json', nullable: true)]
    private ?array $permissions = null;

    #[ORM\Column(type: 'boolean')]
    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(Doctor $doctor, User $secretary, string $ownerType = self::OWNER_DOCTOR, ?Clinic $clinic = null)
    {
        $this->uuid        = Uuid::v4()->toRfc4122();
        $this->doctor      = $doctor;
        $this->secretary   = $secretary;
        $this->ownerType   = $ownerType;
        $this->clinic      = $clinic;
        $this->permissions = self::DEFAULT_PERMISSIONS;
        $this->createdAt   = time();
        $this->updatedAt   = time();
    }

    public function getId(): ?int         { return $this->id; }
    public function getUuid(): string     { return $this->uuid; }
    public function getDoctor(): Doctor   { return $this->doctor; }
    public function getSecretary(): User  { return $this->secretary; }
    public function getOwnerType(): string { return $this->ownerType; }
    public function getClinic(): ?Clinic  { return $this->clinic; }
    public function getPermissions(): array { return $this->permissions ?? self::DEFAULT_PERMISSIONS; }
    public function isActive(): bool      { return $this->active; }
    public function getCreatedAt(): int   { return $this->createdAt; }
    public function getUpdatedAt(): int   { return $this->updatedAt; }

    public function setActive(bool $v): self      { $this->active = $v; $this->touch(); return $this; }
    public function setPermissions(array $v): self { $this->permissions = $v; $this->touch(); return $this; }

    /** Deep merge: only provided resources/actions are updated */
    public function mergePermissions(array $patch): void
    {
        $current = $this->getPermissions();

        if (isset($patch['resources']) && is_array($patch['resources'])) {
            foreach ($patch['resources'] as $resource => $actions) {
                if (!is_array($actions)) continue;
                foreach ($actions as $action => $value) {
                    $current['resources'][$resource][$action] = (bool) $value;
                }
            }
        }
        if (isset($patch['version'])) {
            $current['version'] = (int) $patch['version'];
        }

        $this->permissions = $current;
        $this->touch();
    }

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

    public function toArray(): array
    {
        return [
            'uuid'          => $this->uuid,
            'user_name'     => $this->secretary->getRealName(),
            'mobile_number' => $this->secretary->getMobileNumber(),
            'doctor_name'   => $this->doctor->getName(),
            'doctor_uuid'   => $this->doctor->getUuid(),
            'owner_type'    => $this->ownerType,
            'clinic_uuid'   => $this->clinic?->getUuid(),
            'is_active'     => $this->active,
            'permissions'   => $this->getPermissions()['resources'] ?? $this->getPermissions(),
            'created_at'    => $this->createdAt,
        ];
    }
}
