<?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\Network\Utils as NetworkUtils;
use App\Service\Organization\Utils as OrganizationUtils;
use App\Service\Utils\DatesUtils;

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

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

    /**
     * Test si l'organisation est un dernier parent ET appartient à la CMF.
     *
     * @see config/opentalent/modulesbyconditions.yaml
     * @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.
     *
     * @see config/opentalent/modulesbyconditions.yaml
     * @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.
     *
     * @see config/opentalent/modulesbyconditions.yaml
     * @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.
     *
     * @see config/opentalent/modulesbyconditions.yaml
     * @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.
     *
     * @see config/opentalent/modulesbyconditions.yaml
     * @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.
     *
     * @see UtilsTest::testGetAlertStateAffiliation()
     */
    public function getAlertState(Organization $organization, int $year): ?AlertStateEnum
    {
        $state = $this->cotisationApiResourcesRepository->getAffiliationState($organization->getId(), $year);

        $alertState = null;

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

        return $alertState;
    }

    /**
     * Retourne dans quelle année de cotisation on est aujourd'hui.
     *
     * @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;
    }
}
