<?php

namespace api\user;
require_once __DIR__ . "/../utils/routesInterface.php";
require_once "userData.php";

use api\utils\routesInterface;
use OneLogin\Saml2\Auth;
use OneLogin\Saml2\Error;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\App;

class userRoutes implements routesInterface
{
    private userData $user;
    private Auth $samlAuth;

    /**
     * constructor used to instantiate base user routes, to be used in the index.php file.
     * @param App $app - the slim app used to create the routes
     * @throws Error
     */
    public function __construct(App $app)
    {
        $this->user = new userData();
        $this->samlAuth = new Auth($this->user->getSamlConf());
        $this->createRoutes($app);
    }

    /**
     * creates the routes for the user
     * @param App $app - the slim app used to create the routes
     * @return void - returns nothing
     */
    public function createRoutes(App $app): void
    {
        $app->get("/user/login", function (Request $request, Response $response)
        {
            $this->samlAuth->login();
        });

        $app->get("/user/logout", function (Request $request, Response $response)
        {
            session_unset();
            return $response;
        });

        $app->get("/user/isLoggedIn", function (Request $request, Response $response)
        {
            if (empty($_SESSION["token"]) && empty($_SESSION["username"]))
            {
                // uh oh user not logged in
                return $response->withStatus(401);
            }

            $inactive = 60 * 60 * 48; // 2 days
            $sessionLife = time() - $_SESSION["timeout"];
            if ($sessionLife > $inactive)
            {
                // uh oh user session expired
                session_destroy();
                return $response->withStatus(401);
            }

            if (empty($_SESSION["token"]))
            {
                // user is logged in but no token was created
                $_SESSION["token"] = $this->user->createToken($_SESSION["username"]);
                return $response->withStatus(201);
            }

            $response->getBody()->write(json_encode(array("token" => $_SESSION["token"])));
            return $response;

        });

        $app->get("/user/metadata", function (Request $request, Response $response)
        {
            $settings = $this->samlAuth->getSettings();
            $metadata = $settings->getSPMetadata();
            $errors = $settings->validateMetadata($metadata);
            if (empty($errors))
            {
                $response->getBody()->write($metadata);
                return $response->withHeader("Content-Type", "text/xml");
            }
            $response->getBody()->write(json_encode(array("error" => $errors)));
            return $response->withStatus(500);
        });

        $app->get("/user/checkResetEmail/{email}", function (Request $request, Response $response, array $args)
        {
            if (empty($args["email"]))
            {
                // uh oh sent empty data
                return $response->withStatus(400);
            }

            if ($this->user->checkEmail($args["email"]))
            {
                // yay email does exist
                $_SESSION["resetToken"] = $this->user->sendResetEmail($args["email"]);
                $_SESSION["resetEmail"] = $args["email"];
                return $response;
            }
            return $response->withStatus(404);
        });

        $app->get("/user/resendEmail", function (Request $request, Response $response)
        {
            if (empty($_SESSION["resetToken"]))
            {
                // uh oh not authorized to resend email
                return $response->withStatus(401);
            }

            $_SESSION["resetToken"] = $this->user->sendResetEmail($_SESSION["resetEmail"]);
            return $response;
        });

        $app->get("/user/checkResetCode/{code}", function (Request $request, Response $response, array $args)
        {
            if (empty($args["code"]))
            {
                // uh oh sent empty data
                return $response->withStatus(400);
            }

            if ($_SESSION["resetToken"] === $args["code"])
            {
                // yay, code code matches
                return $response;
            }

            return $response->withStatus(401);
        });

        $app->post("/user/login", function (Request $request, Response $response)
        {
            // get request data
            $data = $request->getParsedBody();

            if (empty($data["username"]) || empty($data["password"]))
            {
                // uh oh user sent empty data
                return $response->withStatus(400);
            }

            if ($this->user->checkUser($data["username"], $data["password"]))
            {
                // yay, user is logged in
                $_SESSION["token"] = $this->user->createToken($data["username"]);
                $_SESSION["username"] = $data["username"];

                $inactive = 60 * 60 * 48; // 2 days
                $_SESSION["timeout"] = time() + $inactive;

                $response->getBody()->write(json_encode(array("token" => $_SESSION["token"])));
                return $response;
            }
            $response->getBody()->write(json_encode(array("error" => "Unauthorised")));
            return $response->withStatus(401);
        });

        $app->post("/user/acs", function (Request $request, Response $response)
        {
            $this->samlAuth->processResponse();

            $attributes = $this->samlAuth->getAttributes();
            $username = $attributes["username"][0];
            $email = $attributes["email"][0];

            if ($this->user->checkSAMLUser($username, $email))
            {
                // yay, user is logged in
                $_SESSION["token"] = $this->user->createToken($username);
                $_SESSION["username"] = $username;
                $_SESSION["email"] = $email;

                $inactive = 60 * 60 * 48; // 2 days
                $_SESSION["timeout"] = time() + $inactive;

                return $response->withHeader("Location", "https://rohitpai.co.uk/editor/editor.html")->withStatus(302);
            }

            $response->getBody()->write(json_encode(array("error" => "Unauthorised")));
            return $response->withStatus(401);
        });

        $app->post("/user/changePassword", function (Request $request, Response $response)
        {
            if (empty($_SESSION["resetToken"]) && empty($_SESSION["resetEmail"]))
            {
                // uh oh not authorized to change password
                return $response->withStatus(401);
            }

            $data = $request->getParsedBody();
            if (empty($data["password"]))
            {
                // uh oh sent empty data
                return $response->withStatus(400);
            }

            if ($this->user->changePassword($_SESSION["resetEmail"], $data["password"]))
            {
                // yay, password changed
                unset($_SESSION["resetToken"]);
                unset($_SESSION["resetEmail"]);
                return $response->withStatus(201);
            }

            return $response->withStatus(500);
        });
    }
}