#pragma once
#include <windows.h>
#include <string>
#include <vector>
#include <algorithm>

struct HistoryEntry { std::wstring path; std::wstring label; };

inline std::wstring HistoryDir() {
    wchar_t buf[MAX_PATH]; GetModuleFileNameW(nullptr, buf, MAX_PATH);
    std::wstring p(buf); p = p.substr(0, p.find_last_of(L"\\/"));
    return p + L"\\history";
}

inline bool WriteFileUtf8(const std::wstring& path, const std::wstring& text) {
    int n = WideCharToMultiByte(CP_UTF8, 0, text.c_str(), (int)text.size(), nullptr, 0, nullptr, nullptr);
    std::string u8(n, '\0');
    if (n) WideCharToMultiByte(CP_UTF8, 0, text.c_str(), (int)text.size(), &u8[0], n, nullptr, nullptr);
    HANDLE h = CreateFileW(path.c_str(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
    if (h == INVALID_HANDLE_VALUE) return false;
    DWORD wr; const unsigned char bom[3] = {0xEF,0xBB,0xBF};
    WriteFile(h, bom, 3, &wr, nullptr);
    WriteFile(h, u8.data(), (DWORD)u8.size(), &wr, nullptr);
    CloseHandle(h);
    return true;
}

inline std::wstring ReadFileUtf8(const std::wstring& path) {
    HANDLE h = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
    if (h == INVALID_HANDLE_VALUE) return L"";
    DWORD size = GetFileSize(h, nullptr), rd = 0;
    std::string u8(size, '\0');
    if (size) ReadFile(h, &u8[0], size, &rd, nullptr);
    CloseHandle(h);
    size_t off = (u8.size() >= 3 && (unsigned char)u8[0]==0xEF && (unsigned char)u8[1]==0xBB && (unsigned char)u8[2]==0xBF) ? 3 : 0;
    int n = MultiByteToWideChar(CP_UTF8, 0, u8.data()+off, (int)(u8.size()-off), nullptr, 0);
    std::wstring w(n, L'\0');
    if (n) MultiByteToWideChar(CP_UTF8, 0, u8.data()+off, (int)(u8.size()-off), &w[0], n);
    return w;
}

inline void PruneHistory(int keep) {
    std::vector<std::wstring> files;
    WIN32_FIND_DATAW fd;
    HANDLE h = FindFirstFileW((HistoryDir() + L"\\*.txt").c_str(), &fd);
    if (h == INVALID_HANDLE_VALUE) return;
    do { files.push_back(HistoryDir() + L"\\" + fd.cFileName); } while (FindNextFileW(h, &fd));
    FindClose(h);
    std::sort(files.begin(), files.end());
    for (int i = 0; i < (int)files.size() - keep; ++i) DeleteFileW(files[i].c_str());
}

inline std::wstring ArchiveSession(const std::wstring& text) {
    bool any = false; for (wchar_t c : text) if (!iswspace(c)) { any = true; break; }
    if (!any) return L"";
    CreateDirectoryW(HistoryDir().c_str(), nullptr);
    SYSTEMTIME t; GetLocalTime(&t);
    wchar_t name[64];
    swprintf_s(name, L"%04d-%02d-%02d_%02d%02d%02d.txt", t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond);
    std::wstring path = HistoryDir() + L"\\" + name;
    WriteFileUtf8(path, text);
    PruneHistory(100);
    return path;
}

inline std::vector<HistoryEntry> LoadHistoryIndex() {
    std::vector<HistoryEntry> out;
    WIN32_FIND_DATAW fd;
    HANDLE h = FindFirstFileW((HistoryDir() + L"\\*.txt").c_str(), &fd);
    if (h == INVALID_HANDLE_VALUE) return out;
    do {
        HistoryEntry e;
        e.path = HistoryDir() + L"\\" + fd.cFileName;
        std::wstring stem(fd.cFileName);
        stem = stem.substr(0, stem.find(L'.'));
        std::wstring preview = ReadFileUtf8(e.path).substr(0, 60);
        for (wchar_t& c : preview) if (c == L'\r' || c == L'\n') c = L' ';
        e.label = stem.substr(0, 10) + L" " + stem.substr(11, 2) + L":" + stem.substr(13, 2)
                + L"  \u2014  " + preview + L"\u2026";
        out.push_back(e);
    } while (FindNextFileW(h, &fd));
    FindClose(h);
    std::sort(out.begin(), out.end(), [](auto& a, auto& b){ return a.path > b.path; });
    return out;
}
