<?php

namespace App\Entity;

use App\Enum\MoyenEnum;
use App\Flux\FluxInterface;
use Doctrine\ORM\Mapping as ORM;
use Gedmo\Timestampable\Traits\TimestampableEntity;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;

/**
 * Achat de monnaie à confirmer par le siege/comptoir par un Adhérent ou Prestataire (espèce/chèque/virement).
 *
 * @ORM\Entity(repositoryClass="App\Repository\AchatMonnaieAConfirmerRepository")
 * @ORM\Table(name="achatemlctoconfirm")
 * @ORM\InheritanceType("SINGLE_TABLE")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 * @ORM\DiscriminatorMap({
 *     "achat_monnaie_a_confirmer" = "AchatMonnaieAConfirmer",
 *     "achat_monnaie_a_confirmer_adherent" = "AchatMonnaieAConfirmerAdherent",
 *     "achat_monnaie_a_confirmer_prestataire" = "AchatMonnaieAConfirmerPrestataire"
 * })
 */
abstract class AchatMonnaieAConfirmer implements FluxInterface
{
    use TimestampableEntity;

    const PARENTTYPE_DEMANDE_ACHAT = 'demande_achat';
    const TYPE_DEMANDE_ACHAT_ADHERENT = 'demande_achat_monnaie_adherent';
    const TYPE_DEMANDE_ACHAT_PRESTATAIRE = 'demande_achat_monnaie_prestataire';

    /**
     * @var int
     *
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     * @Groups({"read"})
     */
    protected $id;

    /**
     * @ORM\ManyToOne(targetEntity="User", inversedBy="flux")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true)
     */
    protected $operateur;

    /**
     * Role en cours de l'utilisateur.
     *
     * @var string
     *
     * @ORM\Column(name="role", type="string", length=200)
     * @Assert\NotBlank
     * @Groups({"read", "write"})
     */
    protected $role;

    /**
     * Type de transfert / transaction : exemple : Prestataire à Adhérent.
     *
     * @var string
     *
     * @ORM\Column(name="type", type="string", length=200)
     * @Assert\NotBlank
     * @Groups({"read", "write"})
     */
    protected $type;

    /**
     * Type de flux : transfert / transaction.
     *
     * @var string
     *
     * @ORM\Column(name="parenttype", type="string", length=20)
     * @Assert\NotBlank
     * @Groups({"read", "write"})
     */
    protected $parenttype;

    /**
     * @var float
     *
     * @ORM\Column(name="montant", type="decimal", precision=7, scale=2)
     * @Assert\NotBlank
     * @Assert\Type("numeric")
     * @Assert\GreaterThanOrEqual(
     *     value = 0
     * )
     * @Groups({"read", "write"})
     */
    protected $montant;

    /**
     * @var string
     *
     * @ORM\Column(name="moyen", type="string", length=100)
     * @Assert\NotBlank
     * @Groups({"read", "write"})
     */
    private $moyen;

    /**
     * @var string|null
     *
     * @ORM\Column(name="reference", type="string", length=255, nullable=true)
     * @Assert\NotBlank
     * @Groups({"read", "write"})
     */
    protected $reference;

    /**
     * Hash => permet de vérifier l'intégrité des données.
     *
     * @var text
     *
     * @ORM\Column(name="hash", type="text", options={"default" : "tmp"})
     */
    protected $hash = 'tmp';

    /**
     * @ORM\ManyToOne(targetEntity="Siege")
     * @ORM\JoinColumn(name="siege_id", referencedColumnName="id", nullable=true)
     */
    protected $expediteur;

    /**
     * @var bool RECONVERTI => Validation du dépôt d'espèce/chèque/virement
     * @Assert\Type("bool")
     * @ORM\Column(type="boolean", nullable=false, options={"default" : false})
     * @Groups({"read", "write"})
     */
    protected $reconverti = false;

    /**
     * @ORM\OneToOne(targetEntity="AchatMonnaie")
     * @ORM\JoinColumn(name="achatmonnaie_id", referencedColumnName="id", nullable=true)
     * @Groups({"read", "write"})
     */
    protected $flux;

    public function __construct()
    {
        $this->parenttype = $this->getParenttype();
        $this->type = $this->getType();
    }

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

    /**
     * @param $parenttype
     *
     * @return $this
     */
    public function setParenttype($parenttype)
    {
        $this->parenttype = $parenttype;

        return $this;
    }

    /**
     * @param User $destinataire
     *
     * @return $this
     */
    public function setOperateur(?User $operateur)
    {
        $this->operateur = $operateur;

        return $this;
    }

    /**
     * @return User operateur
     */
    public function getOperateur(): ?User
    {
        return $this->operateur;
    }

    /**
     * @param $destinataire
     *
     * @return $this
     */
    public function setDestinataire($destinataire)
    {
        $this->destinataire = $destinataire;

        return $this;
    }

    /**
     * @return destinataire
     */
    public function getDestinataire()
    {
        return $this->destinataire;
    }

    /**
     * @param $expediteur
     *
     * @return $this
     */
    public function setExpediteur($expediteur)
    {
        $this->expediteur = $expediteur;

        return $this;
    }

    /**
     * @return expediteur
     */
    public function getExpediteur()
    {
        return $this->expediteur;
    }

    /**
     * @param string $type
     *
     * @return Transaction
     */
    public function setType(string $type)
    {
        $this->type = $type;

        return $this;
    }

    /**
     * @return string
     */
    public function getRole(): ?string
    {
        return $this->role;
    }

    /**
     * @param string $role
     *
     * @return Transaction
     */
    public function setRole(?string $role)
    {
        $this->role = $role;

        return $this;
    }

    /**
     * @return float
     */
    public function getMontant(): ?float
    {
        return $this->montant;
    }

    /**
     * @param float $montant
     *
     * @return Transaction
     */
    public function setMontant(float $montant)
    {
        $this->montant = $montant;

        return $this;
    }

    /**
     * @return string
     */
    public function getReference(): ?string
    {
        return $this->reference;
    }

    /**
     * @param string $reference
     *
     * @return Transaction
     */
    public function setReference(string $reference)
    {
        $this->reference = $reference;

        return $this;
    }

    /**
     * Get hash.
     *
     * @return text
     */
    public function getHash()
    {
        return $this->hash;
    }

    /**
     * Set hash.
     *
     * @return $this
     */
    public function setHash($hash)
    {
        $this->hash = $hash;

        return $this;
    }

    /**
     * @return string
     */
    public function getMoyen(): ?string
    {
        return $this->moyen;
    }

    public function setMoyen($moyen)
    {
        if (!in_array($moyen, MoyenEnum::getAvailableTypes())) {
            throw new \InvalidArgumentException('Moyen de paiement invalide !');
        }
        $this->moyen = $moyen;

        return $this;
    }

    public function getReconverti(): bool
    {
        return $this->reconverti;
    }

    public function setReconverti(bool $reconverti)
    {
        $this->reconverti = $reconverti;

        return $this;
    }

    public function isValidated(): bool
    {
        return $this->reconverti;
    }

    /**
     * Get flux.
     *
     * @return
     */
    public function getFlux(): AchatMonnaie
    {
        return $this->flux;
    }

    /**
     * Set flux.
     *
     * @return $this
     */
    public function setFlux(AchatMonnaie $flux)
    {
        $this->flux = $flux;

        return $this;
    }

    /**
     * @return string
     */
    public function getParenttype(): string
    {
        return self::PARENTTYPE_DEMANDE_ACHAT;
    }

    /**
     * @return string
     */
    public function getType(): string
    {
        return '';
    }

    public function isValidationAchat()
    {
        return false;
    }

    public function getUsersToNotify()
    {
        return [];
    }

    public function getAllOperations()
    {
        return null;
    }

    public function __toString(): string
    {
        if (empty($this->getDestinataire()) || empty($this->getExpediteur()) || null === $this->getMontant()) {
            return '[FLUX] Visualisation impossible ! Destinataire / Expéditeur et/ou montant manquant(s) !';
        }

        return ($this->getCreatedAt() ? $this->getCreatedAt()->format('d/m/Y H:i') . ' | ' : '') . ucwords($this->getParenttype()) . ' : ' . $this->getExpediteur() . ' => ' . $this->getDestinataire() . ' : ' . $this->getMontant() . '€';
    }
}
