<?php
declare(strict_types=1);

namespace App\Service\Organization;

use App\Entity\Organization\Organization;
use App\Enum\Organization\OrganizationIdsEnum;
use App\Enum\Organization\SettingsProductEnum;
use App\Service\Utils\DatesUtils;
use App\Service\Utils\UrlBuilder;
use App\Test\Service\Organization\UtilsTest;
use Doctrine\Common\Collections\Criteria;

/**
 * Service rassemblant des fonctions d'aide pour les questions se rapportant à l'organisation
 */
class Utils
{
    public const START_DATE_KEY = 'dateStart';
    public const END_DATE_KEY = 'dateEnd';

    /**
     * Teste si l'organisation est considérée comme une structure == n'a pas un produit manager
     *
     * @param Organization $organization
     * @return bool
     * @see UtilsTest::testIsStructureTest()
     */
    public function isStructure(Organization $organization): bool
    {
        return $organization->getSettings()->getProduct() !== SettingsProductEnum::MANAGER()->getValue() &&
               $organization->getSettings()->getProduct() !== SettingsProductEnum::MANAGER_PREMIUM()->getValue();
    }

    /**
     * Teste si l'organisation est considérée comme un manager == a un produit manager standard
     *
     * @param Organization $organization
     * @return bool
     * @see UtilsTest::testIsManagerTest()
     */
    public function isManager(Organization $organization): bool
    {
        return $organization->getSettings()->getProduct() === SettingsProductEnum::MANAGER()->getValue();
    }

    /**
     * Teste si l'organisation est la structure 2iOpenservice
     * @param Organization $organization
     * @return bool
     * @see UtilsTest::testIsOrganizationIs2ios()
     */
    public function is2iosOrganization(Organization $organization): bool
    {
        return $this->isOrganizationIdEqualTo($organization, OrganizationIdsEnum::_2IOS());
    }

    /**
     * Test si l'organisation est la structure CMF
     * @param Organization $organization
     * @return bool
     * @see UtilsTest::testIsOrganizationIsCMF()
     */
    public function isOrganizationCMF(Organization $organization): bool
    {
        return $this->isOrganizationIdEqualTo($organization, OrganizationIdsEnum::CMF());
    }

    /**
     * Test si l'id de l'organisation est celui passé en paramètre (doit faire partit des OrganizationIdsEnum)
     * @param Organization $organization
     * @param OrganizationIdsEnum $organizationIdsEnum
     * @return bool
     */
    protected function isOrganizationIdEqualTo(Organization $organization, OrganizationIdsEnum $organizationIdsEnum): bool
    {
        return $organization->getId() === $organizationIdsEnum->getValue();
    }

    /**
     * Retourne l'année d'activité dans laquelle on se situe aujourd'hui
     *
     * @param Organization $organization
     * @return int
     * @throws \Exception
     * @see UtilsTest::testGetOrganizationCurrentActivityYear()
     */
    public function getOrganizationCurrentActivityYear(Organization $organization): int
    {
        $today = DatesUtils::new('now');
        $year = (int)$today->format('Y');

        $musicalDate = $organization->getParameters()->getMusicalDate();
        if(empty($musicalDate)) $musicalDate = new \DateTime($year.'-08-31');

        $base_date = new \DateTime($musicalDate->format($year.'-m-d'));
        $dateStart = new \DateTime($year . '-01-01');

        if($today >= $dateStart && $today < $base_date)
            return $year - 1;

        else return $year;
    }

    /**
     * Fonction permettant de récupérer les dates de début et de fin d'activité d'une structure selon une année
     * @param Organization $organization
     * @param int $year
     * @return string[]
     * @throws \Exception
     * @see UtilsTest::testGetActivityPeriodsSwitchYear()
     */
    public function getActivityPeriodsSwitchYear(Organization $organization, int $year): array
    {
        $musicalDate = $organization->getParameters()->getMusicalDate();

        if (empty($musicalDate)) {
            $dateStart = new \DateTime($year . "-09-01");
            $dateEnd = new \DateTime(($year + 1) . "-08-31");
        } else {
            $dateStart = new \DateTime($year . "-" . $musicalDate->format('m') . "-" . $musicalDate->format('d'));
            $dateEnd = clone($dateStart);
            $dateEnd->add(new \DateInterval('P1Y'))->sub(new \DateInterval('P1D'));
        }

        return [
            self::START_DATE_KEY => $dateStart->format('Y-m-d'),
            self::END_DATE_KEY => $dateEnd->format('Y-m-d')
        ];
    }

    /**
     * Permet de retrouver quelle sera la date d'activité correspondant à une date précise de l'année
     *
     * @param Organization $organization
     * @param \DateTimeInterface $date
     * @return int
     * @throws \Exception
     * @see UtilsTest::testgetActivityYearSwitchDate()
     */
    public function getActivityYearSwitchDate(Organization $organization, \DateTimeInterface $date): int
    {
        $year = $date->format('Y');
        $musicalDate = $organization->getParameters()->getMusicalDate();

        if (empty($musicalDate)) {
            $startDate = new \DateTime($year.'-08-31');
        }else{
            $startDate = new \DateTime($musicalDate->format($year.'-m-d'));
        }

        $pivotDate = new \DateTime($year . '-01-01');

        if($date >= $pivotDate && $date < $startDate)
            return  (int) ($year - 1);
        else return (int) $year;
    }

    /**
     * Return the active subdomain of an organization as a string, or null
     *
     * @param Organization $organization
     * @return mixed
     */
    public function getOrganizationActiveSubdomain(Organization $organization): mixed
    {
        foreach ($organization->getSubdomains() as $subdomain) {
            if ($subdomain->isActive()) {
                return $subdomain->getSubdomain();
            }
        }
        return null;
    }

    /**
     * Get the URL of the current website of the organization
     *
     * @see https://ressources.opentalent.fr/display/SPEC/Preferences#Preferences-Siteinternet
     *
     * @param Organization $organization
     * @return mixed
     */
    public function getOrganizationWebsite(Organization $organization): mixed
    {
        $parameters = $organization->getParameters();

        if ($parameters->getDesactivateOpentalentSiteWeb()) {
            if ($parameters->getOtherWebsite()) {
                return UrlBuilder::prependHttps($parameters->getOtherWebsite());
            }
            return null;
        }

        if (!empty($parameters->getCustomDomain())) {
            return UrlBuilder::prependHttps($parameters->getCustomDomain());
        }

        $subdomain = $this->getOrganizationActiveSubdomain($organization);
        if (!$subdomain) {
            return null;
        }

        return 'https://' . $subdomain . '.opentalent.fr';
    }
}
