<?php
declare(strict_types=1);

namespace App\Service\Cotisation;

use App\Entity\Organization\Organization;
use App\Enum\Cotisation\AlertStateEnum;
use App\Repository\Cotisation\CotisationApiResourcesRepository;
use App\Repository\Network\NetworkOrganizationRepository;
use App\Service\Organization\Utils as OrganizationUtils;
use App\Service\Utils\DatesUtils;
use App\Tests\Service\Cotisation\UtilsTest;
use App\Service\Network\Utils as NetworkUtils;

/**
 * Class Utils : Service rassemblant des fonctions d'interrogation pour gérer des conditions dans les Cotisations
 * @package App\Service\Cotisation
 */
class Utils
{
    const MEMBERSHIP_WAITING = 495; // Affiliation in progress
    const MEMBERSHIP_NOPAYMENT = 517; // Waiting paiement
    const SUBMIT_IN_PROGRESS = 540; // Affiliation in progress

    public function __construct(
        private NetworkUtils                     $networkUtils,
        private OrganizationUtils                $organizationUtils,
        private NetworkOrganizationRepository    $networkOrganizationRepository,
        private CotisationApiResourcesRepository $cotisationApiResourcesRepository
    )
    {}

    /**
     * Test si l'organisation est un dernier parent ET appartient à la CMF.
     * @param Organization $organization
     * @return bool
     * @see UtilsTest::testIsLastParentAndCMF()
     */
    public function isLastParentAndCMF(Organization $organization): bool
    {
        return $this->networkOrganizationRepository->isLastParent($organization) && $this->networkUtils->isCMF($organization);
    }

    /**
     * Test si l'organisation est une structure (non manager) ET appartient à la CMF
     * @param Organization $organization
     * @return bool
     * @see UtilsTest::testIsStructureAndCMF()
     */
    public function isStructureAndCMF(Organization $organization): bool
    {
        return $this->organizationUtils->isStructure($organization) && $this->networkUtils->isCMF($organization);
    }

    /**
     * Test si la structure est un manager ET qu'elle appartient à la CMF
     * @param Organization $organization
     * @return bool
     * @see UtilsTest::testIsManagerAndCMF()
     */
    public function isManagerAndCMF(Organization $organization): bool
    {
        return $this->organizationUtils->isManager($organization) && $this->networkUtils->isCMF($organization);
    }

    /**
     * Test si l'organisation est un manager ET un dernier parent ET appartient à la CMF
     * @param Organization $organization
     * @return bool
     * @see UtilsTest::testIsManagerAndLastParentAndCMF()
     */
    public function isManagerAndLastParentAndCMF(Organization $organization): bool
    {
        return $this->organizationUtils->isManager($organization) && $this->isLastParentAndCMF($organization);
    }

    /**
     * Test si l'organisation est un manager ET n'est pas un dernier parent ET appartient à la CMF
     * @param Organization $organization
     * @return bool
     * @see UtilsTest::testIsManagerAndNotLastParentAndCMF()
     */
    public function isManagerAndNotLastParentAndCMF(Organization $organization): bool
    {
        return $this->organizationUtils->isManager($organization) && !$this->networkOrganizationRepository->isLastParent($organization) && $this->networkUtils->isCMF($organization);
    }


    /**
     * Retourne le niveau d'alerte de l'appel de cotisation pour une année.
     * @param Organization $organization
     * @param int $year
     * @return string|null
     * @see UtilsTest::testGetAlertStateAffiliation()
     */
    public function getAlertState(Organization $organization, int $year): ?string
    {
        $state = $this->cotisationApiResourcesRepository->getAffiliationState($organization->getId(), $year);

        $alertState = null;

        if ($state == self::MEMBERSHIP_WAITING || $state == self::SUBMIT_IN_PROGRESS) {
            $alertState = AlertStateEnum::AFFILIATION()->getValue();
        } else if ($state == self::MEMBERSHIP_NOPAYMENT) {
            $alertState = AlertStateEnum::INVOICE()->getValue();
        } else if ($this->cotisationApiResourcesRepository->isInsuranceNotDone($organization->getId(), $year)) {
            $alertState = AlertStateEnum::INSURANCE()->getValue();
        } else if ($this->cotisationApiResourcesRepository->isNotDGVCustomer($organization->getId())) {
            $alertState = AlertStateEnum::ADVERTISINGINSURANCE()->getValue();
        }

        return $alertState;
    }

    /**
     * Retourne dans quelle année de cotisation on est aujourd'hui
     * @return int
     * @throws \Exception
     * @see UtilsTest::testGetCurrentCotisationYear()
     */
    public function getCurrentCotisationYear(): int
    {
        $date = DatesUtils::new('now');
        $year = (int)$date->format('Y');

        $base_date = new \DateTime($year . '-09-01');
        $dateStart = new \DateTime($year . '-01-01');

        if ($date >= $dateStart && $date <= $base_date) {
            $cotisationYear = $year;
        } else {
            $cotisationYear = $year + 1;
        }

        return $cotisationYear;
    }
}
