--------------------------------------------------------------------------------
-- Nanami-UI: Book Reading UI (BookUI.lua)
-- Replaces ItemTextFrame with Nanami-UI styled interface + page flipping
--------------------------------------------------------------------------------

SFrames = SFrames or {}
SFrames.BookUI = {}
local BUI = SFrames.BookUI

--------------------------------------------------------------------------------
-- Theme (match QuestUI style)
--------------------------------------------------------------------------------
local T = SFrames.ActiveTheme

--------------------------------------------------------------------------------
-- Layout
--------------------------------------------------------------------------------
local FRAME_W       = 340
local FRAME_H       = 400
local HEADER_H      = 34
local BOTTOM_H      = 42
local SIDE_PAD      = 14
local CONTENT_W     = FRAME_W - SIDE_PAD * 2
local SCROLL_STEP   = 40
local BODY_FONT_SIZE = 12
local BODY_LINE_SPACING = 2

--------------------------------------------------------------------------------
-- State
--------------------------------------------------------------------------------
local MainFrame = nil

--------------------------------------------------------------------------------
-- Helpers
--------------------------------------------------------------------------------
local function GetFont()
    if SFrames and SFrames.GetFont then return SFrames:GetFont() end
    return "Fonts\\ARIALN.TTF"
end

local function SetRoundBackdrop(frame)
    frame:SetBackdrop({
        bgFile   = "Interface\\Tooltips\\UI-Tooltip-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 16, edgeSize = 14,
        insets = { left = 3, right = 3, top = 3, bottom = 3 },
    })
    frame:SetBackdropColor(T.panelBg[1], T.panelBg[2], T.panelBg[3], T.panelBg[4])
    frame:SetBackdropBorderColor(T.panelBorder[1], T.panelBorder[2], T.panelBorder[3], T.panelBorder[4])
end

local function CreateShadow(parent)
    local s = CreateFrame("Frame", nil, parent)
    s:SetPoint("TOPLEFT", parent, "TOPLEFT", -4, 4)
    s:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", 4, -4)
    s:SetBackdrop({
        bgFile   = "Interface\\Tooltips\\UI-Tooltip-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 16, edgeSize = 16,
        insets = { left = 4, right = 4, top = 4, bottom = 4 },
    })
    s:SetBackdropColor(0, 0, 0, 0.45)
    s:SetBackdropBorderColor(0, 0, 0, 0.6)
    s:SetFrameLevel(math.max(0, parent:GetFrameLevel() - 1))
    return s
end

local function TextHeight(fs, fallback)
    if not fs then return fallback or 14 end
    local h = fs.GetStringHeight and fs:GetStringHeight()
    if h and h > 0 then return h end
    h = fs:GetHeight()
    if h and h > 1 then return h end
    return fallback or 14
end

local function StripItemTextHTML(text)
    if not text or text == "" then return text end
    if not string.find(text, "<") then return text end

    text = string.gsub(text, "</?HTML>",  "")
    text = string.gsub(text, "</?html>",  "")
    text = string.gsub(text, "</?BODY>",  "")
    text = string.gsub(text, "</?body>",  "")
    text = string.gsub(text, "<H1[^>]*>", "")
    text = string.gsub(text, "<h1[^>]*>", "")
    text = string.gsub(text, "</H1>",     "\n")
    text = string.gsub(text, "</h1>",     "\n")
    text = string.gsub(text, "<P[^>]*>",  "")
    text = string.gsub(text, "<p[^>]*>",  "")
    text = string.gsub(text, "</P>",      "\n")
    text = string.gsub(text, "</p>",      "\n")
    text = string.gsub(text, "<BR/>",     "\n")
    text = string.gsub(text, "<br/>",     "\n")
    text = string.gsub(text, "<br>",      "\n")
    text = string.gsub(text, "<[^>]+>",   "")

    text = string.gsub(text, "^[\n%s]+",  "")
    text = string.gsub(text, "[\n%s]+$",  "")
    text = string.gsub(text, "\n\n\n+",   "\n\n")
    return text
end

local function IsTrue(v)
    return v == true or v == 1
end

local function CreateScrollArea(parent, name)
    local scroll = CreateFrame("ScrollFrame", name, parent)
    local content = CreateFrame("Frame", name .. "Content", scroll)
    content:SetWidth(CONTENT_W)
    content:SetHeight(1)
    scroll:SetScrollChild(content)

    scroll:EnableMouseWheel(true)
    scroll:SetScript("OnMouseWheel", function()
        local cur = this:GetVerticalScroll()
        local maxVal = this:GetVerticalScrollRange()
        if arg1 > 0 then
            this:SetVerticalScroll(math.max(0, cur - SCROLL_STEP))
        else
            this:SetVerticalScroll(math.min(maxVal, cur + SCROLL_STEP))
        end
    end)

    scroll.content = content
    return scroll
end

local function CreateActionBtn(parent, text, w)
    local btn = CreateFrame("Button", nil, parent)
    btn:SetWidth(w or 90)
    btn:SetHeight(28)
    btn:SetBackdrop({
        bgFile   = "Interface\\Tooltips\\UI-Tooltip-Background",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        tile = true, tileSize = 16, edgeSize = 14,
        insets = { left = 3, right = 3, top = 3, bottom = 3 },
    })
    btn:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
    btn:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], T.btnBorder[4])

    local fs = btn:CreateFontString(nil, "OVERLAY")
    fs:SetFont(GetFont(), 11, "OUTLINE")
    fs:SetPoint("CENTER", 0, 0)
    fs:SetTextColor(T.btnText[1], T.btnText[2], T.btnText[3])
    fs:SetText(text or "")
    btn.label = fs

    btn.disabled = false
    function btn:SetDisabled(flag)
        self.disabled = flag
        if flag then
            self.label:SetTextColor(T.btnDisabledText[1], T.btnDisabledText[2], T.btnDisabledText[3])
            self:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], 0.5)
        else
            self.label:SetTextColor(T.btnText[1], T.btnText[2], T.btnText[3])
            self:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
            self:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], T.btnBorder[4])
        end
    end

    btn:SetScript("OnEnter", function()
        if not this.disabled then
            this:SetBackdropColor(T.btnHoverBg[1], T.btnHoverBg[2], T.btnHoverBg[3], T.btnHoverBg[4])
            this:SetBackdropBorderColor(T.btnHoverBd[1], T.btnHoverBd[2], T.btnHoverBd[3], T.btnHoverBd[4])
            this.label:SetTextColor(T.btnActiveText[1], T.btnActiveText[2], T.btnActiveText[3])
        end
    end)
    btn:SetScript("OnLeave", function()
        if not this.disabled then
            this:SetBackdropColor(T.btnBg[1], T.btnBg[2], T.btnBg[3], T.btnBg[4])
            this:SetBackdropBorderColor(T.btnBorder[1], T.btnBorder[2], T.btnBorder[3], T.btnBorder[4])
            this.label:SetTextColor(T.btnText[1], T.btnText[2], T.btnText[3])
        end
    end)
    btn:SetScript("OnMouseDown", function()
        if not this.disabled then
            this:SetBackdropColor(T.btnDownBg[1], T.btnDownBg[2], T.btnDownBg[3], T.btnDownBg[4])
        end
    end)
    btn:SetScript("OnMouseUp", function()
        if not this.disabled then
            this:SetBackdropColor(T.btnHoverBg[1], T.btnHoverBg[2], T.btnHoverBg[3], T.btnHoverBg[4])
        end
    end)

    return btn
end

local function HideBlizzardItemText()
    if not ItemTextFrame then return end
    ItemTextFrame:SetAlpha(0)
    ItemTextFrame:EnableMouse(false)
    ItemTextFrame:ClearAllPoints()
    ItemTextFrame:SetPoint("TOPLEFT", UIParent, "BOTTOMRIGHT", 2000, 2000)
end

local function UpdateBookContent()
    if not MainFrame then return end

    local title = ItemTextGetItem and (ItemTextGetItem() or "") or ""
    local text = ItemTextGetText and (ItemTextGetText() or "") or ""
    if (not text or text == "") and ItemTextPageText and ItemTextPageText.GetText then
        text = ItemTextPageText:GetText() or ""
    end
    if text and text ~= "" then
        text = StripItemTextHTML(text)
        text = string.gsub(text, "\n%s*\n%s*\n+", "\n\n")
    end
    local pageNum = ItemTextGetPage and tonumber(ItemTextGetPage()) or 1
    if not pageNum or pageNum < 1 then pageNum = 1 end

    MainFrame.titleFS:SetText(title)
    MainFrame.pageFS:SetText("第 " .. pageNum .. " 页")
    MainFrame.bodyFS:SetText(text)

    MainFrame.bodyFS:ClearAllPoints()
    MainFrame.bodyFS:SetPoint("TOPLEFT", MainFrame.scroll.content, "TOPLEFT", 2, -6)
    MainFrame.scroll.content:SetHeight(TextHeight(MainFrame.bodyFS, 14) + 18)
    MainFrame.scroll:SetVerticalScroll(0)

    local hasPrevApi = ItemTextHasPrevPage and IsTrue(ItemTextHasPrevPage()) or false
    local hasNextApi = ItemTextHasNextPage and IsTrue(ItemTextHasNextPage()) or false
    local canPrev = (pageNum and pageNum > 1) or hasPrevApi
    MainFrame.prevBtn:SetDisabled(not canPrev)
    MainFrame.nextBtn:SetDisabled(not hasNextApi)
end

local function QueueRefresh(delay, count)
    if not MainFrame then return end
    MainFrame._refreshDelay = delay or 0.05
    MainFrame._refreshCount = count or 1
end

local function CloseBookFrame()
    if MainFrame and MainFrame:IsVisible() then
        MainFrame:Hide()
    end
    if CloseItemText then
        pcall(CloseItemText)
    elseif ItemTextFrame and ItemTextFrame.Hide then
        pcall(ItemTextFrame.Hide, ItemTextFrame)
    end
end

--------------------------------------------------------------------------------
-- Initialize
--------------------------------------------------------------------------------
function BUI:Initialize()
    if MainFrame then return end

    MainFrame = CreateFrame("Frame", "SFramesBookFrame", UIParent)
    MainFrame:SetWidth(FRAME_W)
    MainFrame:SetHeight(FRAME_H)
    MainFrame:SetPoint("LEFT", UIParent, "LEFT", 64, 0)
    MainFrame:SetFrameStrata("HIGH")
    MainFrame:SetToplevel(true)
    MainFrame:EnableMouse(true)
    MainFrame:SetMovable(true)
    MainFrame:RegisterForDrag("LeftButton")
    MainFrame:SetScript("OnDragStart", function() this:StartMoving() end)
    MainFrame:SetScript("OnDragStop", function() this:StopMovingOrSizing() end)
    SetRoundBackdrop(MainFrame)
    CreateShadow(MainFrame)

    local header = CreateFrame("Frame", nil, MainFrame)
    header:SetPoint("TOPLEFT", MainFrame, "TOPLEFT", 0, 0)
    header:SetPoint("TOPRIGHT", MainFrame, "TOPRIGHT", 0, 0)
    header:SetHeight(HEADER_H)

    local titleFS = header:CreateFontString(nil, "OVERLAY")
    titleFS:SetFont(GetFont(), 14, "OUTLINE")
    titleFS:SetPoint("LEFT", header, "LEFT", SIDE_PAD, 0)
    titleFS:SetPoint("RIGHT", header, "RIGHT", -96, 0)
    titleFS:SetJustifyH("LEFT")
    titleFS:SetTextColor(T.gold[1], T.gold[2], T.gold[3])
    MainFrame.titleFS = titleFS

    local pageFS = header:CreateFontString(nil, "OVERLAY")
    pageFS:SetFont(GetFont(), 11, "OUTLINE")
    pageFS:SetPoint("RIGHT", header, "RIGHT", -30, 0)
    pageFS:SetJustifyH("RIGHT")
    pageFS:SetTextColor(T.dimText[1], T.dimText[2], T.dimText[3])
    MainFrame.pageFS = pageFS

    local closeBtn = CreateFrame("Button", nil, MainFrame, "UIPanelCloseButton")
    closeBtn:SetPoint("TOPRIGHT", MainFrame, "TOPRIGHT", 2, 2)
    closeBtn:SetWidth(24); closeBtn:SetHeight(24)

    local headerSep = MainFrame:CreateTexture(nil, "ARTWORK")
    headerSep:SetTexture("Interface\\Buttons\\WHITE8X8")
    headerSep:SetHeight(1)
    headerSep:SetPoint("TOPLEFT", MainFrame, "TOPLEFT", 6, -HEADER_H)
    headerSep:SetPoint("TOPRIGHT", MainFrame, "TOPRIGHT", -6, -HEADER_H)
    headerSep:SetVertexColor(T.divider[1], T.divider[2], T.divider[3], T.divider[4])

    local contentArea = CreateFrame("Frame", nil, MainFrame)
    contentArea:SetPoint("TOPLEFT", MainFrame, "TOPLEFT", SIDE_PAD, -(HEADER_H + 4))
    contentArea:SetPoint("BOTTOMRIGHT", MainFrame, "BOTTOMRIGHT", -SIDE_PAD, BOTTOM_H + 4)
    MainFrame.contentArea = contentArea

    local scroll = CreateScrollArea(contentArea, "SFramesBookScroll")
    scroll:SetPoint("TOPLEFT", contentArea, "TOPLEFT", 0, 0)
    scroll:SetPoint("BOTTOMRIGHT", contentArea, "BOTTOMRIGHT", 0, 0)
    MainFrame.scroll = scroll

    local bodyFS = scroll.content:CreateFontString(nil, "OVERLAY")
    bodyFS:SetFont(GetFont(), BODY_FONT_SIZE)
    if bodyFS.SetSpacing then
        bodyFS:SetSpacing(BODY_LINE_SPACING)
    end
    bodyFS:SetWidth(CONTENT_W - 4)
    bodyFS:SetJustifyH("LEFT")
    bodyFS:SetTextColor(T.bodyText[1], T.bodyText[2], T.bodyText[3])
    MainFrame.bodyFS = bodyFS

    local bottomSep = MainFrame:CreateTexture(nil, "ARTWORK")
    bottomSep:SetTexture("Interface\\Buttons\\WHITE8X8")
    bottomSep:SetHeight(1)
    bottomSep:SetPoint("BOTTOMLEFT", MainFrame, "BOTTOMLEFT", 6, BOTTOM_H)
    bottomSep:SetPoint("BOTTOMRIGHT", MainFrame, "BOTTOMRIGHT", -6, BOTTOM_H)
    bottomSep:SetVertexColor(T.divider[1], T.divider[2], T.divider[3], T.divider[4])

    MainFrame.prevBtn = CreateActionBtn(MainFrame, "上一页", 90)
    MainFrame.prevBtn:SetPoint("BOTTOMLEFT", MainFrame, "BOTTOMLEFT", SIDE_PAD, 8)
    MainFrame.prevBtn:SetScript("OnClick", function()
        if this.disabled then return end
        if ItemTextPrevPage then
            ItemTextPrevPage()
            QueueRefresh(0.05, 5)
        end
    end)

    MainFrame.closeBtn = CreateActionBtn(MainFrame, "关闭", 90)
    MainFrame.closeBtn:SetPoint("BOTTOM", MainFrame, "BOTTOM", 0, 8)
    MainFrame.closeBtn:SetScript("OnClick", function()
        CloseBookFrame()
    end)

    MainFrame.nextBtn = CreateActionBtn(MainFrame, "下一页", 90)
    MainFrame.nextBtn:SetPoint("BOTTOMRIGHT", MainFrame, "BOTTOMRIGHT", -SIDE_PAD, 8)
    MainFrame.nextBtn:SetScript("OnClick", function()
        if this.disabled then return end
        if ItemTextNextPage then
            ItemTextNextPage()
            QueueRefresh(0.05, 5)
        end
    end)

    MainFrame:SetScript("OnHide", function()
        if ItemTextFrame and ItemTextFrame:IsVisible() then
            pcall(ItemTextFrame.Hide, ItemTextFrame)
        end
    end)
    MainFrame:SetScript("OnUpdate", function()
        if not this._refreshCount or this._refreshCount <= 0 then return end
        this._refreshDelay = (this._refreshDelay or 0) - (arg1 or 0)
        if this._refreshDelay > 0 then return end
        UpdateBookContent()
        this._refreshCount = this._refreshCount - 1
        if this._refreshCount > 0 then
            this._refreshDelay = 0.08
        end
    end)

    MainFrame:RegisterEvent("ITEM_TEXT_BEGIN")
    MainFrame:RegisterEvent("ITEM_TEXT_READY")
    MainFrame:RegisterEvent("ITEM_TEXT_CLOSED")
    MainFrame:SetScript("OnEvent", function()
        if event == "ITEM_TEXT_BEGIN" then
            HideBlizzardItemText()
            UpdateBookContent()
            QueueRefresh(0.05, 5)
            MainFrame:Show()
        elseif event == "ITEM_TEXT_READY" then
            HideBlizzardItemText()
            UpdateBookContent()
            QueueRefresh(0.05, 5)
            if not MainFrame:IsVisible() then
                MainFrame:Show()
            end
        elseif event == "ITEM_TEXT_CLOSED" then
            MainFrame._refreshCount = 0
            MainFrame:Hide()
        end
    end)

    MainFrame:Hide()
    tinsert(UISpecialFrames, "SFramesBookFrame")
end

--------------------------------------------------------------------------------
-- Bootstrap
--------------------------------------------------------------------------------
local bootstrap = CreateFrame("Frame")
bootstrap:RegisterEvent("PLAYER_LOGIN")
bootstrap:SetScript("OnEvent", function()
    if event == "PLAYER_LOGIN" then
        BUI:Initialize()
    end
end)
