<?php

namespace App\Controllers;
use Config\Database;
use CodeIgniter\RESTful\ResourceController;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Files\File;
use App\Controllers\PermissionController;
use App\Controllers\TransferController;

class FilesController extends ResourceController
{
    /*
        Created: 2025-09-17
        Author: Kārlis Grīnvalds
        Last edited: 2026-06-01
        Edited by: Kārlis Grīnvalds
    */

    // Retrieves a certain files, topic name is needed
    public function GetTopicFiles($topic) {
        // Checks given data
        if (empty($topic)) {
            return $this->fail(["error" => "Where data?"], 400);
        }
        // Checks permissions
        $test = new TransferController();
        if ($test->CheckUserReadPermissions($topic) == false) {
            return $this->fail(["error" => "Not found!"], 404);
        }
        // Checks if topic exists
        $db = Database::connect();
        $topic_id = $db->query('CALL get_topic_id('.$db->escape($topic).')')->getResult();
        if (empty($topic_id)) {
            return $this->fail(["error" => "Not found!"], 404);
        }
        // Gets all the files that are related to the topic, prepares data and sends it
        $query = $db->query('CALL get_topic_files('.$db->escape($topic_id[0]->id).')')->getResult();
        $responses = [];
        if (!empty($query)) {
            foreach ($query as $row) {
                $responses[] = [
                    "id" => $row->id,
                    "name" => $row->name,
                    "given" => $row->given,
                    "created_at" => $row->created_at,
                    "edited_at" => $row->edited_at,
                ];
            }
        }
        return $this->respond(esc($responses), 200);
    }

    // Returns the actual file, topic and file name are needed
    public function LoadFile($topic, $fileName) {
        // Checks given data
        if (empty($topic) || empty($fileName)) {
            return $this->fail(["error" => "Where data?"], 400);
        }
        // Checks permissions
        $test = new TransferController();
        if ($test->CheckUserReadPermissions($topic) == false) {
            return $this->fail(["error" => "Not found!"], 404);
        }
        // Checks if topic exists
        $db = Database::connect();
        $file_id = $db->query('CALL verify_file('.$db->escape($fileName).', '.$db->escape($topic).')')->getResult();
        if (empty($file_id)) {
            return $this->fail(["error" => "Not found!"], 404);
        }
        // Finds the file
        $filePath = WRITEPATH."uploads/".$topic."/".$fileName;
        if (!is_file($filePath)) {
            return $this->fail(["error" => "Not found!"], 404);
        }
        // Returns source
        return $this->response
                ->setHeader("Content-Type", mime_content_type($filePath))
                ->setHeader("Content-Length", filesize($filePath))
                ->setBody(file_get_contents($filePath));
    }

    // Returns file information, file name is needed
    public function GetFile($fileName) {
        // Checks given data
        if (empty($fileName)) {
            return $this->fail(["error" => "Where data?"], 400);
        }
        $db = Database::connect();
        // Checks if file's data exists
        $query = $db->query('CALL get_file('.$db->escape($fileName).')')->getResult();
        if (!empty($query)) {
            // Checks permissions
            $test = new TransferController();
            if ($test->CheckUserReadPermissions($query[0]->topic_name) == false) {
                return $this->fail(["error" => "Not found!"], 404);
            }
            // Prepares data and sends it
            $responses = [];
            foreach ($query as $row) {
                $responses[] = [
                    "id" => $row->id,
                    "name" => $row->name,
                    "given" => $row->given,
                    "description" => $row->description,
                    "created_at" => $row->created_at,
                    "edited_at" => $row->edited_at,
                ];
            }
            return $this->respond(esc($responses), 200);
        }
        else {
            return $this->fail(["error" => "Not found!"], 404);
        }
    }

    // Creates new or updates file, file id is needed
    public function PostFile($id) {
        // Checks posted data
        if (empty($this->request->getPost())) {
            return $this->fail(["error" => "Where data?", "csrfHash" => csrf_hash()], 400);
        }
        // Checks if topic exists
        $db = Database::connect();
        $query = $db->query('CALL get_topic_id('.$db->escape($this->request->getPost("topic")).')')->getResult();
        if (empty($query)) {
            return $this->fail(["error" => "Not found!", "csrfHash" => csrf_hash()], 404);
        }
        $test = new PermissionController();
        $perms = $test->GetUserPermissions($this->request->getPost("topic"));
        $topicID = $query[0]->id;
        // If file doesn't exist, then it gets added, otherwise gets updated
        if ($id == 0) {
            // Checks permissions
            if (!empty($perms)) {
                if ($perms["upload"] == false && $perms["owner"] == false) {
                    return $this->fail(["error" => "You don't have the permission to do this!", "csrfHash" => csrf_hash()], 403);
                }
            }
            else {
                return $this->fail(["error" => "You don't have the permission to do this!", "csrfHash" => csrf_hash()], 403);
            }
            // Checks posted file
            if (empty($this->request->GetFile("file"))) {
                return $this->fail(["error" => "Where file?", "csrfHash" => csrf_hash()], 400);
            }
            $file = $this->request->GetFile("file");
            // Adds file to the server
            $newName = "";
            if ($file->isValid() && $file->getSize() > 0 && !$file->hasMoved()) {
                $newName = $file->getRandomName();
                $file->move(WRITEPATH."uploads/".$this->request->getPost("topic"), $newName);
            }
            else {
                return $this->fail(["error" => "Invalid file!", "csrfHash" => csrf_hash()], 406);
            }
            // Prepares data and creates new file entry
            $sendData = [
                "topic_id" => $topicID,
                "name" => $newName,
                "given" => $this->request->getPost("given"),
                "description" => $this->request->getPost("description")
            ];
            $db->query('CALL post_file('.$db->escape(json_encode($sendData)).')');
            return $this->respond(["message" => "Uploaded successfully!", "redirect" => $sendData["name"], "csrfHash" => csrf_hash()], 201);
        }
        else {
            // Checks permissions
            if (!empty($perms)) {
                if ($perms["edit_files"] == false && $perms["owner"] == false) {
                    return $this->fail(["error" => "You don't have the permission to do this!", "csrfHash" => csrf_hash()], 403);
                }
            }
            else {
                return $this->fail(["error" => "You don't have the permission to do this!", "csrfHash" => csrf_hash()], 403);
            }
            // Updates file description
            $db->query('CALL put_file('.$db->escape($id).', '.$db->escape($this->request->getPost("given")).', '.$db->escape($this->request->getPost("description")).')');
            return $this->respond(["message" => "Updated successfully!", "csrfHash" => csrf_hash()], 200);
        }
    }

    // Deletes file, file id is needed
    public function DeleteFile($id) {
        // Checks given data
        if (empty($id)) {
            return $this->fail(["error" => "Where data?", "csrfHash" => csrf_hash()], 400);
        }
        // Checks permissions
        $test = new PermissionController();
        $perms = $test->GetUserPermissions($this->request->getRawInput()["topic"]);
        if (!empty($perms)) {
            if ($perms["delete_files"] == true || $perms["owner"] == true) {
                $db = Database::connect();
                $db->query('CALL delete_file('.$db->escape($id).')');
                return $this->respond(["message" => "Deleted successfully!", "csrfHash" => csrf_hash()], 200);
            }
        }
        return $this->fail(["error" => "You don't have the permission to do this!", "csrfHash" => csrf_hash()], 403);
    }
}