<?php

namespace api\project;

use api\utils\imgUtils;
use PDO;
use Psr\Http\Message\UploadedFileInterface;

require_once __DIR__ . "/../utils/config.php";
require_once __DIR__ . "/../utils/imgUtils.php";

/**
 * Project Data Class
 * Define all functions which either get, update, create or delete timeline data
 */
class projectData
{
    /**
     * Get all project data
     * @return array<array> - Array of all project data or error message
     */
    public function getProjectData(): array
    {
        $conn = dbConn();
        $stmt = $conn->prepare("SELECT ID, title, isMainProject, information, imgLocation, projectLink, gitLink FROM projects ORDER BY isMainProject DESC;");
        $stmt->execute();

        // set the resulting array to associative
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);

        if ($result)
        {
            return $result;
        }

        return array("errorMessage" => "Error, project data not found");
    }


    /**
     * Update project data in the database with the given ID
     * @param string $ID - ID of the project in the database to update
     * @param string $title - Title of the project
     * @param bool $isMainProject - Is the project a main project or not
     * @param string $information - Information about the project
     * @param string $projectLink - Link to the project
     * @param string $gitLink - Link to the git repository
     * @return bool|string - True if project was updated, false if not and there was an error, or an error string
     */
    public function updateProjectData(string $ID, string $title, bool $isMainProject, string $information, string $projectLink, string $gitLink): bool|string
    {
        $conn = dbConn();

        $stmtMainProject = $conn->prepare("SELECT isMainProject FROM projects WHERE ID = :ID");
        $stmtMainProject->bindParam(":ID", $ID);
        $stmtMainProject->execute();
        $result = $stmtMainProject->fetch(PDO::FETCH_ASSOC);

        if (!$result)
        {
            return "project not found";
        }

        if (!$isMainProject && $result["isMainProject"] === "1")
        {
            return "unset main project";
        }

        if ($isMainProject)
        {
            $stmtMainProject = $conn->prepare("UPDATE projects SET isMainProject = 0 WHERE isMainProject = 1;");
            $stmtMainProject->execute();
        }

        $stmt = $conn->prepare("UPDATE projects SET title = :title, isMainProject = :isMainProject, information = :information,  projectLink = :projectLink, gitLink = :gitLink WHERE ID = :ID");
        $stmt->bindParam(":title", $title);
        $isMainProj = $isMainProject ? 1 : 0;
        $stmt->bindParam(":isMainProject", $isMainProj);
        $stmt->bindParam(":information", $information);
        $stmt->bindParam(":projectLink", $projectLink);
        $stmt->bindParam(":gitLink", $gitLink);
        $stmt->bindParam(":ID", $ID);
        return $stmt->execute();
    }

    /**
     * Delete project data from the database
     * @param int $ID - ID of the project in the database to delete
     * @return string - True if project was deleted, false if not and there was an error
     */
    public function deleteProjectData(int $ID): string
    {
        $conn = dbConn();

        // check if the project is a main project if it is return false
        $stmtMainProject = $conn->prepare("SELECT isMainProject FROM projects WHERE ID = :ID");
        $stmtMainProject->bindParam(":ID", $ID);
        $stmtMainProject->execute();
        $result = $stmtMainProject->fetch(PDO::FETCH_ASSOC);

        if (!$result)
        {
            return "project not found";
        }

        if ($result["isMainProject"] === "1")
        {
            return "cannot delete";
        }

        $this->deleteImage($ID);

        $stmt = $conn->prepare("DELETE FROM projects WHERE ID = :ID");
        $stmt->bindParam(":ID", $ID);
        $stmt->execute();

        if ($stmt->rowCount() > 0)
        {
            return "ok";
        }

        return "error";
    }

    /**
     * Add project data to the database
     * @param string $title - Title of the project
     * @param string $isMainProject - Is the project a main project or not
     * @param string $information - Information about the project
     * @param string $projectLink - Link to the project
     * @param string $gitLink - Link to the github repository
     * @return int|bool - ID of the project if it was added, false if not and there was an error
     */
    public function addProjectData(string $title, string $isMainProject, string $information, string $projectLink, string $gitLink): int|bool
    {

        $conn = dbConn();
        if ($isMainProject === "true")
        {
            $stmtMainProject = $conn->prepare("UPDATE projects SET isMainProject = 0 WHERE isMainProject = 1;");
            $stmtMainProject->execute();
        }

        $stmt = $conn->prepare("INSERT INTO projects (title, isMainProject, information, projectLink, gitLink) VALUES (:title, :isMainProject, :information, :projectLink, :gitLink)");
        $stmt->bindParam(":title", $title);
        $isMainProj = ($isMainProject === "true") ? 1 : 0;
        $stmt->bindParam(":isMainProject", $isMainProj);
        $stmt->bindParam(":information", $information);
        $stmt->bindParam(":projectLink", $projectLink);
        $stmt->bindParam(":gitLink", $gitLink);
        $stmt->execute();

        if ($stmt->rowCount() > 0)
        {
            return $conn->lastInsertId();
        }

        return false;
    }

    /**
     * Upload the image to the server and update the database with the new image location
     * @param int $ID - ID of the project in the database to update
     * @param UploadedFileInterface $img - Image preview of the project
     * @return string|array - String with error message or array with the new image location
     */
    public function uploadImage(int $ID, UploadedFileInterface $img): string|array
    {

        $conn = dbConn();

        $stmt = $conn->prepare("SELECT ID FROM projects WHERE ID = :ID");
        $stmt->bindParam(":ID", $ID);
        $stmt->execute();
        $result = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$result)
        {
            return "Project with ID $ID not found";
        }


        $targetDir = "../imgs/projects/";
        $imgUtils = new imgUtils();
        $targetFile = $imgUtils->uploadFile($targetDir, $img);

        if (!is_array($targetFile))
        {
            return $targetFile;
        }

        if (file_exists($targetFile["imgLocation"]))
        {
            $this->deleteImage($ID);
            // update the database with the new image location
            $stmt = $conn->prepare("UPDATE projects SET imgLocation = :imgLocation WHERE ID = :ID");
            $stmt->bindParam(":imgLocation", $targetFile["imgLocation"]);
            $stmt->bindParam(":ID", $ID);
            $stmt->execute();

            if ($stmt->rowCount() > 0)
            {
                return array("imgLocation" => $targetFile["imgLocation"]);
            }

            return "Couldn't update the database";
        }

        return "Couldn't upload the image";
    }

    /**
     * Delete the image from the server
     * @param int $ID - ID of the project in the database
     */
    private function deleteImage(int $ID): void
    {
        $conn = dbConn();
        $imgStmt = $conn->prepare("SELECT imgLocation FROM projects WHERE ID = :ID");
        $imgStmt->bindParam(":ID", $ID);
        $imgStmt->execute();
        $imgLocation = $imgStmt->fetch(PDO::FETCH_ASSOC)["imgLocation"];

        if ($imgLocation != null)
        {
            unlink($imgLocation);
        }
    }
}