// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright OpenBMC Authors
#pragma once

#include "app.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "routing.hpp"
#include "webroutes.hpp"

#include <boost/container/flat_set.hpp>

#include <algorithm>
#include <array>
#include <filesystem>
#include <fstream>
#include <string>
#include <string_view>

namespace crow
{
namespace webassets
{

inline std::string getStaticEtag(const std::filesystem::path& webpath)
{
    // webpack outputs production chunks in the form:
    // <filename>.<hash>.<extension>
    // For example app.63e2c453.css
    // Try to detect this, so we can use the hash as the ETAG
    std::vector<std::string> split;
    bmcweb::split(split, webpath.filename().string(), '.');
    if (split.size() < 3)
    {
        return "";
    }

    // get the second to last element
    std::string hash = split.rbegin()[1];

    // Webpack hashes are 8 characters long
    if (hash.size() != 8)
    {
        return "";
    }
    // Webpack hashes only include hex printable characters
    if (hash.find_first_not_of("0123456789abcdefABCDEF") != std::string::npos)
    {
        return "";
    }
    return std::format("\"{}\"", hash);
}

static constexpr std::string_view rootpath("/usr/share/www/");

struct StaticFile
{
    std::filesystem::path absolutePath;
    std::string_view contentType;
    std::string_view contentEncoding;
    std::string etag;
    bool renamed = false;
};

inline void handleStaticAsset(
    const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const StaticFile& file)
{
    if (!file.contentType.empty())
    {
        asyncResp->res.addHeader(boost::beast::http::field::content_type,
                                 file.contentType);
    }

    if (!file.contentEncoding.empty())
    {
        asyncResp->res.addHeader(boost::beast::http::field::content_encoding,
                                 file.contentEncoding);
    }

    if (!file.etag.empty())
    {
        asyncResp->res.addHeader(boost::beast::http::field::etag, file.etag);
        // Don't cache paths that don't have the etag in them, like
        // index, which gets transformed to /
        if (!file.renamed)
        {
            // Anything with a hash can be cached forever and is
            // immutable
            asyncResp->res.addHeader(boost::beast::http::field::cache_control,
                                     "max-age=31556926, immutable");
        }

        std::string_view cachedEtag =
            req.getHeaderValue(boost::beast::http::field::if_none_match);
        if (cachedEtag == file.etag)
        {
            asyncResp->res.result(boost::beast::http::status::not_modified);
            return;
        }
    }

    if (asyncResp->res.openFile(file.absolutePath) != crow::OpenCode::Success)
    {
        BMCWEB_LOG_DEBUG("failed to read file");
        asyncResp->res.result(
            boost::beast::http::status::internal_server_error);
        return;
    }
}

inline std::string_view getFiletypeForExtension(std::string_view extension)
{
    constexpr static std::array<std::pair<std::string_view, std::string_view>,
                                17>
        contentTypes{
            {{".css", "text/css;charset=UTF-8"},
             {".eot", "application/vnd.ms-fontobject"},
             {".gif", "image/gif"},
             {".html", "text/html;charset=UTF-8"},
             {".ico", "image/x-icon"},
             {".jpeg", "image/jpeg"},
             {".jpg", "image/jpeg"},
             {".js", "application/javascript;charset=UTF-8"},
             {".json", "application/json"},
             // dev tools don't care about map type, setting to json causes
             // browser to show as text
             // https://stackoverflow.com/questions/19911929/what-mime-type-should-i-use-for-javascript-source-map-files
             {".map", "application/json"},
             {".png", "image/png;charset=UTF-8"},
             {".svg", "image/svg+xml"},
             {".ttf", "application/x-font-ttf"},
             {".woff", "application/x-font-woff"},
             {".woff2", "application/x-font-woff2"},
             {".xml", "application/xml"}}};

    const auto* contentType =
        std::ranges::find_if(contentTypes, [&extension](const auto& val) {
            return val.first == extension;
        });

    if (contentType == contentTypes.end())
    {
        BMCWEB_LOG_ERROR(
            "Cannot determine content-type for file with extension {}",
            extension);
        return "";
    }
    return contentType->second;
}

inline void addFile(App& app, const std::filesystem::directory_entry& dir)
{
    StaticFile file;
    file.absolutePath = dir.path();
    std::filesystem::path relativePath(
        file.absolutePath.string().substr(rootpath.size() - 1));

    std::string extension = relativePath.extension();
    std::filesystem::path webpath = relativePath;

    if (extension == ".gz")
    {
        webpath = webpath.replace_extension("");
        // Use the non-gzip version for determining content type
        extension = webpath.extension().string();
        file.contentEncoding = "gzip";
    }
    else if (extension == ".zstd")
    {
        webpath = webpath.replace_extension("");
        // Use the non-zstd version for determining content type
        extension = webpath.extension().string();
        file.contentEncoding = "zstd";
    }

    file.etag = getStaticEtag(webpath);

    if (webpath.filename().string().starts_with("index."))
    {
        webpath = webpath.parent_path();
        if (webpath.string().empty() || webpath.string().back() != '/')
        {
            // insert the non-directory version of this path
            webroutes::routes.insert(webpath);
            webpath += "/";
            file.renamed = true;
        }
    }

    std::pair<boost::container::flat_set<std::string>::iterator, bool>
        inserted = webroutes::routes.insert(webpath);

    if (!inserted.second)
    {
        // Got a duplicated path.  This is expected in certain
        // situations
        BMCWEB_LOG_DEBUG("Got duplicated path {}", webpath.string());
        return;
    }
    file.contentType = getFiletypeForExtension(extension);

    if (webpath == "/")
    {
        forward_unauthorized::hasWebuiRoute = true;
    }

    app.routeDynamic(webpath)(
        [file = std::move(
             file)](const crow::Request& req,
                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
            handleStaticAsset(req, asyncResp, file);
        });
}

inline void requestRoutes(App& app)
{
    std::error_code ec;
    std::filesystem::recursive_directory_iterator dirIter({rootpath}, ec);
    if (ec)
    {
        BMCWEB_LOG_ERROR(
            "Unable to find or open {} static file hosting disabled", rootpath);
        return;
    }

    // In certain cases, we might have both a gzipped version of the file AND a
    // non-gzipped version.  To avoid duplicated routes, we need to make sure we
    // get the gzipped version first.  Because the gzipped path should be longer
    // than the non gzipped path, if we sort in descending order, we should be
    // guaranteed to get the gzip version first.
    std::vector<std::filesystem::directory_entry> paths(
        std::filesystem::begin(dirIter), std::filesystem::end(dirIter));
    std::sort(paths.rbegin(), paths.rend());

    for (const std::filesystem::directory_entry& dir : paths)
    {
        if (std::filesystem::is_directory(dir))
        {
            // don't recurse into hidden directories or symlinks
            if (dir.path().filename().string().starts_with(".") ||
                std::filesystem::is_symlink(dir))
            {
                dirIter.disable_recursion_pending();
            }
        }
        else if (std::filesystem::is_regular_file(dir))
        {
            addFile(app, dir);
        }
    }
}
} // namespace webassets
} // namespace crow
