local ADDON_NAME, RPAL = ...

-- Compact RP Currency widget ------------------------------------------------
-- This surface is deliberately not a modal. It behaves like a normal movable
-- HUD widget and keeps the complete player-transfer protocol in Currency.lua
-- intact for compatibility while making everyday bookkeeping immediate.

local WHITE="Interface\\Buttons\\WHITE8X8"
local FONT=STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF"
local COIN_TEXTURES={
    "Interface\\MoneyFrame\\UI-GoldIcon",
    "Interface\\MoneyFrame\\UI-SilverIcon",
    "Interface\\MoneyFrame\\UI-CopperIcon",
}
local UNIT_VALUES={10000,100,1}
local UNIT_NAMES={"gold","silver","copper"}

local widget
local activeStore="pouch"
local activeEditBox
local offerFrames={}
local transferStatus="Ready."

local function P()
    if RPAL.GetCurrentThemePalette then
        local palette=RPAL.GetCurrentThemePalette()
        if palette then return palette end
    end
    return {
        main={0.045,0.032,0.018,0.99},panel={0.105,0.065,0.035,0.98},
        panel2={0.16,0.105,0.055,0.98},border={0.42,0.28,0.12,1},
        button={0.105,0.070,0.040,1},buttonHover={0.17,0.115,0.060,1},
        accent={0.66,0.45,0.16,1},gold={0.86,0.63,0.28,1},
        pale={0.88,0.82,0.68,1},muted={0.57,0.50,0.40,1},
    }
end

local function FS(parent,text,size,color)
    local f=parent:CreateFontString(nil,"OVERLAY")
    f:SetFont(FONT,RPAL.GetScaledFontSize and RPAL.GetScaledFontSize(size or 10) or (size or 10),"")
    color=color or P().pale
    f:SetTextColor(color[1],color[2],color[3],color[4] or 1)
    f:SetText(tostring(text or ""))
    return f
end

local function Surface(frame,bg,border)
    bg=bg or P().panel
    border=border or P().border
    frame:SetBackdrop({
        bgFile="Interface\\Tooltips\\UI-Tooltip-Background",
        edgeFile="Interface\\Tooltips\\UI-Tooltip-Border",
        tile=false,tileSize=16,edgeSize=12,
        insets={left=3,right=3,top=3,bottom=3},
    })
    frame:SetBackdropColor(bg[1],bg[2],bg[3],bg[4] or 1)
    frame:SetBackdropBorderColor(border[1],border[2],border[3],border[4] or 1)
end

local function FlatBackdrop(frame,bg,border)
    bg=bg or P().button
    border=border or P().border
    frame:SetBackdrop({bgFile=WHITE,edgeFile=WHITE,edgeSize=1,insets={left=1,right=1,top=1,bottom=1}})
    frame:SetBackdropColor(bg[1],bg[2],bg[3],bg[4] or 1)
    frame:SetBackdropBorderColor(border[1],border[2],border[3],border[4] or 1)
end

local function StyleButton(button,selected,hovered)
    if not button then return end
    local p=P()
    button._selected=selected and true or false
    local bg=selected and p.accent or (hovered and p.buttonHover or p.button)
    local edge=(selected or hovered) and p.gold or p.border
    FlatBackdrop(button,bg,edge)
    if button.label then
        local color=selected and p.pale or (hovered and p.gold or p.pale)
        button.label:SetTextColor(color[1],color[2],color[3],color[4] or 1)
    end
end

local function SmallButton(parent,label,w,h)
    local b=CreateFrame("Button",nil,parent,"BackdropTemplate")
    b:SetSize(w or 28,h or 24)
    b.label=FS(b,label,8.2,P().pale)
    b.label:SetPoint("CENTER",0,0)
    b:SetScript("OnEnter",function(self)StyleButton(self,self._selected,true)end)
    b:SetScript("OnLeave",function(self)StyleButton(self,self._selected,false)end)
    StyleButton(b,false,false)
    return b
end

local function WidgetSettings()
    local settings=RPAL.GetSettings and RPAL.GetSettings() or nil
    if type(settings)~="table" then
        if type(RPAL_DB)~="table" then RPAL_DB={} end
        RPAL_DB.settings=type(RPAL_DB.settings)=="table" and RPAL_DB.settings or {}
        settings=RPAL_DB.settings
    end
    settings.currencyWidget=type(settings.currencyWidget)=="table" and settings.currencyWidget or {}
    local s=settings.currencyWidget
    if type(s.point)~="string" then s.point="TOPLEFT" end
    if type(s.relativePoint)~="string" then s.relativePoint="TOPLEFT" end
    if s.x==nil then s.x=245 end
    if s.y==nil then s.y=-180 end
    if s.store~="bank" and s.store~="pouch" then s.store="pouch" end
    return s
end

local function PositionWidget(frame)
    if not frame then return end
    local s=WidgetSettings()
    frame:ClearAllPoints()
    local ok=pcall(frame.SetPoint,frame,s.point,UIParent,s.relativePoint,tonumber(s.x) or 245,tonumber(s.y) or -180)
    if not ok then
        s.point,s.relativePoint,s.x,s.y="TOPLEFT","TOPLEFT",245,-180
        frame:SetPoint("TOPLEFT",UIParent,"TOPLEFT",245,-180)
    end
end

local function SaveWidgetPosition(frame)
    if not frame then return end
    local point,_,relativePoint,x,y=frame:GetPoint(1)
    local s=WidgetSettings()
    s.point=point or "TOPLEFT"
    s.relativePoint=relativePoint or "TOPLEFT"
    s.x=math.floor((tonumber(x) or 0)+0.5)
    s.y=math.floor((tonumber(y) or 0)+0.5)
end

local function Feedback(ok,message)
    if ok then return end
    message=tostring(message or "That currency change could not be completed.")
    if UIErrorsFrame and UIErrorsFrame.AddMessage then
        UIErrorsFrame:AddMessage(message,1,0.32,0.32,1)
    else
        print("|cffff6666ODYN Currency:|r "..message)
    end
end

local function StoreTotal(store,state)
    state=state or (RPAL.GetRPCurrencyState and RPAL.GetRPCurrencyState()) or {}
    return math.max(0,math.floor(tonumber(store=="bank" and state.bank or state.pouch) or 0))
end

local function AdjustStore(store,delta,reason)
    if delta==0 then return true end
    if store=="bank" then
        if RPAL.AdjustBank then return RPAL.AdjustBank(delta,reason) end
        return false,"Bank editing is unavailable."
    end
    if RPAL.AdjustPouch then return RPAL.AdjustPouch(delta,reason) end
    return false,"Coin Pouch editing is unavailable."
end

local function SetStoreValue(store,newTotal,reason)
    local oldTotal=StoreTotal(store)
    newTotal=math.max(0,math.floor(tonumber(newTotal) or 0))
    return AdjustStore(store,newTotal-oldTotal,reason)
end

local function ApplyTheme(frame)
    if not frame then return end
    local p=P()
    Surface(frame,p.main,p.gold)
    StyleButton(frame.pouchTab,activeStore=="pouch",false)
    StyleButton(frame.bankTab,activeStore=="bank",false)
    StyleButton(frame.closeButton,false,false)
    for _,row in ipairs(frame.rows or {}) do
        StyleButton(row.valueButton,false,false)
        StyleButton(row.minusButton,false,false)
        StyleButton(row.plusButton,false,false)
        if row.valueButton and row.valueButton.label then
            row.valueButton.label:SetTextColor(p.pale[1],p.pale[2],p.pale[3],1)
        end
        if row.editBox then
            FlatBackdrop(row.editBox,p.panel,p.gold)
            row.editBox:SetTextColor(p.pale[1],p.pale[2],p.pale[3],1)
        end
    end
end

local function Refresh(frame)
    frame=frame or widget
    if not frame then return end
    local state=RPAL.GetRPCurrencyState and RPAL.GetRPCurrencyState() or {pouch=0,bank=0}
    local total=StoreTotal(activeStore,state)
    local g,s,c=0,0,0
    if RPAL.CurrencyToParts then g,s,c=RPAL.CurrencyToParts(total) end
    local parts={g or 0,s or 0,c or 0}
    for index,row in ipairs(frame.rows or {}) do
        row.valueButton.label:SetText(tostring(parts[index] or 0))
    end
    ApplyTheme(frame)
end

local function EndActiveEdit()
    if activeEditBox and activeEditBox.HasFocus and activeEditBox:HasFocus() then
        activeEditBox:ClearFocus()
    end
end

local function SelectStore(store)
    if store~="bank" then store="pouch" end
    EndActiveEdit()
    activeStore=store
    WidgetSettings().store=store
    Refresh(widget)
end

local function CommitEdit(row)
    if not row or row._committing then return end
    row._committing=true
    local edit=row.editBox
    local cancelled=edit._cancelEdit
    edit._cancelEdit=nil

    if not cancelled then
        local requested=math.max(0,math.floor(tonumber(edit:GetText()) or 0))
        if row.index>1 then requested=math.min(99,requested) end
        local store=row.editStore or activeStore
        local current=StoreTotal(store)
        local g,s,c=0,0,0
        if RPAL.CurrencyToParts then g,s,c=RPAL.CurrencyToParts(current) end
        local parts={g or 0,s or 0,c or 0}
        parts[row.index]=requested
        local nextTotal=RPAL.CurrencyFromParts and RPAL.CurrencyFromParts(parts[1],parts[2],parts[3]) or current
        local ok,result=SetStoreValue(store,nextTotal,"widget_"..UNIT_NAMES[row.index].."_edit")
        Feedback(ok,result)
    end

    edit:Hide()
    row.valueButton:Show()
    row.editStore=nil
    if activeEditBox==edit then activeEditBox=nil end
    row._committing=false
    Refresh(widget)
end

local function BeginEdit(row)
    if not row then return end
    EndActiveEdit()
    local total=StoreTotal(activeStore)
    local g,s,c=0,0,0
    if RPAL.CurrencyToParts then g,s,c=RPAL.CurrencyToParts(total) end
    local parts={g or 0,s or 0,c or 0}
    row.editStore=activeStore
    row.editBox:SetText(tostring(parts[row.index] or 0))
    row.valueButton:Hide()
    row.editBox:Show()
    activeEditBox=row.editBox
    row.editBox:SetFocus()
    if row.editBox.HighlightText then row.editBox:HighlightText() end
end

local function ChangeOne(row,direction)
    if not row then return end
    EndActiveEdit()
    local delta=(direction<0 and -1 or 1)*(UNIT_VALUES[row.index] or 1)
    local ok,result=AdjustStore(activeStore,delta,"widget_"..UNIT_NAMES[row.index]..(direction<0 and "_minus" or "_plus"))
    Feedback(ok,result)
    Refresh(widget)
end

local function BuildRow(parent,index,x)
    local valueWidth=(index==1) and 52 or 38
    local rowWidth=valueWidth+68
    local row=CreateFrame("Frame",nil,parent)
    row:SetSize(rowWidth,24)
    row:SetPoint("TOPLEFT",x,-36)
    row.index=index

    row.valueButton=SmallButton(row,"0",valueWidth,24)
    row.valueButton:SetPoint("LEFT",0,0)
    row.valueButton.label:ClearAllPoints()
    row.valueButton.label:SetPoint("RIGHT",-6,0)
    row.valueButton.label:SetJustifyH("RIGHT")

    row.icon=row:CreateTexture(nil,"ARTWORK")
    row.icon:SetTexture(COIN_TEXTURES[index])
    row.icon:SetSize(16,16)
    row.icon:SetPoint("LEFT",row.valueButton,"RIGHT",4,0)
    row.icon:SetTexCoord(0,1,0,1)

    row.minusButton=SmallButton(row,"-",20,22)
    row.minusButton:SetPoint("LEFT",row.icon,"RIGHT",5,0)
    row.plusButton=SmallButton(row,"+",20,22)
    row.plusButton:SetPoint("LEFT",row.minusButton,"RIGHT",3,0)

    row.editBox=CreateFrame("EditBox",nil,row,"BackdropTemplate")
    row.editBox:SetSize(valueWidth,24)
    row.editBox:SetPoint("LEFT",0,0)
    row.editBox:SetFont(FONT,RPAL.GetScaledFontSize and RPAL.GetScaledFontSize(11) or 11,"")
    row.editBox:SetTextInsets(5,5,0,0)
    row.editBox:SetJustifyH("RIGHT")
    row.editBox:SetNumeric(true)
    row.editBox:SetMaxLetters(9)
    row.editBox:SetAutoFocus(false)
    row.editBox:Hide()

    row.valueButton:SetScript("OnClick",function()BeginEdit(row)end)
    row.minusButton:SetScript("OnClick",function()ChangeOne(row,-1)end)
    row.plusButton:SetScript("OnClick",function()ChangeOne(row,1)end)
    row.editBox:SetScript("OnEnterPressed",function(self)self:ClearFocus()end)
    row.editBox:SetScript("OnEscapePressed",function(self)self._cancelEdit=true;self:ClearFocus()end)
    row.editBox:SetScript("OnEditFocusLost",function()CommitEdit(row)end)
    return row
end

local function BuildWidget()
    if widget then return widget end
    local f=CreateFrame("Frame","RPAL_CurrencyWidget",UIParent,"BackdropTemplate")
    widget=f
    RPAL._currencyWidget=f
    f:SetSize(374,66)
    f:SetFrameStrata("DIALOG")
    f:SetFrameLevel(240)
    f:SetClampedToScreen(true)
    f:SetMovable(true)
    f:EnableMouse(true)
    f:RegisterForDrag("LeftButton")
    PositionWidget(f)

    -- Keep a narrow empty strip on the left as a reliable grab area.
    -- The rest of the widget is intentionally dense and button-first.
    f.dragHandle=CreateFrame("Frame",nil,f)
    f.dragHandle:SetPoint("TOPLEFT",4,-4)
    f.dragHandle:SetPoint("BOTTOMLEFT",4,4)
    f.dragHandle:SetWidth(12)
    f.dragHandle:EnableMouse(true)
    f.dragHandle:RegisterForDrag("LeftButton")

    f.closeButton=SmallButton(f,"X",18,18)
    f.closeButton:SetPoint("TOPRIGHT",-6,-7)
    f.closeButton:SetScript("OnClick",function()f:Hide()end)

    f.pouchTab=SmallButton(f,"POUCH",62,21)
    f.pouchTab:SetPoint("TOPLEFT",20,-7)
    f.bankTab=SmallButton(f,"BANK",62,21)
    f.bankTab:SetPoint("LEFT",f.pouchTab,"RIGHT",4,0)
    f.pouchTab:SetScript("OnClick",function()SelectStore("pouch")end)
    f.bankTab:SetScript("OnClick",function()SelectStore("bank")end)

    -- Gold / Silver / Copper sit on one line instead of three stacked rows.
    f.rows={
        BuildRow(f,1,20),
        BuildRow(f,2,144),
        BuildRow(f,3,254),
    }

    local function StartWidgetDrag()
        EndActiveEdit()
        f._currencyDragging=true
        f:StartMoving()
        if RPAL.HideCursorTooltip then RPAL.HideCursorTooltip() end
    end
    local function StopWidgetDrag()
        if not f._currencyDragging then return end
        f._currencyDragging=nil
        f:StopMovingOrSizing()
        SaveWidgetPosition(f)
    end

    f:SetScript("OnDragStart",StartWidgetDrag)
    f:SetScript("OnDragStop",StopWidgetDrag)
    f.dragHandle:SetScript("OnDragStart",StartWidgetDrag)
    f.dragHandle:SetScript("OnDragStop",StopWidgetDrag)
    f:SetScript("OnHide",function(self)
        EndActiveEdit()
        if self._currencyDragging then
            self._currencyDragging=nil
            self:StopMovingOrSizing()
            SaveWidgetPosition(self)
        end
        if RPAL.HideCursorTooltip then RPAL.HideCursorTooltip() end
    end)
    f:SetScript("OnEnter",function()
        if RPAL.ShowCursorTooltip then RPAL.ShowCursorTooltip({
            eyebrow="RP CURRENCY",
            title=activeStore=="bank" and "Bank" or "Coin Pouch",
            body="Use Pouch or Bank, then change Gold, Silver or Copper directly.",
            sectionTitle="CONTROLS",
            section="- / + changes exactly one coin. Click the number to type an exact value.",
            detailTitle="MOVE",
            detail="Drag the empty strip on the left edge to reposition the widget.",
            footer=transferStatus~="Ready." and transferStatus or "",
            accent=P().gold,width=360,
        }) end
    end)
    f:SetScript("OnLeave",function()
        if not f._currencyDragging and RPAL.HideCursorTooltip then RPAL.HideCursorTooltip() end
    end)

    if RPAL.RegisterEscapeFrame then RPAL.RegisterEscapeFrame(f) end
    activeStore=WidgetSettings().store
    Refresh(f)
    f:Hide()
    return f
end

local function LayoutOfferFrames()
    local visibleIndex=0
    for _,frame in ipairs(offerFrames) do
        if frame and frame:IsShown() then
            visibleIndex=visibleIndex+1
            frame:ClearAllPoints()
            if widget and widget:IsShown() then
                frame:SetPoint("TOPLEFT",widget,"TOPRIGHT",6,-((visibleIndex-1)*98))
            else
                frame:SetPoint("TOPLEFT",UIParent,"TOPLEFT",245,-180-((visibleIndex-1)*98))
            end
        end
    end
end

local function RemoveOfferFrame(frame)
    for index=#offerFrames,1,-1 do
        if offerFrames[index]==frame then table.remove(offerFrames,index) end
    end
    LayoutOfferFrames()
end

function RPAL.OpenCurrencyUI()
    local f=BuildWidget()
    activeStore=WidgetSettings().store
    if not f:IsShown() then
        PositionWidget(f)
        f:Show()
    end
    Refresh(f)
    return f
end

function RPAL.CloseCurrencyUI()
    if widget then widget:Hide() end
end

function RPAL.ResetCurrencyWidgetPosition()
    local s=WidgetSettings()
    s.point,s.relativePoint,s.x,s.y="TOPLEFT","TOPLEFT",245,-180
    if widget then PositionWidget(widget) end
end

function RPAL.UpdateCurrencyWidget()
    if not widget then return end
    if not activeEditBox then activeStore=WidgetSettings().store end
    Refresh(widget)
end

function RPAL.ShowCurrencyOfferPrompt(sender,id,amount)
    local frame=CreateFrame("Frame",nil,UIParent,"BackdropTemplate")
    frame:SetSize(250,92)
    frame:SetFrameStrata("DIALOG")
    frame:SetFrameLevel(320+(#offerFrames*10))
    frame:SetClampedToScreen(true)
    frame:EnableMouse(true)
    Surface(frame,P().main,P().gold)

    local title=FS(frame,tostring(sender or "Unknown player").." offers:",8.5,P().pale)
    title:SetPoint("TOPLEFT",10,-9)
    title:SetPoint("RIGHT",-10,0)
    title:SetWordWrap(false)

    local money=FS(frame,RPAL.FormatRPCurrency and RPAL.FormatRPCurrency(amount) or tostring(amount),14,P().gold)
    money:SetPoint("TOP",0,-31)

    local decline=SmallButton(frame,"DECLINE",94,24)
    decline:SetPoint("BOTTOMLEFT",10,8)
    local accept=SmallButton(frame,"ACCEPT",94,24)
    accept:SetPoint("BOTTOMRIGHT",-10,8)
    accept._selected=true
    StyleButton(accept,true,false)

    decline:SetScript("OnClick",function()
        if RPAL.DeclineCurrencyOffer then RPAL.DeclineCurrencyOffer(id,"declined") end
        frame:Hide()
    end)
    accept:SetScript("OnClick",function()
        local ok,result=false,"Currency offers are unavailable."
        if RPAL.AcceptCurrencyOffer then ok,result=RPAL.AcceptCurrencyOffer(id) end
        Feedback(ok,result)
        if ok then frame:Hide() end
    end)
    frame:HookScript("OnHide",function(self)RemoveOfferFrame(self)end)

    offerFrames[#offerFrames+1]=frame
    LayoutOfferFrames()
    if C_Timer and C_Timer.After then
        C_Timer.After(61,function()if frame and frame:IsShown() then frame:Hide() end end)
    end
    return nil,frame
end

RPAL.OnRPCurrencyChanged=function()
    Refresh(widget)
end

RPAL.OnCurrencyTransferStatus=function(text,kind)
    transferStatus=tostring(text or "Ready.")
    if kind=="failed" or kind=="warning" then Feedback(false,transferStatus) end
    Refresh(widget)
end
