#pragma once

// ==========================================================
// string_utils.hpp - String Manipulation & Hex Formatting
// C++23 Core Engine - AutoPOE2 (DOC-49 & Rule 16)
// ==========================================================

#include <string>
#include <string_view>
#include <vector>
#include <cstdint>
#include <cstddef>
#include <algorithm>
#include <sstream>
#include <iomanip>

namespace common {

/**
 * @brief Chuyển đổi chuỗi ký tự sang chữ thường (lowercase).
 * 
 * @param str Chuỗi ký tự đầu vào (std::string_view).
 * @return std::string Chuỗi kết quả toàn bộ ký tự thường.
 * 
 * @code
 * std::string lower = common::ToLower("POEWindowClass");
 * @endcode
 */
inline std::string ToLower(std::string_view str) {
    std::string res;
    res.reserve(str.size());
    for (char c : str) {
        res.push_back(static_cast<char>(std::tolower(static_cast<unsigned char>(c))));
    }
    return res;
}

/**
 * @brief Loại bỏ các ký tự khoảng trắng dư thừa ở đầu và cuối chuỗi (std::string_view).
 * 
 * Không phân bổ bộ nhớ mới trên heap, trả về string_view trực tiếp.
 * 
 * @param str Chuỗi ký tự đầu vào.
 * @return std::string_view Đoạn nhìn (view) đã được cắt tỉa khoảng trắng.
 */
inline std::string_view Trim(std::string_view str) noexcept {
    const size_t first = str.find_first_not_of(" \t\r\n");
    if (first == std::string_view::npos) return {};
    const size_t last = str.find_last_not_of(" \t\r\n");
    return str.substr(first, last - first + 1);
}

/**
 * @brief Tách chuỗi theo một ký tự phân cách (delimiter).
 * 
 * @param str Chuỗi ký tự cần tách.
 * @param delim Ký tự phân cách (mặc định ',').
 * @return std::vector<std::string> Danh sách các phân đoạn đã tách.
 */
inline std::vector<std::string> Split(std::string_view str, char delim = ',') {
    std::vector<std::string> result;
    size_t start = 0;
    while (start < str.size()) {
        size_t pos = str.find(delim, start);
        if (pos == std::string_view::npos) {
            result.emplace_back(str.substr(start));
            break;
        }
        result.emplace_back(str.substr(start, pos - start));
        start = pos + 1;
    }
    return result;
}

/**
 * @brief Tách chuỗi theo chuỗi con phân cách (delimiter string).
 * 
 * @param str Chuỗi ký tự cần tách.
 * @param delim Chuỗi con phân cách.
 * @return std::vector<std::string> Danh sách các phân đoạn đã tách.
 */
inline std::vector<std::string> Split(std::string_view str, std::string_view delim) {
    std::vector<std::string> result;
    if (delim.empty()) {
        result.emplace_back(str);
        return result;
    }
    size_t start = 0;
    while (start < str.size()) {
        size_t pos = str.find(delim, start);
        if (pos == std::string_view::npos) {
            result.emplace_back(str.substr(start));
            break;
        }
        result.emplace_back(str.substr(start, pos - start));
        start = pos + delim.size();
    }
    return result;
}

/**
 * @brief Định dạng vùng đệm nhị phân thành chuỗi Hex thập lục phân (uppercase).
 * 
 * @param data Con trỏ tới vùng nhớ cần format.
 * @param len Kích thước vùng nhớ tính theo byte.
 * @param spaceSeparated Nếu true, chèn dấu cách giữa các byte ("01 2A FF"). Nếu false: "012AFF".
 * @return std::string Chuỗi biểu diễn Hex.
 */
inline std::string HexStr(const void* data, size_t len, bool spaceSeparated = true) {
    if (!data || len == 0) return {};
    const auto* bytes = static_cast<const uint8_t*>(data);
    std::ostringstream oss;
    for (size_t i = 0; i < len; ++i) {
        if (i > 0 && spaceSeparated) oss << " ";
        oss << std::hex << std::uppercase << std::setw(2) << std::setfill('0')
            << static_cast<int>(bytes[i]);
    }
    return oss.str();
}

/**
 * @brief Định dạng giá trị số nguyên 64-bit sang chuỗi Hex viết hoa (hỗ trợ tiền tố 0x và độ rộng).
 * 
 * @param v Giá trị số nguyên 64-bit.
 * @param prefix Nếu true, chèn "0x" ở đầu chuỗi.
 * @param width Độ rộng tối thiểu (zero-padded). Nếu 0, không chèn padding.
 * @return std::string Chuỗi Hex.
 */
inline std::string HexStr(uint64_t v, bool prefix = false, int width = 0) {
    std::ostringstream oss;
    if (prefix) oss << "0x";
    oss << std::hex << std::uppercase;
    if (width > 0) oss << std::setw(width) << std::setfill('0');
    oss << v;
    return oss.str();
}

/**
 * @brief Kiểm tra xem chuỗi có bắt đầu bằng tiền tố (prefix) hay không.
 * 
 * @param str Chuỗi cần kiểm tra.
 * @param prefix Tiền tố cần so khớp.
 * @return true nếu str bắt đầu bằng prefix, false nếu không.
 */
inline bool StartsWith(std::string_view str, std::string_view prefix) noexcept {
    return str.starts_with(prefix);
}

/**
 * @brief Kiểm tra xem chuỗi có kết thúc bằng hậu tố (suffix) hay không.
 * 
 * @param str Chuỗi cần kiểm tra.
 * @param suffix Hậu tố cần so khớp.
 * @return true nếu str kết thúc bằng suffix, false nếu không.
 */
inline bool EndsWith(std::string_view str, std::string_view suffix) noexcept {
    return str.ends_with(suffix);
}

} // namespace common

using common::ToLower;
using common::Trim;
using common::Split;
using common::HexStr;
using common::StartsWith;
using common::EndsWith;
