<?php

namespace App\Entity;

use DateTime;
use Doctrine\ORM\Mapping as ORM;
use Payum\Core\Model\Payment as BasePayment;
use Ramsey\Uuid\Doctrine\UuidGenerator;

/**
 * @ORM\Entity(repositoryClass="App\Repository\PaymentRepository")
 * @ORM\Table(name="payment")
 */
class Payment extends BasePayment
{
    const TYPE_ACHAT_MONNAIE_ADHERENT = 'achat_monnaie_adherent';
    const TYPE_ACHAT_MONNAIE_PRESTA = 'achat_monnaie_presta';
    const TYPE_COTISATION_ADHERENT = 'cotisation_adherent';
    const TYPE_COTISATION_PRESTA = 'cotisation_presta';
    const TYPE_ADHESION = 'adhesion';
    const TYPE_PAIEMENT_COTISATION_TAV = 'paiement_cotisation_tav';
    const TYPE_PAIEMENT_RECURRENT_COTISATION_TAV = 'paiement_recurrent_cotisation_tav';

    /**
     * @var \Ramsey\Uuid\UuidInterface
     *
     * @ORM\Id
     * @ORM\Column(type="uuid", unique=true)
     * @ORM\GeneratedValue(strategy="CUSTOM")
     * @ORM\CustomIdGenerator(class=UuidGenerator::class)
     */
    protected $id;

    /**
     * @var string|null
     *
     * @ORM\Column(type="string", length=50, nullable=true)
     */
    protected $status;

    /**
     * @var string|null
     *                  JSON array of 'Flux' to persist if payment valid
     *
     * @ORM\Column(type="text", nullable=true)
     */
    protected $flux_data;

    /**
     * @var string|null
     *                  Extra data to persist if payment valid
     *
     * @ORM\Column(type="text", nullable=true)
     */
    protected $extra_data;

    /**
     * @ORM\Column(type="boolean", nullable=True)
     */
    private $isRecurrent;

    /**
     * @ORM\Column(type="integer", nullable=true)
     */
    private $recurrenceMonthsCount;

    /**
     * @ORM\Column(type="integer", nullable=true)
     */
    private $recurrenceMonthDay;

    /**
     * @ORM\Column(type="integer", nullable=true)
     */
    private $recurrenceAmount;

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

    /**
     * @param string $status
     *
     * @return Payment
     */
    public function setStatus(string $status): self
    {
        $this->status = $status;

        return $this;
    }

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

    /**
     * @param string $flux_data
     *
     * @return Payment
     */
    public function setFluxData(string $flux_data): self
    {
        $this->flux_data = $flux_data;

        return $this;
    }

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

    /**
     * @param string $extra_data
     *
     * @return Payment
     */
    public function setExtraData(string $extra_data): self
    {
        $this->extra_data = $extra_data;

        return $this;
    }

    public function getIsRecurrent(): ?bool
    {
        return $this->isRecurrent;
    }

    public function setIsRecurrent(bool $isRecurrent): self
    {
        $this->isRecurrent = $isRecurrent;

        return $this;
    }

    public function getRecurrenceMonthsCount(): ?int
    {
        return $this->recurrenceMonthsCount;
    }

    public function setRecurrenceMonthsCount(?int $recurrenceMonthsCount): self
    {
        $this->recurrenceMonthsCount = $recurrenceMonthsCount;

        return $this;
    }

    public function getRecurrenceMonthDay(): ?int
    {
        return $this->recurrenceMonthDay;
    }

    public function setRecurrenceMonthDay(?int $recurrenceMonthDay): self
    {
        $this->recurrenceMonthDay = $recurrenceMonthDay;

        return $this;
    }

    public function getRecurrenceAmount(): ?int
    {
        return $this->recurrenceAmount;
    }

    public function setRecurrenceAmount(?int $recurrenceAmount): self
    {
        $this->recurrenceAmount = $recurrenceAmount;

        return $this;
    }

    /**
     * Return null in case of error
     * Returns true if payment is already ended or CB expired
     * Returns false otherwise
     *
     * @param $reason
     * @return bool|null
     */
    public function isRecurringPaymentEndedOrExpired(&$reason)
    {
        if (
            !$this->details
            || !array_key_exists('vads_effective_creation_date', $this->details)
            || !array_key_exists('vads_expiry_year', $this->details)
            || !array_key_exists('vads_effective_creation_date', $this->details)
        ) {
            $reason = "Attribut détails vide ou clés absentes.";
            return null;
        }
        $firstDayOfCreationMonth = DateTime::createFromFormat(
            'Ymd',
            substr($this->details['vads_effective_creation_date'], 0, 6) . "01"
        );
        if (!$firstDayOfCreationMonth) {
            $reason = "Error parsing vads_effective_creation_date : " . $this->details['vads_effective_creation_date'];
            return null;
        }
        $day = $this->getRecurrenceMonthDay() ? $this->getRecurrenceMonthDay() - 1 : 0; //if not set assume first day of month (not a big deal anyway)
        $dateOfFirstOccurenceAfterInitialPayment = $firstDayOfCreationMonth->modify(
            "+" . $day . " days next month"
        );

        $paymentEndDate = $this->getRecurrenceMonthsCount() ?
            $dateOfFirstOccurenceAfterInitialPayment->modify(
                "+" . ($this->getRecurrenceMonthsCount() - 1) . " months" //minus one because initial payment is not considered by payzen as the first occurence
            )
            : null; //assume no end date if recurrenceMonthsCount not set

        //Now check expiry date
        $paymentEndDateDueToExpiry = new DateTime();
        $paymentEndDateDueToExpiry->setDate($this->details['vads_expiry_year'], $this->details['vads_expiry_month'], $day + 1);

        $now = new DateTime();
        if ($paymentEndDate && $paymentEndDate < $paymentEndDateDueToExpiry) {
            //Compare now with payment end date
            $reason = "Paiement récurrent en cours de " . $this->recurrenceAmount . "€ jusqu'à dernière échéance le " . $paymentEndDate->format('d/m/Y') . ".";
            return $now >= $paymentEndDate;
        } else {
            //Compare now with expiry date
            $reason = "Paiement récurrent en cours de " . $this->recurrenceAmount . "€ jusqu'à dernière échéance le " . $paymentEndDateDueToExpiry->format('d/m/Y') . " en raison de l'expiration du moyen de paiement.";
            return $now >= $paymentEndDateDueToExpiry;
        }
    }
}
