<?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 App\Shared\Context\EntityContext;
use App\Shared\Tenant\TenantOwnedTrait;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;

#[ORM\Entity(repositoryClass: DoctorSecretaryRepository::class)]
#[ORM\Table(name: 'doctor_secretaries')]
// entity_id در کلید هست تا یک منشی بتواند به همان پزشک در چند کلینیک تخصیص یابد؛
// کلید قبلی فقط owner_type را داشت و ردیف دومِ 'clinic' را تکراری می‌شمرد.
#[ORM\UniqueConstraint(name: 'uniq_doctor_secretary_scope', columns: ['doctor_id', 'secretary_id', 'entity_type', 'entity_id'])]
class DoctorSecretary
{
    use TenantOwnedTrait;

    public const OWNER_DOCTOR = EntityContext::TYPE_DOCTOR;
    public const OWNER_CLINIC = EntityContext::TYPE_CLINIC;

    public const DEFAULT_PERMISSIONS = [
        'version'   => 1,
        'resources' => [
            'appointments' => ['view' => true,  'create' => true,  'cancel' => false, 'update_status' => true],
            'patients'     => ['view' => true,  'create' => false, 'update' => false, 'delete' => false],
            'payments'     => ['view' => true,  'create' => false, 'update' => false, 'delete' => false],
            'insurances'   => ['view' => true,  'create' => false, 'update' => false, 'delete' => false],
            'addresses'    => ['view' => true,  'create' => false, 'update' => false, 'delete' => false],
            'clinic_info'  => ['view' => true,  'update' => false],
            'inventory'    => ['view' => false, 'create' => false, 'update' => false, 'delete' => false],
            'tags'         => ['view' => false, 'create' => false, 'update' => false, 'delete' => false],
            'services'     => ['view' => false, 'create' => false, 'update' => false, 'delete' => false],
            'staff'        => ['view' => false, 'create' => false, 'update' => false, 'delete' => false],
            'discounts'    => ['view' => false, 'create' => false, 'update' => false, 'delete' => false],
            'sms'          => ['view' => false, 'create' => false, 'update' => false, 'delete' => false],
            'appointment_settings' => ['view' => false, 'update' => false],
            'clinic_doctors' => ['view' => false, 'create' => false, 'update' => false, 'delete' => false],
            'subscription' => ['view' => false, 'create' => 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\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(name: 'national_code', type: 'string', length: 20, nullable: true)]
    private ?string $nationalCode = null;

    #[ORM\Column(name: 'address', type: 'text', nullable: true)]
    private ?string $address = null;

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

    /**
     * سهم منشی از نوبت‌های آنلاینِ همین پزشک/کلینیک فعال است؟ تنظیم per-relation است:
     * یک منشی می‌تواند برای یک پزشک سهم داشته باشد و برای دیگری نه.
     */
    #[ORM\Column(name: 'online_share_enabled', type: 'boolean', options: ['default' => false])]
    private bool $onlineShareEnabled = false;

    /** درصد سهم منشی از «خالصِ پس از مالیات» نوبت آنلاین. */
    #[ORM\Column(name: 'online_share_percent', type: 'decimal', precision: 5, scale: 2, options: ['default' => '0.00'])]
    private string $onlineSharePercent = '0.00';

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

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

    /** محیط از $clinic می‌آید: null یعنی مطب شخصی همان پزشک. */
    public function __construct(Doctor $doctor, User $secretary, ?Clinic $clinic = null)
    {
        $this->uuid        = Uuid::v4()->toRfc4122();
        $this->doctor      = $doctor;
        $this->secretary   = $secretary;
        $this->clinic      = $clinic;
        $this->permissions = self::DEFAULT_PERMISSIONS;
        $this->createdAt   = time();
        $this->updatedAt   = time();

        // clinic تعیین‌کننده است، نه $ownerType: ترکیب ناسازگارِ ('clinic', clinic=null)
        // در گذشته ممکن بود ساخته شود و همین ردیف‌ها بودند که یکتایی را می‌شکستند.
        $this->assignTenant(EntityContext::forBooking($doctor, $clinic));
    }

    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->entityType; }
    public function getClinic(): ?Clinic  { return $this->clinic; }
    public function getPermissions(): array { return $this->permissions ?? self::DEFAULT_PERMISSIONS; }
    public function getNationalCode(): ?string { return $this->nationalCode; }
    public function getAddress(): ?string { return $this->address; }
    public function isActive(): bool      { return $this->active; }
    public function isOnlineShareEnabled(): bool { return $this->onlineShareEnabled; }
    public function getOnlineSharePercent(): float { return (float) $this->onlineSharePercent; }
    /** سهم مؤثر: درصد فقط وقتی معنا دارد که رابطه فعال و سهم روشن باشد. */
    public function effectiveOnlineSharePercent(): float
    {
        return ($this->active && $this->onlineShareEnabled) ? (float) $this->onlineSharePercent : 0.0;
    }
    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; }
    public function setNationalCode(?string $v): self { $this->nationalCode = $v; $this->touch(); return $this; }
    public function setAddress(?string $v): self      { $this->address = $v; $this->touch(); return $this; }
    public function setOnlineShareEnabled(bool $v): self  { $this->onlineShareEnabled = $v; $this->touch(); return $this; }
    public function setOnlineSharePercent(float $v): self { $this->onlineSharePercent = (string) $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,
            'secretary_uuid' => $this->secretary->getUuid(),
            'user_name'     => $this->secretary->getRealName(),
            'mobile_number' => $this->secretary->getMobileNumber(),
            'doctor_name'   => $this->doctor->getName(),
            'doctor_uuid'   => $this->doctor->getUuid(),
            // کلید پاسخ عمداً owner_type مانده تا قرارداد کلاینت‌ها نشکند.
            'owner_type'    => $this->entityType,
            'clinic_uuid'   => $this->clinic?->getUuid(),
            'is_active'     => $this->active,
            'online_share_enabled' => $this->onlineShareEnabled,
            'online_share_percent' => (float) $this->onlineSharePercent,
            'national_code' => $this->nationalCode,
            'address'       => $this->address,
            'permissions'   => $this->getPermissions()['resources'] ?? $this->getPermissions(),
            'created_at'    => $this->createdAt,
        ];
    }
}
