<?php
declare (strict_types=1);

namespace App\Entity\Billing;

use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\ApiResource;
use App\Entity\Core\Tagg;
use App\Entity\Organization\Organization;
//use DH\Auditor\Provider\Doctrine\Auditing\Annotation\Auditable;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\Collection;

/**
 * @todo : A la suite de la migration, il faut supprimer le nom de la table pour avoir une table BillAccounting, et supprimer l'attribut discr.
 * Classe ... qui ...
 */
#[ApiResource(
    operations: [
        new Get(
            security: 'is_granted(\'ROLE_ADMIN\') and object.getOrganization().getId() == user.getOrganization().getId()'
        )
    ]
)]
//#[Auditable]
#[ORM\Entity]
class BillAccounting
{
    #[ORM\Id]
    #[ORM\Column]
    #[ORM\GeneratedValue]
    protected ?int $id = null;

    #[ORM\Column(length: 255, nullable: false)]
    protected string $discr = 'billaccounting';

    #[ORM\ManyToOne]
    #[ORM\JoinColumn(nullable: true)]
    protected Organization $organization;

    #[ORM\OneToMany(mappedBy: 'bill', targetEntity: BillLine::class, cascade: ['persist'], orphanRemoval: true)]
    protected Collection $billLines;

    #[ORM\OneToMany(mappedBy: 'bill', targetEntity: BillCredit::class, cascade: ['persist'], orphanRemoval: true)]
    protected Collection $billCredits;

    #[ORM\OneToMany(mappedBy: 'bill', targetEntity: BillPayment::class, cascade: ['persist'], orphanRemoval: true)]
    protected Collection $billPayments;

    #[ORM\ManyToOne(inversedBy: 'billCredits')]
    #[ORM\JoinColumn(nullable: true)]
    protected BillAccounting $bill;

    #[ORM\OneToMany(mappedBy: 'bill', targetEntity: BillingIntangibleExcludeDate::class, cascade: ['persist'], orphanRemoval: true)]
    protected Collection $billingIntangibleExcludeDates;

    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'bills')]
    #[ORM\JoinColumn(nullable: true)]
    protected Pes $pes;

    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'bills')]
    #[ORM\JoinColumn(nullable: true)]
    protected BergerLevrault $bergerLevrault;

    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'bills')]
    #[ORM\JoinColumn(nullable: true)]
    protected Ciril $ciril;

    #[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'bills')]
    #[ORM\JoinColumn(nullable: true)]
    protected Jvs $jvs;

    #[ORM\ManyToMany(targetEntity: Tagg::class, inversedBy: 'billAccountings', cascade: ['persist'])]
    #[ORM\JoinTable(name: 'tag_billAccounting')]
    #[ORM\JoinColumn(name: 'billAccounting_id', referencedColumnName: 'id')]
    #[ORM\InverseJoinColumn(name: 'tag_id', referencedColumnName: 'id')]
    protected Collection $tags;

    public function __construct()
    {
        $this->billLines = new ArrayCollection();
        $this->billCredits = new ArrayCollection();
        $this->billPayments = new ArrayCollection();
        $this->billingIntangibleExcludeDates = new ArrayCollection();
        $this->tags = new ArrayCollection();
    }

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getOrganization(): ?Organization
    {
        return $this->organization;
    }

    public function setOrganization(?Organization $organization): self
    {
        $this->organization = $organization;
        return $this;
    }

    /**
     * @return Collection<int, BillLine>
     */
    public function getBillLines(): Collection
    {
        return $this->billLines;
    }

    public function addBillLine(BillLine $billLine): self
    {
        if (!$this->billLines->contains($billLine)) {
            $this->billLines[] = $billLine;
            $billLine->setBill($this);
        }
        return $this;
    }

    public function removeBillLine(BillLine $billLine): self
    {
        if ($this->billLines->removeElement($billLine)) {
            // set the owning side to null (unless already changed)
            if ($billLine->getBill() === $this) {
                $billLine->setBill(null);
            }
        }
        return $this;
    }

    /**
     * @return Collection<int, BillCredit>
     */
    public function getBillCredits(): Collection
    {
        return $this->billCredits;
    }

    public function addBillCredit(BillCredit $billCredit): self
    {
        if (!$this->billCredits->contains($billCredit)) {
            $this->billCredits[] = $billCredit;
            $billCredit->setBill($this);
        }
        return $this;
    }

    public function removeBillCredit(BillCredit $billCredit): self
    {
        if ($this->billCredits->removeElement($billCredit)) {
            // set the owning side to null (unless already changed)
            if ($billCredit->getBill() === $this) {
                $billCredit->setBill(null);
            }
        }
        return $this;
    }

    /**
     * @return Collection<int, BillPayment>
     */
    public function getBillPayments(): Collection
    {
        return $this->billPayments;
    }

    public function addBillPayment(BillPayment $billPayment): self
    {
        if (!$this->billPayments->contains($billPayment)) {
            $this->billPayments[] = $billPayment;
            $billPayment->setBill($this);
        }
        return $this;
    }

    public function removeBillPayment(BillPayment $billPayment): self
    {
        if ($this->billPayments->removeElement($billPayment)) {
            // set the owning side to null (unless already changed)
            if ($billPayment->getBill() === $this) {
                $billPayment->setBill(null);
            }
        }
        return $this;
    }

    public function getBill(): ?self
    {
        return $this->bill;
    }

    public function setBill(?self $bill): self
    {
        $this->bill = $bill;
        return $this;
    }

    /**
     * @return Collection<int, BillingIntangibleExcludeDate>
     */
    public function getBillingIntangibleExcludeDates(): Collection
    {
        return $this->billingIntangibleExcludeDates;
    }

    public function addBillingIntangibleExcludeDate(BillingIntangibleExcludeDate $billingIntangibleExcludeDate): self
    {
        if (!$this->billingIntangibleExcludeDates->contains($billingIntangibleExcludeDate)) {
            $this->billingIntangibleExcludeDates[] = $billingIntangibleExcludeDate;
            /** @phpstan-ignore-next-line */
            $billingIntangibleExcludeDate->setBill($this);
        }
        return $this;
    }

    public function removeBillingIntangibleExcludeDate(BillingIntangibleExcludeDate $billingIntangibleExcludeDate): self
    {
        if ($this->billingIntangibleExcludeDates->removeElement($billingIntangibleExcludeDate)) {
            // set the owning side to null (unless already changed)
            if ($billingIntangibleExcludeDate->getBill() === $this) {
                $billingIntangibleExcludeDate->setBill(null);
            }
        }
        return $this;
    }

    public function getPes(): ?Pes
    {
        return $this->pes;
    }

    public function setPes(?Pes $pes): self
    {
        $this->pes = $pes;
        return $this;
    }

    public function getBergerLevrault(): ?BergerLevrault
    {
        return $this->bergerLevrault;
    }

    public function setBergerLevrault(?BergerLevrault $bergerLevrault): self
    {
        $this->bergerLevrault = $bergerLevrault;
        return $this;
    }

    public function getCiril(): ?Ciril
    {
        return $this->ciril;
    }

    public function setCiril(?Ciril $ciril): self
    {
        $this->ciril = $ciril;
        return $this;
    }

    public function getJvs(): ?Jvs
    {
        return $this->jvs;
    }

    public function setJvs(?Jvs $jvs): self
    {
        $this->jvs = $jvs;
        return $this;
    }

    /**
     * @return Collection<int, Tagg>
     */
    public function getTags(): Collection
    {
        return $this->tags;
    }

    public function addTag(Tagg $tag): self
    {
        if (!$this->tags->contains($tag)) {
            $this->tags[] = $tag;
        }
        return $this;
    }

    public function removeTag(Tagg $tag): self
    {
        $this->tags->removeElement($tag);
        return $this;
    }
}
