#include "dx_exception.h"
#include <stdexcept>
#include <Windows.h>
#include <sstream>

namespace {
std::wstring HResultToWString(HRESULT hr) {
    LPWSTR buffer = nullptr;

    DWORD flags =
            FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_FROM_SYSTEM |
            FORMAT_MESSAGE_IGNORE_INSERTS;

    DWORD len = FormatMessageW(
        flags, nullptr, hr,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        reinterpret_cast<LPWSTR>(&buffer), 0, nullptr);

    // 如果是 HRESULT_FROM_WIN32(...) 形式，尝试取低 16 位 Win32 error code
    if (len == 0 && HRESULT_FACILITY(hr) == FACILITY_WIN32) {
        len = FormatMessageW(
            flags,
            nullptr,
            HRESULT_CODE(hr),
            MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
            reinterpret_cast<LPWSTR>(&buffer),
            0,
            nullptr
        );
    }

    if (len == 0) {
        wchar_t fallback[64];
        swprintf_s(fallback, L"Unknown HRESULT: 0x%08X", static_cast<unsigned>(hr));
        return fallback;
    }

    std::wstring message(buffer, len);
    LocalFree(buffer);

    return message;
}
std::wstring GetErrorMessage(DWORD errorCode) {
    LPWSTR buffer = nullptr;

    DWORD length = FormatMessageW(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        nullptr,
        errorCode,
        0, // 使用系统默认语言
        reinterpret_cast<LPWSTR>(&buffer),
        0,
        nullptr
    );

    if (length == 0) {
        return L"未知错误，错误代码：" + std::to_wstring(errorCode);
    }

    std::wstring message(buffer, length);
    LocalFree(buffer);

    // FormatMessage 返回的文本通常带有回车换行
    while (!message.empty() &&
           (message.back() == L'\r' ||
            message.back() == L'\n' ||
            message.back() == L' ')) {
        message.pop_back();
    }

    return message;
}
std::string WStringToUtf8(const std::wstring &wstr) {
    if (wstr.empty()) {
        return {};
    }

    int size = WideCharToMultiByte(
        CP_UTF8, // 转成 UTF-8
        0, // UTF-8 常用 0
        wstr.c_str(),
        static_cast<int>(wstr.size()), // 不包含结尾 \0
        nullptr,
        0,
        nullptr, // UTF-8 时必须是 nullptr
        nullptr // UTF-8 时必须是 nullptr
    );

    if (size == 0) {
        throw std::runtime_error("WideCharToMultiByte size query failed");
    }

    std::string result(size, '\0');

    int written = WideCharToMultiByte(
        CP_UTF8,
        0,
        wstr.c_str(),
        static_cast<int>(wstr.size()),
        result.data(),
        size,
        nullptr,
        nullptr
    );

    if (written == 0) {
        throw std::runtime_error("WideCharToMultiByte conversion failed");
    }

    return result;
}

}

void ThrowIfFailed(HRESULT hr, LPCWSTR caption) {
    if (!FAILED(hr)) return;
    std::wostringstream oss;
    DWORD errc = GetLastError();
    oss << L"HR:" << hr << L" msg:" << HResultToWString(hr) << L"\nLastError CODE: " << errc <<
            L"\nError Msg: " << GetErrorMessage(errc);
    std::wstring str = oss.str();
    std::string u8str = WStringToUtf8(str);
    MessageBoxW(nullptr, str.c_str(), caption,MB_OK);

    throw std::runtime_error{u8str};
}












//
