#include "overlay.hpp"
#include "common/window_utils.hpp"

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>

#include <atomic>
#include <deque>
#include <mutex>
#include <string>
#include <thread>
#include <vector>

namespace overlay {

namespace {

std::mutex g_mutex;
std::vector<std::string> g_lines;
std::deque<std::string> g_recentLogs;
std::atomic<bool> g_running{false};
std::thread g_thread;
HWND g_hwnd = nullptr;

constexpr int kOverlayW = 680;
constexpr int kOverlayH = 480;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM w, LPARAM l) {
    if (msg == WM_DESTROY) { PostQuitMessage(0); return 0; }
    return DefWindowProcW(hwnd, msg, w, l);
}

HWND FindGameWindow() {
    return common::FindPoe2Window();
}

std::wstring Utf8ToWide(const std::string& utf8) {
    if (utf8.empty()) return L"";
    int size = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, nullptr, 0);
    if (size <= 0) return L"";
    std::wstring wide(size - 1, L'\0');
    MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, &wide[0], size);
    return wide;
}

void RenderThread() {
    WNDCLASSW wc{};
    wc.lpfnWndProc = WndProc;
    wc.hInstance = GetModuleHandleW(nullptr);
    wc.lpszClassName = L"AutoPOE2Overlay";
    RegisterClassW(&wc);

    g_hwnd = CreateWindowExW(
        WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOPMOST | WS_EX_NOACTIVATE,
        wc.lpszClassName, L"", WS_POPUP,
        16, 16, kOverlayW, kOverlayH,
        nullptr, nullptr, wc.hInstance, nullptr);
    if (!g_hwnd) { g_running = false; return; }

    // Colorkey: màu đen RGB(0, 0, 0) = trong suốt hoàn toàn
    SetLayeredWindowAttributes(g_hwnd, RGB(0, 0, 0), 0, LWA_COLORKEY);
    ShowWindow(g_hwnd, SW_SHOWNOACTIVATE);

    HFONT fontTitle = CreateFontW(-19, 0, 0, 0, FW_BOLD, 0, 0, 0, DEFAULT_CHARSET,
        OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY,
        FIXED_PITCH, L"Consolas");
    HFONT fontBody = CreateFontW(-15, 0, 0, 0, FW_SEMIBOLD, 0, 0, 0, DEFAULT_CHARSET,
        OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY,
        FIXED_PITCH, L"Consolas");
    HFONT fontLog = CreateFontW(-13, 0, 0, 0, FW_NORMAL, 0, 0, 0, DEFAULT_CHARSET,
        OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY,
        FIXED_PITCH, L"Consolas");

    // Persistent double-buffer bitmap & DC (TASK-OPT-12)
    HDC hdcScreen = GetDC(nullptr);
    HDC hdcMem = CreateCompatibleDC(hdcScreen);
    HBITMAP memBmp = CreateCompatibleBitmap(hdcScreen, kOverlayW, kOverlayH);
    HBITMAP oldBmp = (HBITMAP)SelectObject(hdcMem, memBmp);
    HBRUSH blackBrush = CreateSolidBrush(RGB(0, 0, 0));
    ReleaseDC(nullptr, hdcScreen);

    SetBkMode(hdcMem, TRANSPARENT);
    const RECT rcOverlay{ 0, 0, kOverlayW, kOverlayH };

    auto DrawOutlinedText = [&](HDC dc, int x, int y, const std::wstring& text, COLORREF color) {
        if (text.empty()) return;
        int len = static_cast<int>(text.size());
        SetTextColor(dc, RGB(12, 12, 12));
        TextOutW(dc, x + 1, y, text.c_str(), len);
        TextOutW(dc, x - 1, y, text.c_str(), len);
        TextOutW(dc, x, y + 1, text.c_str(), len);
        TextOutW(dc, x, y - 1, text.c_str(), len);
        SetTextColor(dc, color);
        TextOutW(dc, x, y, text.c_str(), len);
    };

    int tickCount = 0;
    while (g_running.load(std::memory_order_acquire)) {
        // Mỗi ~500ms (6 ticks), đồng bộ vị trí bám theo cửa sổ game POE2
        if ((++tickCount % 6) == 0) {
            HWND hGame = FindGameWindow();
            if (hGame) {
                if (IsIconic(hGame)) {
                    ShowWindow(g_hwnd, SW_HIDE);
                } else {
                    RECT rc{};
                    if (GetWindowRect(hGame, &rc) && (rc.right - rc.left) > 100) {
                        SetWindowPos(g_hwnd, HWND_TOPMOST, rc.left + 16, rc.top + 16,
                                     kOverlayW, kOverlayH, SWP_NOACTIVATE | SWP_SHOWWINDOW);
                    }
                }
            } else {
                ShowWindow(g_hwnd, SW_SHOWNOACTIVATE);
            }
        }

        if (hdcMem) {
            FillRect(hdcMem, &rcOverlay, blackBrush);

            std::vector<std::string> lines;
            std::deque<std::string> logs;
            {
                std::lock_guard<std::mutex> lk(g_mutex);
                lines = g_lines;
                logs = g_recentLogs;
            }

            int y = 6;
            // 1. Vẽ các dòng trạng thái & thông số Telemetry chính
            for (const auto& l : lines) {
                std::wstring wl = Utf8ToWide(l);
                bool isTitle = (l.find("HUD") != std::string::npos || l.find("AutoPOE2") != std::string::npos);
                bool isState = (l.find("TRẠNG THÁI") != std::string::npos || l.find("STATE") != std::string::npos);
                bool isGuide = (l.find("HƯỚNG DẪN") != std::string::npos || l.find("GUIDE") != std::string::npos);

                HFONT old = (HFONT)SelectObject(hdcMem, isTitle ? fontTitle : fontBody);

                COLORREF col = RGB(140, 255, 140); // Mặc định xanh lục nhạt
                if (isTitle) {
                    col = RGB(255, 230, 80); // Vàng tươi
                } else if (isState) {
                    if (l.find("CHỜ KHÓA HP") != std::string::npos || l.find("TỬ VONG") != std::string::npos || l.find("NGUY HIỂM") != std::string::npos) {
                        col = RGB(255, 95, 75); // Đỏ cam cảnh báo / chờ
                    } else if (l.find("TẠM DỪNG") != std::string::npos) {
                        col = RGB(255, 205, 60); // Vàng hổ phách
                    } else {
                        col = RGB(85, 255, 140); // Xanh lục hoạt động
                    }
                } else if (isGuide) {
                    col = RGB(110, 235, 255); // Xanh lơ hướng dẫn thao tác
                }

                DrawOutlinedText(hdcMem, 10, y, wl, col);
                SelectObject(hdcMem, old);
                y += (isTitle ? 25 : 21);
                if (y > kOverlayH - 120) break;
            }

            // 2. Đường kẻ phân tách và tiêu đề Log hoạt động realtime
            y += 4;
            DrawOutlinedText(hdcMem, 10, y, L"--------------------------------------------------------------------------------", RGB(120, 130, 140));
            y += 18;
            DrawOutlinedText(hdcMem, 10, y, L"📋 [ NHẬT KÝ THỜI GIAN THỰC (REALTIME LOGS) ]", RGB(255, 225, 90));
            y += 20;

            // 3. Vẽ danh sách các dòng nhật ký gần nhất
            HFONT oldLogFont = (HFONT)SelectObject(hdcMem, fontLog);
            for (const auto& logEntry : logs) {
                std::wstring wLog = Utf8ToWide(logEntry);
                COLORREF logCol = RGB(225, 230, 235); // Mặc định trắng xám sáng

                if (logEntry.find("LỖI") != std::string::npos || logEntry.find("FAILED") != std::string::npos ||
                    logEntry.find("Tử vong") != std::string::npos || logEntry.find("TỬ VONG") != std::string::npos) {
                    logCol = RGB(255, 120, 120);
                } else if (logEntry.find("THÀNH CÔNG") != std::string::npos || logEntry.find("KHÓA") != std::string::npos ||
                           logEntry.find("🎯") != std::string::npos || logEntry.find("OK") != std::string::npos) {
                    logCol = RGB(120, 255, 150);
                } else if (logEntry.find("Bơm") != std::string::npos || logEntry.find("Dodge") != std::string::npos) {
                    logCol = RGB(140, 210, 255);
                }

                DrawOutlinedText(hdcMem, 10, y, wLog, logCol);
                y += 18;
                if (y > kOverlayH - 20) break;
            }
            SelectObject(hdcMem, oldLogFont);

            HDC hdcWin = GetDC(g_hwnd);
            if (hdcWin) {
                BitBlt(hdcWin, 0, 0, kOverlayW, kOverlayH, hdcMem, 0, 0, SRCCOPY);
                ReleaseDC(g_hwnd, hdcWin);
            }
        }

        // Bơm message để cửa sổ không treo
        MSG msg;
        while (PeekMessageW(&msg, g_hwnd, 0, 0, PM_REMOVE)) {
            if (msg.message == WM_QUIT) { g_running = false; break; }
            TranslateMessage(&msg);
            DispatchMessageW(&msg);
        }
        Sleep(16); // ~60 FPS
    }

    // Giải phóng tài nguyên GDI
    if (hdcMem) {
        SelectObject(hdcMem, oldBmp);
        DeleteObject(memBmp);
        DeleteDC(hdcMem);
    }
    if (blackBrush) DeleteObject(blackBrush);
    if (fontTitle) DeleteObject(fontTitle);
    if (fontBody) DeleteObject(fontBody);
    if (fontLog) DeleteObject(fontLog);
    if (g_hwnd) DestroyWindow(g_hwnd);
    g_hwnd = nullptr;
}

} // namespace

void Start() {
    bool expected = false;
    if (!g_running.compare_exchange_strong(expected, true)) return;
    g_thread = std::thread(RenderThread);
}

void Stop() {
    g_running.store(false, std::memory_order_release);
    if (g_thread.joinable()) g_thread.join();
}

void SetLines(const std::vector<std::string>& lines) {
    std::lock_guard<std::mutex> lk(g_mutex);
    g_lines = lines;
}

void AddLog(const std::string& line) {
    if (line.empty()) return;
    SYSTEMTIME st;
    GetLocalTime(&st);
    char buf[16];
    snprintf(buf, sizeof(buf), "[%02d:%02d:%02d] ", st.wHour, st.wMinute, st.wSecond);

    std::string clean = line;
    if (clean.size() > 95) clean = clean.substr(0, 92) + "...";

    std::string entry = buf + clean;
    std::lock_guard<std::mutex> lk(g_mutex);
    g_recentLogs.push_back(entry);
    while (g_recentLogs.size() > 8) {
        g_recentLogs.pop_front();
    }
}

} // namespace overlay