local DR = select(2, ...)
local constants = DR.Modules["Core.Constants"]

--- Deferred trade tracker: won items waiting to be traded to their winners.
local DeferredTradeFrame = {
  frame = nil,
}
LibStub("AceEvent-3.0"):Embed(DeferredTradeFrame)

local FILTER_ALL = "all"

local FILTER_ORDER = {
  FILTER_ALL,
  constants.DEFERRED_TRADE.STATUS.TO_TRADE,
  constants.DEFERRED_TRADE.STATUS.TRADED,
  constants.DEFERRED_TRADE.STATUS.TIMEOUT,
  constants.DEFERRED_TRADE.STATUS.CANCELLED,
}

local FILTER_LABELS = {
  [FILTER_ALL] = "All",
  [constants.DEFERRED_TRADE.STATUS.TO_TRADE] = "To Trade",
  [constants.DEFERRED_TRADE.STATUS.TRADED] = "Traded",
  [constants.DEFERRED_TRADE.STATUS.TIMEOUT] = "Timeout",
  [constants.DEFERRED_TRADE.STATUS.CANCELLED] = "Cancelled",
}

local function Kit()
  return DR:Require("UI.Kit")
end

local function getDisplay(guid)
  return DR:Require("Services.Identity"):GetDisplayByGuid(guid) or guid or "unknown"
end

local function statusText(status)
  return FILTER_LABELS[status] or tostring(status)
end

local function shortText(value, maxLen)
  local text = tostring(value or "")
  if #text <= maxLen then
    return text
  end
  return string.sub(text, 1, maxLen - 3) .. "..."
end

local function formatTs(ts)
  if not ts then
    return "-"
  end
  if date then
    return date("%m-%d %H:%M", ts)
  end
  return tostring(ts)
end

local function resolveSelectedId(frame)
  local text = frame.idInput and frame.idInput:GetText() or ""
  if text and text ~= "" then
    return text
  end

  local service = DR:Require("Services.DeferredTrade")
  local status = frame.currentFilter
  local first = nil
  if status and status ~= FILTER_ALL then
    first = service:GetFirstByStatus(status)
  else
    first = service:GetFirstByStatus(constants.DEFERRED_TRADE.STATUS.TO_TRADE)
  end
  return first and first.id or nil
end

local function nextFilter(current)
  local idx = 1
  for i, key in ipairs(FILTER_ORDER) do
    if key == current then
      idx = i
      break
    end
  end
  idx = idx + 1
  if idx > #FILTER_ORDER then
    idx = 1
  end
  return FILTER_ORDER[idx]
end

local function getRowsForFilter(service, filterKey)
  if not filterKey or filterKey == FILTER_ALL then
    return service:GetOrdered()
  end
  return service:GetByStatus(filterKey)
end

local function render(frame)
  if not frame or not frame.listText then
    return
  end

  local service = DR:Require("Services.DeferredTrade")
  local allRows = service:GetOrdered()
  local filterKey = frame.currentFilter or FILTER_ALL
  local rows = getRowsForFilter(service, filterKey)
  local counts = service:GetStatusCounts()
  if frame.filterBtn then
    frame.filterBtn.label:SetText("Filter: " .. (FILTER_LABELS[filterKey] or "All"))
  end

  if #allRows == 0 then
    frame.listText:SetText("No deferred trades")
    return
  end

  if frame.idInput and (frame.idInput:GetText() or "") == "" then
    local first = nil
    if filterKey ~= FILTER_ALL then
      first = service:GetFirstByStatus(filterKey)
    end
    if not first then
      first = service:GetFirstByStatus(constants.DEFERRED_TRADE.STATUS.TO_TRADE)
    end
    if first then
      frame.idInput:SetText(first.id)
    end
  end

  local out = {
    string.format(
      "Shown: %d/%d  |cff9a9baaTo Trade %d - Traded %d - Timeout %d - Cancelled %d|r",
      #rows,
      #allRows,
      counts[constants.DEFERRED_TRADE.STATUS.TO_TRADE] or 0,
      counts[constants.DEFERRED_TRADE.STATUS.TRADED] or 0,
      counts[constants.DEFERRED_TRADE.STATUS.TIMEOUT] or 0,
      counts[constants.DEFERRED_TRADE.STATUS.CANCELLED] or 0
    ),
    "|cffffb84cID | Status | Winner | Item | Updated|r",
  }

  if #rows == 0 then
    out[#out + 1] = "No entries for current filter"
    frame.listText:SetText(table.concat(out, "\n"))
    return
  end

  for i = 1, math.min(#rows, 10) do
    local row = rows[i]
    local statusCell = statusText(row.status)
    if row.reason and row.reason ~= "" then
      statusCell = statusCell .. " (" .. shortText(row.reason, 14) .. ")"
    end

    out[#out + 1] = string.format(
      "%s | %s | %s | %s | %s",
      shortText(row.id, 16),
      shortText(statusCell, 24),
      shortText(getDisplay(row.winnerGuid), 16),
      shortText(row.itemLink or "-", 30),
      formatTs(row.updatedAt or row.createdAt)
    )
  end
  frame.listText:SetText(table.concat(out, "\n"))
end

local function setStatus(frame, status)
  local id = resolveSelectedId(frame)
  if not id then
    DR:Print("No deferred trade selected")
    return
  end

  local ok, reason = DR:Require("Services.DeferredTrade"):SetStatus(id, status, "manual_ui")
  if not ok then
    DR:Print("Deferred trade update failed: " .. tostring(reason))
    return
  end

  DR:Print(string.format("Deferred trade %s => %s", id, status))
  render(frame)
end

function DeferredTradeFrame:CreateFrame()
  if self.frame then
    return self.frame
  end

  local kit = Kit()
  local C = kit.COLORS
  local frame = kit:CreateWindow("DeferredTradeFrame", "DetentionRolls - Deferred Trades", 560, 330, { defaultY = -220 })

  local idLabel = kit:CreateLabel(frame.content, "Trade ID (optional)", "small", C.textDim)
  idLabel:SetPoint("TOPLEFT", 0, 0)

  local idInput = kit:CreateEditBox(frame.content, 260, 24)
  idInput:SetPoint("TOPLEFT", idLabel, "BOTTOMLEFT", 0, -4)
  frame.idInput = idInput

  local refreshBtn = kit:CreateButton(frame.content, "Refresh", 64, 24, function()
    render(frame)
  end, { smallText = true })
  refreshBtn:SetPoint("LEFT", idInput, "RIGHT", 6, 0)

  local filterBtn = kit:CreateButton(frame.content, "Filter: All", 92, 24, function()
    frame.currentFilter = nextFilter(frame.currentFilter)
    render(frame)
  end, { smallText = true })
  filterBtn:SetPoint("LEFT", refreshBtn, "RIGHT", 6, 0)
  frame.filterBtn = filterBtn

  local sweepBtn = kit:CreateButton(frame.content, "Sweep", 58, 24, function()
    local count = DR:Require("Services.DeferredTrade"):RunTimeoutSweep()
    DR:Print(string.format("Deferred trade timeout sweep: %d updated", count or 0))
    render(frame)
  end, { smallText = true })
  sweepBtn:SetPoint("LEFT", filterBtn, "RIGHT", 6, 0)

  local tradedBtn = kit:CreateButton(frame.content, "Traded", 70, 22, function()
    setStatus(frame, constants.DEFERRED_TRADE.STATUS.TRADED)
  end, { smallText = true })
  tradedBtn:SetPoint("TOPLEFT", idInput, "BOTTOMLEFT", 0, -8)

  local timeoutBtn = kit:CreateButton(frame.content, "Timeout", 70, 22, function()
    setStatus(frame, constants.DEFERRED_TRADE.STATUS.TIMEOUT)
  end, { smallText = true })
  timeoutBtn:SetPoint("LEFT", tradedBtn, "RIGHT", 6, 0)

  local cancelBtn = kit:CreateButton(frame.content, "Cancel", 70, 22, function()
    setStatus(frame, constants.DEFERRED_TRADE.STATUS.CANCELLED)
  end, { smallText = true, danger = true })
  cancelBtn:SetPoint("LEFT", timeoutBtn, "RIGHT", 6, 0)

  local resetBtn = kit:CreateButton(frame.content, "To Trade", 70, 22, function()
    setStatus(frame, constants.DEFERRED_TRADE.STATUS.TO_TRADE)
  end, { smallText = true })
  resetBtn:SetPoint("LEFT", cancelBtn, "RIGHT", 6, 0)

  local divider = kit:CreateDivider(frame.content)
  divider:SetPoint("TOPLEFT", tradedBtn, "BOTTOMLEFT", 0, -8)
  divider:SetPoint("RIGHT", frame.content, "RIGHT", 0, 0)

  local listText = kit:CreateLabel(frame.content, "No deferred trades", "small")
  listText:SetPoint("TOPLEFT", tradedBtn, "BOTTOMLEFT", 0, -16)
  listText:SetPoint("BOTTOMRIGHT", frame.content, "BOTTOMRIGHT", 0, 0)
  listText:SetJustifyH("LEFT")
  listText:SetJustifyV("TOP")
  frame.listText = listText
  frame.currentFilter = FILTER_ALL

  self.frame = frame
  return frame
end

function DeferredTradeFrame:Toggle()
  local frame = self:CreateFrame()
  if frame:IsShown() then
    frame:Hide()
  else
    frame:Show()
    render(frame)
  end
end

function DeferredTradeFrame:OnInitialize()
  self:CreateFrame()
  DR:RegisterChatCommand("drolltrade", function()
    self:Toggle()
  end)

  self:RegisterMessage("DR_DEFERRED_TRADE_ADDED", function()
    render(self.frame)
  end)
  self:RegisterMessage("DR_DEFERRED_TRADE_UPDATED", function()
    render(self.frame)
  end)
end

DR:RegisterModule("Modules.DeferredTradeFrame", DeferredTradeFrame)
