#include "PathUtils.hpp"

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <algorithm>
#include <cctype>

namespace GModTeach {
namespace Platform {

std::filesystem::path PathUtils::GetExecutablePath() {
    wchar_t buffer[MAX_PATH];
    DWORD length = GetModuleFileNameW(nullptr, buffer, MAX_PATH);
    if (length == 0 || length == MAX_PATH) {
        return std::filesystem::current_path();
    }
    return std::filesystem::path(buffer);
}

std::filesystem::path PathUtils::GetExecutableDirectory() {
    return GetExecutablePath().parent_path();
}

std::filesystem::path PathUtils::GetGmadExecutablePath() {
    return GetExecutableDirectory() / L"gmad.exe";
}

std::filesystem::path PathUtils::Get7zExecutablePath() {
    return GetExecutableDirectory() / L"7za.exe";
}

std::string PathUtils::Trim(const std::string& s) {
    const size_t start = s.find_first_not_of(" \t\r\n");
    if (start == std::string::npos) return "";
    const size_t end = s.find_last_not_of(" \t\r\n");
    return s.substr(start, end - start + 1);
}

std::string PathUtils::ToLower(std::string s) {
    std::transform(s.begin(), s.end(), s.begin(),
        [](unsigned char c) { return static_cast<char>(std::tolower(c)); });
    return s;
}

std::filesystem::path PathUtils::FindInnerPayload(const std::filesystem::path& directory) {
    std::error_code ec;
    if (!std::filesystem::exists(directory, ec) || !std::filesystem::is_directory(directory, ec)) {
        return {};
    }

    for (const auto& entry : std::filesystem::directory_iterator(directory, ec)) {
        if (ec) break;
        if (entry.is_regular_file()) {
            const auto path = entry.path();
            if (path.extension().empty()) {
                return path;
            }
        }
    }
    return {};
}

std::vector<std::filesystem::path> PathUtils::CollectFilesByExtension(
    const std::filesystem::path& root,
    const std::string& targetExtension,
    bool recursive
) {
    std::vector<std::filesystem::path> files;
    std::error_code ec;

    if (!std::filesystem::exists(root, ec) || !std::filesystem::is_directory(root, ec)) {
        return files;
    }

    std::string lowerExt = ToLower(targetExtension);
    if (!lowerExt.empty() && lowerExt[0] != '.') {
        lowerExt = "." + lowerExt;
    }

    if (recursive) {
        for (const auto& entry : std::filesystem::recursive_directory_iterator(root, ec)) {
            if (ec) break;
            if (entry.is_regular_file()) {
                if (ToLower(entry.path().extension().string()) == lowerExt) {
                    files.push_back(entry.path());
                }
            }
        }
    } else {
        for (const auto& entry : std::filesystem::directory_iterator(root, ec)) {
            if (ec) break;
            if (entry.is_regular_file()) {
                if (ToLower(entry.path().extension().string()) == lowerExt) {
                    files.push_back(entry.path());
                }
            }
        }
    }

    return files;
}

} 
} 
