#include "HttpController.hpp"
#include "server.hpp"
#include "put_handler.hpp"
#include "update_handler.hpp"
#include "welcome_page.hpp"
#include <nlohmann/json.hpp>

namespace simple_object_storage {

void HttpController::getIndex(const drogon::HttpRequestPtr &req,
                              std::function<void(const drogon::HttpResponsePtr &)> &&callback) {
    auto resp = drogon::HttpResponse::newHttpResponse();
    resp->setBody(welcome_page());
    resp->setContentTypeCode(drogon::CT_TEXT_HTML);
    auto server = Server::getInstance();
    if (server) {
        server->add_security_headers(resp);
    }
    callback(resp);
}

void HttpController::getHash(const drogon::HttpRequestPtr &req,
                             std::function<void(const drogon::HttpResponsePtr &)> &&callback,
                             const std::string &key) {
    auto server = Server::getInstance();
    if (server) {
        server->handle_get_hash(req, std::move(callback), key);
    } else {
        auto resp = drogon::HttpResponse::newHttpResponse();
        resp->setStatusCode(drogon::k500InternalServerError);
        // Try to add security headers if server instance is available
        auto srv = Server::getInstance();
        if (srv) {
            srv->add_security_headers(resp);
        }
        callback(resp);
    }
}

void HttpController::getVersion(const drogon::HttpRequestPtr &req,
                                std::function<void(const drogon::HttpResponsePtr &)> &&callback,
                                const std::string &key) {
    auto server = Server::getInstance();
    if (server) {
        server->handle_get_version(req, std::move(callback));
    } else {
        auto resp = drogon::HttpResponse::newHttpResponse();
        resp->setStatusCode(drogon::k500InternalServerError);
        // Try to add security headers if server instance is available
        auto srv = Server::getInstance();
        if (srv) {
            srv->add_security_headers(resp);
        }
        callback(resp);
    }
}

void HttpController::checkExists(const drogon::HttpRequestPtr &req,
                                 std::function<void(const drogon::HttpResponsePtr &)> &&callback,
                                 const std::string &key) {
    auto server = Server::getInstance();
    if (server) {
        server->handle_exists(req, std::move(callback), key);
    } else {
        auto resp = drogon::HttpResponse::newHttpResponse();
        resp->setStatusCode(drogon::k500InternalServerError);
        // Try to add security headers if server instance is available
        auto srv = Server::getInstance();
        if (srv) {
            srv->add_security_headers(resp);
        }
        callback(resp);
    }
}

void HttpController::getDirectory(const drogon::HttpRequestPtr &req,
                                  std::function<void(const drogon::HttpResponsePtr &)> &&callback) {
    auto server = Server::getInstance();
    if (server) {
        server->handle_get_directory(req, std::move(callback));
    } else {
        auto resp = drogon::HttpResponse::newHttpResponse();
        resp->setStatusCode(drogon::k500InternalServerError);
        // Try to add security headers if server instance is available
        auto srv = Server::getInstance();
        if (srv) {
            srv->add_security_headers(resp);
        }
        callback(resp);
    }
}

void HttpController::uploadObject(const drogon::HttpRequestPtr &req,
                                  std::function<void(const drogon::HttpResponsePtr &)> &&callback) {
    auto server = Server::getInstance();
    if (server && server->put_handler_) {
        server->put_handler_->handle_upload_object(req, std::move(callback));
    } else {
        auto resp = drogon::HttpResponse::newHttpResponse();
        resp->setStatusCode(drogon::k500InternalServerError);
        // Try to add security headers if server instance is available
        auto srv = Server::getInstance();
        if (srv) {
            srv->add_security_headers(resp);
        }
        callback(resp);
    }
}

void HttpController::updateObject(const drogon::HttpRequestPtr &req,
                                  std::function<void(const drogon::HttpResponsePtr &)> &&callback) {
    auto server = Server::getInstance();
    if (server && server->update_handler_) {
        server->update_handler_->handle_update_object(req, std::move(callback));
    } else {
        auto resp = drogon::HttpResponse::newHttpResponse();
        resp->setStatusCode(drogon::k500InternalServerError);
        // Try to add security headers if server instance is available
        auto srv = Server::getInstance();
        if (srv) {
            srv->add_security_headers(resp);
        }
        callback(resp);
    }
}

void HttpController::getMetadata(const drogon::HttpRequestPtr &req,
                                 std::function<void(const drogon::HttpResponsePtr &)> &&callback,
                                 const std::string &key) {
    auto server = Server::getInstance();
    if (server) {
        server->handle_get_metadata(req, std::move(callback), key);
    } else {
        auto resp = drogon::HttpResponse::newHttpResponse();
        resp->setStatusCode(drogon::k500InternalServerError);
        // Try to add security headers if server instance is available
        auto srv = Server::getInstance();
        if (srv) {
            srv->add_security_headers(resp);
        }
        callback(resp);
    }
}

void HttpController::deleteObject(const drogon::HttpRequestPtr &req,
                                  std::function<void(const drogon::HttpResponsePtr &)> &&callback) {
    auto server = Server::getInstance();
    if (server) {
        server->handle_delete_object(req, std::move(callback));
    } else {
        auto resp = drogon::HttpResponse::newHttpResponse();
        resp->setStatusCode(drogon::k500InternalServerError);
        // Try to add security headers if server instance is available
        auto srv = Server::getInstance();
        if (srv) {
            srv->add_security_headers(resp);
        }
        callback(resp);
    }
}

void HttpController::deleteOldObjects(const drogon::HttpRequestPtr &req,
                                       std::function<void(const drogon::HttpResponsePtr &)> &&callback) {
    auto server = Server::getInstance();
    if (server) {
        server->handle_delete_old_objects(req, std::move(callback));
    } else {
        auto resp = drogon::HttpResponse::newHttpResponse();
        resp->setStatusCode(drogon::k500InternalServerError);
        // Try to add security headers if server instance is available
        auto srv = Server::getInstance();
        if (srv) {
            srv->add_security_headers(resp);
        }
        callback(resp);
    }
}

void HttpController::getStatus(const drogon::HttpRequestPtr &req,
                               std::function<void(const drogon::HttpResponsePtr &)> &&callback) {
    auto resp = drogon::HttpResponse::newHttpResponse();
    nlohmann::json response = {{"result", "success"}, {"status", "ok"}};
    resp->setBody(response.dump());
    resp->setContentTypeCode(drogon::CT_APPLICATION_JSON);
    auto server = Server::getInstance();
    if (server) {
        server->add_security_headers(resp);
    }
    callback(resp);
}

void HttpController::getObject(const drogon::HttpRequestPtr &req,
                               std::function<void(const drogon::HttpResponsePtr &)> &&callback,
                               const std::string &key) {
    auto server = Server::getInstance();
    if (server) {
        server->handle_get_object(req, std::move(callback), key);
    } else {
        auto resp = drogon::HttpResponse::newHttpResponse();
        resp->setStatusCode(drogon::k500InternalServerError);
        // Try to add security headers if server instance is available
        auto srv = Server::getInstance();
        if (srv) {
            srv->add_security_headers(resp);
        }
        callback(resp);
    }
}

void HttpController::getRoot(const drogon::HttpRequestPtr &req,
                             std::function<void(const drogon::HttpResponsePtr &)> &&callback) {
    auto resp = drogon::HttpResponse::newHttpResponse();
    resp->setBody(welcome_page());
    resp->setContentTypeCode(drogon::CT_TEXT_HTML);
    auto server = Server::getInstance();
    if (server) {
        server->add_security_headers(resp);
    }
    callback(resp);
}

void HttpController::getAny(const drogon::HttpRequestPtr &req,
                            std::function<void(const drogon::HttpResponsePtr &)> &&callback,
                            const std::string &path) {
    auto server = Server::getInstance();
    if (server) {
        server->handle_get_object(req, std::move(callback), path);
    } else {
        auto resp = drogon::HttpResponse::newHttpResponse();
        resp->setStatusCode(drogon::k500InternalServerError);
        // Try to add security headers if server instance is available
        auto srv = Server::getInstance();
        if (srv) {
            srv->add_security_headers(resp);
        }
        callback(resp);
    }
}


} // namespace simple_object_storage