<?php

namespace App\Discount\Entity;

use App\Discount\Repository\DiscountRuleRepository;
use App\Shared\Tenant\TenantOwnedTrait;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\Uuid;

/**
 * قانون تخفیف عمومی، per-tenant (پزشک یا کلینیک). موتور تخفیف
 * (DiscountEngine) این قوانین را برای یک پرونده ارزیابی می‌کند.
 */
#[ORM\Entity(repositoryClass: DiscountRuleRepository::class)]
#[ORM\Table(name: 'discount_rules')]
#[ORM\Index(columns: ['entity_type', 'entity_id', 'active'], name: 'idx_discount_rules_tenant')]
class DiscountRule
{
    use TenantOwnedTrait;

    public const TYPE_PATIENT_TAG      = 'patient_tag';
    public const TYPE_INVOICE_AMOUNT   = 'invoice_amount';
    public const TYPE_SPECIFIC_PATIENT = 'specific_patient';
    public const TYPE_OCCASION         = 'occasion';
    public const TYPE_SERVICE          = 'service';
    public const TYPE_VISIT_COUNT      = 'visit_count';

    public const TYPES = [
        self::TYPE_PATIENT_TAG,
        self::TYPE_INVOICE_AMOUNT,
        self::TYPE_SPECIFIC_PATIENT,
        self::TYPE_OCCASION,
        self::TYPE_SERVICE,
        self::TYPE_VISIT_COUNT,
    ];

    public const DISCOUNT_PERCENT = 'percent';
    public const DISCOUNT_FIXED   = 'fixed';

    /** زیرنوع مناسبت: birthday | null (بازه‌ی تاریخی) */
    public const OCCASION_BIRTHDAY = 'birthday';

    #[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(type: 'string', length: 120)]
    private string $name;

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

    #[ORM\Column(name: 'discount_type', type: 'string', length: 10)]
    private string $discountType = self::DISCOUNT_PERCENT;

    /** مقدار خام: درصد (۰..۱۰۰) یا ریال، بسته به discountType */
    #[ORM\Column(type: 'integer')]
    private int $value = 0;

    #[ORM\Column(type: 'integer')]
    private int $priority = 0;

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

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

    #[ORM\Column(name: 'valid_from', type: 'integer', nullable: true)]
    private ?int $validFrom = null;

    #[ORM\Column(name: 'valid_to', type: 'integer', nullable: true)]
    private ?int $validTo = null;

    // ── target fields (بسته به type فقط یکی معنی‌دار است؛ uuid برای سازگاری با UI) ──
    #[ORM\Column(name: 'target_tag_uuid', type: 'string', length: 36, nullable: true)]
    private ?string $targetTagUuid = null;

    #[ORM\Column(name: 'target_record_uuid', type: 'string', length: 36, nullable: true)]
    private ?string $targetRecordUuid = null;

    #[ORM\Column(name: 'target_service_item_uuid', type: 'string', length: 36, nullable: true)]
    private ?string $targetServiceItemUuid = null;

    #[ORM\Column(name: 'min_amount_rials', type: 'integer', nullable: true)]
    private ?int $minAmountRials = null;

    #[ORM\Column(name: 'min_visit_count', type: 'integer', nullable: true)]
    private ?int $minVisitCount = null;

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

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

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

    public function __construct(string $entityType, int $entityId, string $name, string $type)
    {
        $this->uuid      = Uuid::v4()->toRfc4122();
        $this->name      = $name;
        $this->type      = $type;
        $this->createdAt = time();
        $this->updatedAt = time();
        $this->assignTenantPair($entityType, $entityId);
    }

    public function getId(): ?int              { return $this->id; }
    public function getUuid(): string          { return $this->uuid; }
    public function getName(): string          { return $this->name; }
    public function getType(): string          { return $this->type; }
    public function getDiscountType(): string  { return $this->discountType; }
    public function getValue(): int            { return $this->value; }
    public function getPriority(): int         { return $this->priority; }
    public function isCombinable(): bool       { return $this->combinable; }
    public function isActive(): bool           { return $this->active; }
    public function getValidFrom(): ?int       { return $this->validFrom; }
    public function getValidTo(): ?int         { return $this->validTo; }
    public function getTargetTagUuid(): ?string     { return $this->targetTagUuid; }
    public function getTargetRecordUuid(): ?string  { return $this->targetRecordUuid; }
    public function getTargetServiceItemUuid(): ?string { return $this->targetServiceItemUuid; }
    public function getMinAmountRials(): ?int  { return $this->minAmountRials; }
    public function getMinVisitCount(): ?int   { return $this->minVisitCount; }
    public function getOccasionKind(): ?string { return $this->occasionKind; }

    public function setName(string $v): self          { $this->name = $v; $this->touch(); return $this; }
    public function setType(string $v): self          { $this->type = $v; $this->touch(); return $this; }
    public function setDiscountType(string $v): self  { $this->discountType = $v; $this->touch(); return $this; }
    public function setValue(int $v): self            { $this->value = $v; $this->touch(); return $this; }
    public function setPriority(int $v): self         { $this->priority = $v; $this->touch(); return $this; }
    public function setCombinable(bool $v): self      { $this->combinable = $v; $this->touch(); return $this; }
    public function setActive(bool $v): self          { $this->active = $v; $this->touch(); return $this; }
    public function setValidFrom(?int $v): self       { $this->validFrom = $v; $this->touch(); return $this; }
    public function setValidTo(?int $v): self         { $this->validTo = $v; $this->touch(); return $this; }
    public function setTargetTagUuid(?string $v): self     { $this->targetTagUuid = $v; $this->touch(); return $this; }
    public function setTargetRecordUuid(?string $v): self  { $this->targetRecordUuid = $v; $this->touch(); return $this; }
    public function setTargetServiceItemUuid(?string $v): self { $this->targetServiceItemUuid = $v; $this->touch(); return $this; }
    public function setMinAmountRials(?int $v): self  { $this->minAmountRials = $v; $this->touch(); return $this; }
    public function setMinVisitCount(?int $v): self   { $this->minVisitCount = $v; $this->touch(); return $this; }
    public function setOccasionKind(?string $v): self { $this->occasionKind = $v; $this->touch(); return $this; }

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

    public function toArray(): array
    {
        return [
            'uuid'                    => $this->uuid,
            'name'                    => $this->name,
            'type'                    => $this->type,
            'discount_type'           => $this->discountType,
            'value'                   => $this->value,
            'priority'                => $this->priority,
            'combinable'              => $this->combinable,
            'active'                  => $this->active,
            'valid_from'              => $this->validFrom,
            'valid_to'                => $this->validTo,
            'target_tag_uuid'          => $this->targetTagUuid,
            'target_record_uuid'       => $this->targetRecordUuid,
            'target_service_item_uuid' => $this->targetServiceItemUuid,
            'min_amount_rials'         => $this->minAmountRials,
            'min_visit_count'         => $this->minVisitCount,
            'occasion_kind'           => $this->occasionKind,
            'created_at'              => $this->createdAt,
            'updated_at'              => $this->updatedAt,
        ];
    }
}
