<?php

namespace api\blog;
require_once __DIR__ . "/../utils/routesInterface.php";
require_once "blogData.php";


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

class blogRoutes implements routesInterface
{
    private blogData $blogData;

    /**
     * constructor used to instantiate a base blog routes, to be used in the index.php file.
     * @param App $app - the slim app used to create the routes
     */
    public function __construct(App $app)
    {
        $this->blogData = new blogData();
        $this->createRoutes($app);
    }

    /**
     * creates the routes for the blog
     * @param App $app - the slim app used to create the routes
     * @return void - returns nothing
     */
    public function createRoutes(App $app): void
    {
        $app->get("/blog/categories", function (Request $request, Response $response)
        {
            $post = $this->blogData->getCategories();
            if (array_key_exists("errorMessage", $post))
            {
                $response->getBody()->write(json_encode($post));
                return $response->withStatus(404);
            }

            $response->getBody()->write(json_encode($post));
            return $response;
        });

        $app->get("/blog/categories/{category}", function (Request $request, Response $response, $args)
        {
            if ($args["category"] != null)
            {
                $post = $this->blogData->getPostsByCategory($args["category"]);
                if (array_key_exists("errorMessage", $post))
                {
                    $response->getBody()->write(json_encode($post));
                    return $response->withStatus(404);
                }

                $response->getBody()->write(json_encode($post));
                return $response;
            }

            $response->getBody()->write(json_encode(array("error" => "Please provide a category")));
            return $response->withStatus(400);
        });

        $app->get("/blog/post", function (Request $request, Response $response)
        {
            $posts = $this->blogData->getBlogPosts();

            $json = json_encode($posts);

            $response->getBody()->write($json);

            if (array_key_exists("errorMessage", $posts))
            {
                $response->withStatus(404);
            }

            return $response;
        });

        $app->get("/blog/post/{type}", function (Request $request, Response $response, $args)
        {
            if ($args["type"] == null)
            {
                $response->getBody()->write(json_encode(array("error" => "Please provide a title")));
                return $response->withStatus(400);
            }

            if ($args["type"] == "latest")
            {
                $post = $this->blogData->getLatestBlogPost();
                if (array_key_exists("errorMessage", $post))
                {
                    $response->getBody()->write(json_encode($post));
                    return $response->withStatus(404);
                }

                $response->getBody()->write(json_encode($post));
                return $response;
            }

            if ($args["type"] == "featured")
            {
                $post = $this->blogData->getFeaturedBlogPost();
                if (array_key_exists("errorMessage", $post))
                {
                    $response->getBody()->write(json_encode($post));
                    return $response->withStatus(404);
                }

                $response->getBody()->write(json_encode($post));
                return $response;
            }

            $post = $this->blogData->getBlogPost($args["type"]);
            if (array_key_exists("errorMessage", $post))
            {
                $response->getBody()->write(json_encode($post));
                return $response->withStatus(404);
            }

            $response->getBody()->write(json_encode($post));
            return $response;

        });

        $app->get("/blog/feed/{type}", function (Request $request, Response $response, $args)
        {
            if ($args["type"] == null)
            {
                $response->getBody()->write(json_encode(array("error" => "Please provide a title")));
                return $response->withStatus(400);
            }

            $feed = $this->blogData->getFeed($args["type"]);
            if (is_array($feed))
            {
                $response->getBody()->write(json_encode($feed));
                return $response->withStatus(404);
            }

            if ($args["type"] == "atom")
            {
                $response->getBody()->write($feed);
                return $response->withHeader("Content-Type", "application/atom+xml");
            }

            if ($args["type"] == "rss")
            {
                $response->getBody()->write($feed);
                return $response->withHeader("Content-Type", "application/rss+xml");
            }

            if ($args["type"] == "json")
            {
                $response->getBody()->write(json_encode($feed));
                return $response->withHeader("Content-Type", "application/feed+json");
            }

            $response->getBody()->write(json_encode(array("error" => "Invalid feed type")));
            return $response->withStatus(400);
        });

        $app->get("/blog/search/{searchTerm}", function (Request $request, $response, $args)
        {
            if ($args["searchTerm"] == null)
            {
                $response->getBody()->write(json_encode(array("error" => "Please provide a search term")));
                return $response->withStatus(400);
            }

            $posts = $this->blogData->searchBlog($args["searchTerm"]);

            $json = json_encode($posts);

            $response->getBody()->write($json);

            if (array_key_exists("errorMessage", $posts))
            {
                $response->withStatus(404);
            }

            return $response;

        });

        $app->patch("/blog/post/{id}", function (Request $request, Response $response, $args)
        {
            $data = $request->getParsedBody();
            if ($args["id"] == null)
            {
                $response->getBody()->write(json_encode(array("error" => "Please provide an ID")));
                return $response->withStatus(400);
            }

            if (empty($data["title"]) || strlen($data["featured"]) == 0 || empty($data["body"]) || empty($data["bodyText"]) || empty($data["dateModified"]) || empty($data["categories"]))
            {
                // uh oh sent some empty data
                $response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
                return $response->withStatus(400);
            }

            if (!preg_match('/[a-zA-Z0-9 ]+, |\w+/mx', $data["categories"]))
            {
                // uh oh sent some empty data
                $response->getBody()->write(json_encode(array("error" => "Categories must be in a CSV  format")));
                return $response->withStatus(400);
            }

            $message = $this->blogData->updatePost($args["id"], $data["title"], intval($data["featured"]), $data["abstract"], $data["body"], $data["bodyText"], $data["dateModified"], $data["categories"]);

            if ($message === "post not found")
            {
                // uh oh something went wrong
                $response->getBody()->write(json_encode(array("error" => "Error, post not found")));
                return $response->withStatus(404);
            }

            if ($message === "unset featured")
            {
                // uh oh something went wrong
                $response->getBody()->write(json_encode(array("error" => "Error, cannot unset featured post, try updating another post to be featured first")));
                return $response->withStatus(409);
            }

            if (!is_bool($message) || $message === false)
            {
                // uh oh something went wrong
                $response->getBody()->write(json_encode(array("error" => $message)));
                return $response->withStatus(500);
            }

            $response->withStatus(201);
            return $response;

        });

        $app->delete("/blog/post/{id}", function (Request $request, Response $response, $args)
        {
            if ($args["id"] == null)
            {
                $response->getBody()->write(json_encode(array("error" => "Please provide an ID")));
                return $response->withStatus(400);
            }

            $message = $this->blogData->deletePost($args["id"]);

            if ($message === "post not found")
            {
                // uh oh something went wrong
                $response->getBody()->write(json_encode(array("error" => "Error, post not found")));
                return $response->withStatus(404);
            }

            if ($message === "error")
            {
                // uh oh something went wrong
                $response->getBody()->write(json_encode(array("error" => "Error, something went wrong")));
                return $response->withStatus(500);
            }

            if ($message === "cannot delete")
            {
                // uh oh something went wrong
                $response->getBody()->write(json_encode(array("error" => "Error, cannot delete featured post")));
                return $response->withStatus(409);
            }
            return $response;
        });

        $app->delete("/blog/newsletter/{email}", function (Request $request, Response $response, $args)
        {
            if ($args["email"] == null)
            {
                $response->getBody()->write(json_encode(array("error" => "Please provide an email")));
                return $response->withStatus(400);
            }

            $message = $this->blogData->deleteNewsletterEmail($args["email"]);

            if ($message === "email not found")
            {
                // uh oh something went wrong
                $response->getBody()->write(json_encode(array("message" => "Woah, you're already trying to leave without signing up?")));
                return $response->withStatus(404);
            }

            if ($message === "error")
            {
                // uh oh something went wrong
                $response->getBody()->write(json_encode(array("message" => "Error, something went wrong")));
                return $response->withStatus(500);
            }

            $response->getBody()->write(json_encode(array("message" => "Sorry to see you go! You'll no longer receive any emails from me. If you change your mind, you can always sign up again.")));
            return $response;
        });

        $app->post("/blog/post", function (Request $request, Response $response)
        {
            $data = $request->getParsedBody();
            $files = $request->getUploadedFiles();
            if (empty($data["title"]) || strlen($data["featured"]) == 0 || empty($data["body"]) || empty($data["bodyText"]) || empty($data["abstract"]) || empty($data["dateCreated"]) || empty($data["categories"]))
            {
                // uh oh sent some empty data
                $response->getBody()->write(json_encode(array("error" => "Error, empty data sent")));
                return $response->withStatus(400);
            }

            if (!preg_match('/[a-zA-Z0-9 ]+, |\w+/mx', $data["categories"]))
            {
                // uh oh sent some empty data
                $response->getBody()->write(json_encode(array("error" => "Categories must be in a CSV  format")));
                return $response->withStatus(400);
            }

            if (array_key_exists("headerImg", $files))
            {
                $headerImg = $files["headerImg"];
            }

            if (empty($files["headerImg"]))
            {
                $headerImg = null;
            }

//            $featured = $data["featured"] === "true";
            $insertedID = $this->blogData->createPost($data["title"], $data["abstract"], $data["body"], $data["bodyText"], $data["dateCreated"], intval($data["featured"]), $data["categories"], $headerImg);
            if (!is_int($insertedID))
            {
                // uh oh something went wrong
                $response->getBody()->write(json_encode(array("error" => $insertedID)));
                return $response->withStatus(500);
            }
            $response->getBody()->write(json_encode(array("ID" => $insertedID)));
            return $response->withStatus(201);
        });

        $app->post("/blog/uploadPostImage", function (Request $request, Response $response)
        {
            $files = $request->getUploadedFiles();
            if (empty($files))
            {
                // uh oh sent some empty data
                $response->getBody()->write(json_encode(array("error" => array("message" => "Error, empty data sent"))));
                return $response->withStatus(400);
            }

            $message = $this->blogData->uploadPostImage($files["upload"]);
            if (!is_array($message))
            {
                $response->getBody()->write(json_encode(array("error" => array("message" => $message))));
                return $response->withStatus(500);
            }

            $response->getBody()->write(json_encode($message));
            return $response->withStatus(201);
        });

        $app->post("/blog/headerImage/{id}", function (Request $request, Response $response, $args)
        {
            $files = $request->getUploadedFiles();

            if ($args["id"] == null)
            {
                $response->getBody()->write(json_encode(array("error" => "Please provide an ID")));
                return $response->withStatus(400);
            }

            if (empty($files))
            {
                // uh oh sent some empty data
                $response->getBody()->write(json_encode(array("error" => "Error, empty data sent")));
                return $response->withStatus(400);
            }

            $message = $this->blogData->uploadHeaderImage($args["id"], $files["headerImg"]);
            if (!is_array($message))
            {
                $response->getBody()->write(json_encode(array("error" => $message)));
                return $response->withStatus(500);
            }

            $response->getBody()->write(json_encode($message));
            return $response->withStatus(201);
        });

        $app->post("/blog/newsletter", function (Request $request, Response $response)
        {
            $data = $request->getParsedBody();
            if (empty($data["subject"]) || empty($data["message"]))
            {
                // uh oh sent some empty data
                $response->getBody()->write(json_encode(array("error" => "Error, empty data sent")));
                return $response->withStatus(400);
            }

            $message = $this->blogData->sendNewsletter(strtolower($data["subject"]), $data["message"]);
            if (is_array($message))
            {
                $response->getBody()->write(json_encode(array("error" => "Error, something went wrong")));
                return $response->withStatus(500);
            }

            $response->getBody()->write(json_encode(array("message" => "Message sent")));
            return $response->withStatus(201);
        });

        $app->post("/blog/newsletter/{email}", function (Request $request, Response $response, $args)
        {
            if ($args["email"] == null)
            {
                $response->getBody()->write(json_encode(array("error" => "Please provide an email")));
                return $response->withStatus(400);
            }

            $message = $this->blogData->addNewsletterEmail($args["email"]);
            if ($message === "Email already exists")
            {
                $response->getBody()->write(json_encode(array("message" => "exists")));
                return $response->withStatus(409);
            }

            if (is_array($message) || !$message || $message === "error")
            {
                $response->getBody()->write(json_encode(array("message" => "Something went wrong")));
                return $response->withStatus(500);
            }

            $response->getBody()->write(json_encode(array("message" => "Thanks for signing up!")));
            return $response->withStatus(201);
        });

    }
}