-- TOG Tools — Gathering Log sub-tab (UI)
-- Renders inside the Logs outer tab's nested AceGUI TabGroup. Layout:
--   Filter row:   Date range ▾   (Character / Type / Zone / Source filtering is
--                 in the column-header menus now — no dropdown row)
--   Data table:   Time · Character · Type · Qty · Item · Source · Zone
--
-- Date-range state lives on the module table so it survives Draw rebuilds
-- triggered by capture refresh, but resets on /reload. Everything below the
-- date range is filtered + sorted via the RowList column-header menus.

local _, addon = ...
local AceGUI = LibStub("AceGUI-3.0")

local GatheringLog = addon.logCategories["gathering"]

GatheringLog._filterRange        = GatheringLog._filterRange        or addon.DateRangePicker.DEFAULT_KEY
GatheringLog._filterCustomFrom   = GatheringLog._filterCustomFrom   or nil
GatheringLog._filterCustomTo     = GatheringLog._filterCustomTo     or nil
GatheringLog._filterCalendarOpen = GatheringLog._filterCalendarOpen or false
GatheringLog._search             = GatheringLog._search             or ""

-- ---------------------------------------------------------------------------
-- Cell formatters
-- ---------------------------------------------------------------------------
-- Absolute MM/DD/YY HH:MM:SS stamp (24-hour). Gathering bursts many nodes
-- in a session, so the exact second is more useful here than a relative
-- "Nm ago". date() formats `ts` in local time, matching the addon's other
-- timestamps (Debug output, chat).
local function fmtTime(ts)
    if not ts or ts <= 0 then return "—" end
    return date("%m/%d/%y %H:%M:%S", ts)
end

local function fmtItem(e)
    return e.link or e.name or ("item:" .. tostring(e.itemID))
end

-- ---------------------------------------------------------------------------
-- Draw
-- ---------------------------------------------------------------------------
function GatheringLog:Draw(container)
    container:SetLayout("Flow")

    local function rebuild()
        if addon.MainWindow and addon.MainWindow.Refresh then
            addon.MainWindow:Refresh()
        end
    end

    local rl   -- data table; forward-declared so the search box can reach it

    -- ---- Filter row -----------------------------------------------------
    local filterRow = AceGUI:Create("SimpleGroup")
    filterRow:SetFullWidth(true)
    filterRow:SetLayout("Flow")
    container:AddChild(filterRow)

    filterRow:AddChild(addon.DateRangePicker:Create({
        default  = self._filterRange,
        onChange = function(key)
            local enteringCustom = (key == "custom" and self._filterRange ~= "custom")
            self._filterRange = key
            if enteringCustom then self._filterCalendarOpen = true end
            rebuild()
        end,
    }))

    -- Free-text search across all columns. Live (no button); filters the table
    -- in place via the RowList without a full re-Draw, so typing keeps focus.
    local search = AceGUI:Create("EditBox")
    search:SetWidth(240)
    search:DisableButton(true)
    search:SetText(self._search or "")
    search:SetCallback("OnTextChanged", function(_, _, text)
        self._search = text
        if rl then rl:SetSearch(text) end
    end)
    addon.UI.StyleSearchBox(search, true)   -- magnifying-glass icon instead of a "Search" label
    filterRow:AddChild(search)

    if self._filterRange == "custom" and self._filterCustomFrom
       and not self._filterCalendarOpen then
        local pickBtn = AceGUI:Create("Button")
        pickBtn:SetWidth(140)
        pickBtn:SetText("Pick range...")
        pickBtn:SetCallback("OnClick", function()
            self._filterCalendarOpen = true
            rebuild()
        end)
        filterRow:AddChild(pickBtn)
    end

    if self._filterRange == "custom"
       and (not self._filterCustomFrom or self._filterCalendarOpen) then
        local unbounded = GatheringLog:GetEntries(nil, nil, nil, nil, nil)
        local timestamps = {}
        for _, e in ipairs(unbounded) do tinsert(timestamps, e.ts) end
        container:AddChild(addon.DateRangePicker:CreateCalendar({
            defaultFrom = self._filterCustomFrom,
            defaultTo   = self._filterCustomTo,
            timestamps  = timestamps,
            onApply     = function(fromTs, toTs)
                self._filterCustomFrom   = fromTs
                self._filterCustomTo     = toTs
                self._filterCalendarOpen = false
                rebuild()
            end,
        }))
        if not self._filterCustomFrom then return end
    end

    -- ---- Resolve filtered data -----------------------------------------
    local fromTs, toTs = addon.DateRangePicker:Resolve(
        self._filterRange, self._filterCustomFrom, self._filterCustomTo)
    local entries = GatheringLog:GetEntries(nil, nil, nil, fromTs, toTs)

    -- Spacer between the filter row and the data table.
    local sp = AceGUI:Create("Label")
    sp:SetFullWidth(true); sp:SetText(" ")
    container:AddChild(sp)

    -- ---- Data table -----------------------------------------------------
    local body = AceGUI:Create("SimpleGroup")
    body:SetFullWidth(true)
    body:SetFullHeight(true)
    body:SetLayout("List")
    container:AddChild(body)

    if #entries == 0 then
        local empty = AceGUI:Create("Label")
        empty:SetFullWidth(true)
        empty:SetText("|cff888888No gathering entries in this date range.|r\n\nThe Gathering Log fills in as you mine, herb, skin, and fish. Widen the |cffffd700Date range|r above, or check a column header's filter — a |cffffd700*|r on a header means it's narrowing the list.")
        body:AddChild(empty)
        return
    end

    rl = addon.RowList:New(body.content, {
        rowHeight = 16,
        columns = {
            { key = "ts", header = "Time", autoFit = true, minWidth = 50, justify = "LEFT",
              sortKey = "ts", sortDescDefault = true, sortType = "date",
              headerTip = "Time",
              headerTipDesc = "When the item was gathered, as a MM/DD/YY HH:MM:SS timestamp (24-hour, local time). Click to sort by time.",
              format = function(e) return fmtTime(e.ts) end },

            { key = "player", header = "Character", autoFit = true, minWidth = 60, justify = "LEFT",
              headerTip = "Character",
              headerTipDesc = "The alt that gathered this item. The Gathering Log is account-wide; click this column header to filter by character, or use the search box.",
              format = function(e) return e.player or "?" end },

            { key = "prof", header = "Type", autoFit = true, minWidth = 60, justify = "LEFT",
              filterable = true,
              headerTip = "Type",
              headerTipDesc = "Which gathering profession produced this drop — Mining, Herbalism, Skinning, or Fishing. Use the Profession filter above to narrow.",
              format = function(e) return GatheringLog.PROF_LABEL[e.prof] or e.prof or "?" end },

            { key = "count", header = "Qty", autoFit = true, minWidth = 36, justify = "RIGHT",
              sortKey = "count", sortDescDefault = true,
              headerTip = "Quantity",
              headerTipDesc = "How many of the item dropped in this pickup. Click to sort by quantity.",
              format = function(e) return tostring(e.count or 1) end },

            { key = "name", header = "Item", justify = "LEFT",
              headerTip = "Item",
              headerTipDesc = "The gathered item. This is the stretchy column — hover for the tooltip, shift-click to link it into chat. Sorts alphabetically by name.",
              format = function(e) return fmtItem(e) end },

            { key = "source", header = "Source", autoFit = true, minWidth = 90, justify = "LEFT",
              sortKey = "source", filterable = true,
              headerTip = "Source",
              headerTipDesc = "What you gathered it from — the vein / herb / node (or creature, for skinning). Captured from the object's tooltip the moment you gathered it; entries from before source tracking show \"—\". The stats panel above breaks down yield per source.",
              format = function(e) return e.source or (e.sourceID and ("#" .. e.sourceID)) or "—" end },

            { key = "zone", header = "Zone", autoFit = true, minWidth = 70, justify = "LEFT",
              filterable = true, filterGroup = function(e) return e.continent end,
              headerTip = "Zone",
              headerTipDesc = "Where the item was gathered. The header filter groups zones by continent (continent > zone) so the list stays manageable; entries from before continent tracking fall under \"Other\".",
              format = function(e) return e.zone or "—" end },
        },
    })
    rl:SetSort("ts", true)
    rl:SetData(entries)
    if self._search and self._search ~= "" then rl:SetSearch(self._search) end

    body:SetCallback("OnRelease", function() rl:Detach() end)
end
