<?php

namespace App\Controller;


use App\Entity\User;
use App\Repository\UserRepository;

use App\Service\CalendarService;
use DateInterval;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ObjectManager;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;

use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;

use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;


class OAuthController extends AbstractController
{


    const GOOGLE_ENDPOINT="https://accounts.google.com/o/oauth2/v2/auth";
    const GOOGLE_DATA_ENDPOINT="https://oauth2.googleapis.com/token";
    const CLOCK_SKEW_SECS = 300; // five minutes in seconds
    const AUTH_TOKEN_LIFETIME_SECS = 300; // five minutes in seconds
    const MAX_TOKEN_LIFETIME_SECS = 86400; // one day in seconds

    /**
     * @var string
     */
    private $email;

    /**
     * @var array<string>
     */
    public $oauthTokenArray;

    /**
     * @var ObjectManager
     */
    private $em;

    /**
     * @var UserRepository
     */
    private $userRepository;

    /**
     * @var CalendarService
     */
    private $calendarService;

    /**
     * @var User
     */
    private $connectedUser;

    /**
     * @var HttpClientInterface
     */
    private $httpClient;

    /**
     * @var string
     */
    private $oauth_token;

    /**
     * @param EntityManagerInterface $em
     */
    public function __construct(ObjectManager $em,CalendarService $calendarService, HttpClientInterface $httpClient)
    {

        $this->em = $em;
        $this->userRepository = $em->getRepository(User::class);
        $this->calendarService=$calendarService;

        $this->httpClient=$httpClient;

    }


    /**
     * @Route("/oauth/google", name="app.oauth.google", methods={"GET"})
     */
    public function getOauthCalendar(
        CsrfTokenManagerInterface $csrfTokenManager,
        UrlGeneratorInterface $urlGenerator,
        HttpClientInterface $httpClient
    ): ? RedirectResponse
    {

        if ($this->get('security.token_storage')->getToken() == null)
            return new RedirectResponse($this->generateUrl('app_login'));


        $this->connectedUser=$this->getConnectedUser();

        $oauth_Refresh_Token = $this->connectedUser->getOauthGoogleRefreshToken();

        if (!isset($oauth_Refresh_Token))
            return $this->calendarService->getOauthCode( $csrfTokenManager,$urlGenerator);
        else
        {
            $oauth_Expires_In = $this->connectedUser->getOauthGoogleCurrentTokenMustExpiresAt();
            $oauth_token = $this->connectedUser->getOauthGoogleCurrentToken();

            try {
                $arrayToken =[
                    "refresh_token" => $oauth_Refresh_Token,
                    "expires_in"    => $oauth_Expires_In,
                    "current_token" => $oauth_token
                ];
                $this->oauth_token = $this->calendarService->refreshTokenIfNeeded(
                    $httpClient,
                    $arrayToken
                    );

                return new RedirectResponse($this->generateUrl('app.calendar',[
                    'access_token'=>  $this->oauth_token
                ]));


            } catch (ClientExceptionInterface | DecodingExceptionInterface | RedirectionExceptionInterface | ServerExceptionInterface | TransportExceptionInterface $e) {

            }
        }
        return null;
    }

    /**
     * @Route("/oauth/google/check", name="app.oauth.google.check", methods={"GET"})
     */
    public function checkCsrfToken(Request $request,
                                   UrlGeneratorInterface $urlGenerator,
                                   CsrfTokenManagerInterface $csrfTokenManager,
                                   HttpClientInterface $httpClient) : ? RedirectResponse
    {

        $uri = $request->getUri();
        $code = $request->get('code');
        $state = $request->get('state');

        if (!$state || !$csrfTokenManager->isTokenValid(new CsrfToken('vexinenmarche@gmail.com', $state)))
            throw new AccessDeniedException('Invalid user and password');


        try {
            $arrayToken = $this->calendarService->getOAuthTokenFromCode($code, $urlGenerator, $httpClient);

            [
                "access_token" => $access_token,
                "refresh_token" => $refresh_token,
                "expires_in" => $expires_in
            ] = $arrayToken;
            $this->connectedUser=$this->getConnectedUser();
            $this->connectedUser->setOauthGoogleRefreshToken($refresh_token);

            $dt = new \DateTimeImmutable();
            $dt->add(new DateInterval('PT'.$expires_in.'S'));

            $this->connectedUser->setOauthGoogleCurrentTokenMustExpiresAt($dt);
            $this->connectedUser->setOauthGoogleCurrentToken($access_token);
            $this->em->persist($this->connectedUser);
            $this->em->flush();
            $this->oauth_token=$access_token;

            return new RedirectResponse($this->generateUrl('app.calendar',
            ['access_token' =>  $access_token] ));

        } catch (ClientExceptionInterface | DecodingExceptionInterface | RedirectionExceptionInterface | ServerExceptionInterface | TransportExceptionInterface | \Exception $e) {
        }
        return  null;
    }
    /**
     * @Route("/calendardata", name="app.calendar.data")
     */
    public function getDataCalendar(
        CsrfTokenManagerInterface $csrfTokenManager,
        UrlGeneratorInterface $urlGenerator,
        HttpClientInterface $httpClient)
    {
        $redirectUrl=$this->getOauthCalendar($csrfTokenManager, $urlGenerator, $httpClient)->getTargetUrl();
        return new RedirectResponse($redirectUrl);
    }
    /**
     * @Route("/calendar", name="app.calendar")
     */
    public function getCalendarData(HttpClientInterface $httpClient, Request $request): ? Response
    {
        $calendarId = '4s1b934thlspr6s3a86d2qm02k';
        $access_token = $request->get('access_token');
        if ($access_token) {
            try {
                $data = $this->calendarService->getCalendarData($httpClient,$access_token, $calendarId);

                $idx=0;
                $jdx=0;
                $resp="";
                $array = array();
                foreach ($data["items"] as $key => $value) {
                    $jdx ++;
                    $summary="";
                    if (array_key_exists("summary",$value))
                        $summary = $value["summary"];




                    if(

                        str_contains( $summary,"Obseques")
                        || str_contains( $summary,"Obsèques")
                        || str_contains( $summary,"obsèques")
                        || str_contains( $summary,"obseques")
                        /*
                        str_contains( $summary,"Mariage")
                        || str_contains( $summary,"mariage")
                        */
                        /*
                                    str_contains( $summary,"Baptême")
                                    || str_contains( $summary,"Bapteme")
                                    || str_contains( $summary,"bapteme")
                                    || str_contains( $summary,"baptême")
                        */

                    )
                    {
                        if (array_key_exists(
                            'dateTime',
                            $value["start"])) {
                            $googleDate=$value["start"]["dateTime"];
                            $sentDates= explode('T', $googleDate);
                            $dateStart= date_create($sentDates[0]);

                            $year=intval($dateStart->format('Y'));


                            $array[] = array( 'year' => $year,'date'=>$dateStart);

                        }
                    }


                }
                $dt=$this->group_by("year",$array);

dd($dt);
                return $this->render('home/secretariat/calendar/index.html.twig', [
                    'calendar_data' => $dt
                ]);
            } catch (ClientExceptionInterface | DecodingExceptionInterface | RedirectionExceptionInterface | ServerExceptionInterface | TransportExceptionInterface $e) {
            }
        }
        return null;
    }

    /**
     * @return User
     */
    private function getConnectedUser() :User
    {
        $emailUserConnected = $this->get('security.token_storage')->getToken()->getUser()->getUserIdentifier();
        /* get the user id connected */
        return $this->userRepository->findOneBy(
            ['email'=> $emailUserConnected]);
    }

    /**
     * Function that groups an array of associative arrays by some key.
     *
     * @param {String} $key Property to sort by.
     * @param {Array} $data Array that stores multiple associative arrays.
     */
    private function group_by($key, $data) {
        $result = array();

        foreach($data as $val) {
            if(array_key_exists($key, $val)){
                $result[$val[$key]][] = $val;
            }else{
                $result[""][] = $val;
            }
        }

        return $result;
    }


}
