<?php

declare(strict_types=1);

/**
 * Created by Aurélien RICHAUD (31/07/2019 11:03)
 */
require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'OAuthAuthCode.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'OAuthAccessToken.php';
require_once __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'classes' . DIRECTORY_SEPARATOR . 'OAuthClient.php';

class MyvetshopcliniqueTokenModuleFrontController extends FrontController
{
    /**
     * @throws PrestaShopDatabaseException
     * @throws PrestaShopException
     */
    public function init(): void
    {
        if (!isset($_SERVER['REQUEST_METHOD'])) {
            $_SERVER['REQUEST_METHOD'] = null;
        }

        if ('POST' === $_SERVER['REQUEST_METHOD']) {
            /////////////////////////////////////////
            // Récupération des informations OAuth
            $code = Tools::getValue('code');
            $grant_type = Tools::getValue('grant_type');
            $client_id = Tools::getValue('client_id');
            $client_secret = Tools::getValue('client_secret');
            $redirect_uri = Tools::getValue('redirect_uri');

            // Paramètres obligatoires
            if (!$code
                || !$grant_type
                || !$client_id
                || !$client_secret
                || !$redirect_uri) {
                header('HTTP/1.0 400 Bad Request');
                exit();
            }

            try {
                $authCode = OAuthAuthCode::getByToken($code);
                $client = OAuthClient::getByRandomId($client_id);
            } catch (PrestaShopDatabaseException $e) {
                $authCode = null;
                $client = null;
            } catch (PrestaShopException $e) {
                $authCode = null;
                $client = null;
            }

            /////////////////////////////////////////
            // AuthCode invalide
            if (!$authCode || !$client || $authCode->client_id != $client->id_oauth_client) {
                header('HTTP/1.0 400 Bad Request');
                var_dump($authCode);
                var_dump($client);
                if ($authCode instanceof OAuthAuthCode) {
                    var_dump($authCode->client_id);
                }
                if ($client instanceof OAuthClient) {
                    var_dump($client->id_oauth_client);
                }
                exit();
            }

            /////////////////////////////////////////
            // Client secret
            if ($client->secret != $client_secret) {
                header('HTTP/1.0 403 Forbidden');
                echo 'Invalid client secret';
                exit();
            }

            /////////////////////////////////////////
            // RedirectUri invalide
            if (!in_array($redirect_uri, explode(',', $client->redirect_uris))) {
                header('HTTP/1.0 403 Forbidden');
                exit();
            }

            /////////////////////////////////////////
            // RedirectUri invalide
            if ('bearer' != strtolower($grant_type)) {
                header('HTTP/1.0 403 Forbidden');
                exit();
            }

            /////////////////////////////////////////
            /// Création d'un AccessToken
            $accessToken = new OAuthAccessToken();
            $accessToken->client_id = (string) $authCode->client_id;
            $accessToken->id_customer = $authCode->id_customer;
            $accessToken->redirect_uri = $redirect_uri;
            $accessToken->created = time();
            $accessToken->expires = time() + 365 * 24 * 60 * 60; // 1 an

            // Sauvegarde l'AuthCode
            try {
                $accessToken->save();
                $authCode->delete();
            } catch (PrestaShopException $e) {
                header('HTTP/1.0 500 Internal Server Error');
                header('Content-Type: application/json');
                echo json_encode(['error' => $e->getMessage()], JSON_PRETTY_PRINT);
                exit();
            }

            /////////////////////////////////////////
            /// Redirrige vers l'URL de retour
            header('Content-Type: application/json');
            echo json_encode(
                [
                    'access_token' => $accessToken->token,
                    'expires_in' => $accessToken->expires - time(),
                    'token_type' => 'Bearer',
                    'scope' => '',
                ],
                JSON_PRETTY_PRINT
            );
        } elseif ('DELETE' === $_SERVER['REQUEST_METHOD']) {
            $body = file_get_contents('php://input');
            if ($body) {
                parse_str($body, $vars);
            } else {
                $vars = [];
            }

            // Déconnexion
            if (!isset($vars['access_token'])) {
                $token = Tools::getValue('access_token');
            } else {
                $token = $vars['access_token'];
            }

            $accessToken = OAuthAccessToken::getByToken($token);
            // Si token non trouvé, refuse l'accès
            if (!$accessToken) {
                header('Content-Type: application/json');
                echo json_encode(
                    [
                        'error' => 'Token not found',
                    ],
                    JSON_PRETTY_PRINT
                );
                exit();
                /*
                                header('HTTP/1.0 401 Unauthorized');
                                header('Content-Type: application/json');
                                echo json_encode(
                                    [
                                        'error' => "Token not found",
                                    ],
                                    JSON_PRETTY_PRINT
                                );
                                exit();
                */
            }
            // Si le token est déjà expiré, on arrête là
            if ($accessToken->expires <= time()) {
                header('Content-Type: application/json');
                echo json_encode(
                    [
                        'access_token' => $accessToken->token,
                        'expires_in' => $accessToken->expires - time(),
                        'token_type' => 'Bearer',
                        'scope' => '',
                    ],
                    JSON_PRETTY_PRINT
                );
                exit();
            }

            // Indique la date d'expiration du token
            $accessToken->expires = time();
            $accessToken->save();

            // Indique le token est expiré
            header('Content-Type: application/json');
            echo json_encode(
                [
                    'access_token' => $accessToken->token,
                    'expires_in' => $accessToken->expires - time(),
                    'token_type' => 'Bearer',
                    'scope' => '',
                ],
                JSON_PRETTY_PRINT
            );
        } else {
            header('HTTP/1.0 405 Method Not Allowed');
        }
        exit();
    }
}
