local DR = select(2, ...)

--- Shared flat/dark UI factory so every DetentionRolls window looks the same
--- and none of them use the stock WoW dialog styling. All windows are
--- movable (drag the title bar) and remember their position per profile.
local Kit = {}

local WHITE = "Interface\\Buttons\\WHITE8X8"

local COLORS = {
  bg        = { 0.055, 0.060, 0.080, 0.97 },
  bgLight   = { 0.105, 0.110, 0.140, 1.00 },
  bgCard    = { 0.085, 0.090, 0.115, 1.00 },
  border    = { 0.220, 0.230, 0.290, 1.00 },
  accent    = { 1.000, 0.720, 0.300, 1.00 },
  accentDim = { 1.000, 0.720, 0.300, 0.35 },
  text      = { 0.920, 0.920, 0.950, 1.00 },
  textDim   = { 0.600, 0.610, 0.680, 1.00 },
  btn       = { 0.130, 0.135, 0.175, 1.00 },
  btnHover  = { 0.200, 0.210, 0.275, 1.00 },
  danger    = { 0.850, 0.380, 0.380, 1.00 },
  good      = { 0.420, 0.800, 0.480, 1.00 },
}
Kit.COLORS = COLORS

local BACKDROP_PANEL = {
  bgFile = WHITE,
  edgeFile = WHITE,
  edgeSize = 1,
}

local BACKDROP_FILL = {
  bgFile = WHITE,
}

local function positions()
  local ui = DR.db.profile.ui
  ui.positions = ui.positions or {}
  return ui.positions
end

function Kit:SavePosition(key, frame)
  local point, _, relativePoint, x, y = frame:GetPoint(1)
  if point then
    positions()[key] = { point = point, relativePoint = relativePoint, x = x, y = y }
  end
end

function Kit:RestorePosition(key, frame, defaultX, defaultY)
  local saved = positions()[key]
  frame:ClearAllPoints()
  if saved and saved.point then
    frame:SetPoint(saved.point, UIParent, saved.relativePoint or saved.point, saved.x or 0, saved.y or 0)
  else
    frame:SetPoint("CENTER", UIParent, "CENTER", defaultX or 0, defaultY or 0)
  end
end

function Kit:CreateLabel(parent, text, size, color)
  local template = size == "large" and "GameFontNormalLarge" or size == "small" and "GameFontHighlightSmall" or "GameFontHighlight"
  local label = parent:CreateFontString(nil, "OVERLAY", template)
  label:SetText(text or "")
  local c = color or COLORS.text
  label:SetTextColor(c[1], c[2], c[3], c[4] or 1)
  return label
end

function Kit:CreateButton(parent, text, width, height, onClick, opts)
  opts = opts or {}
  local btn = CreateFrame("Button", nil, parent, "BackdropTemplate")
  btn:SetSize(width, height)
  btn:SetBackdrop(BACKDROP_PANEL)

  local base = opts.danger and { 0.30, 0.13, 0.13, 1 }
    or opts.accent and { 0.55, 0.37, 0.10, 1 }
    or COLORS.btn
  local hover = opts.danger and { 0.45, 0.18, 0.18, 1 }
    or opts.accent and { 0.75, 0.51, 0.15, 1 }
    or COLORS.btnHover
  btn:SetBackdropColor(base[1], base[2], base[3], base[4])
  btn:SetBackdropBorderColor(unpack(COLORS.border))

  local label = btn:CreateFontString(nil, "OVERLAY", opts.smallText and "GameFontHighlightSmall" or "GameFontHighlight")
  label:SetPoint("CENTER", 0, 0)
  label:SetText(text)
  label:SetTextColor(unpack(COLORS.text))
  btn.label = label

  btn:SetScript("OnEnter", function(b)
    b:SetBackdropColor(hover[1], hover[2], hover[3], hover[4])
    b:SetBackdropBorderColor(unpack(COLORS.accentDim))
  end)
  btn:SetScript("OnLeave", function(b)
    b:SetBackdropColor(base[1], base[2], base[3], base[4])
    b:SetBackdropBorderColor(unpack(COLORS.border))
  end)
  if onClick then
    btn:SetScript("OnClick", onClick)
  end

  function btn:SetEnabledState(enabled)
    if enabled then
      self:Enable()
      self.label:SetTextColor(unpack(COLORS.text))
    else
      self:Disable()
      self.label:SetTextColor(unpack(COLORS.textDim))
    end
  end

  return btn
end

function Kit:CreateEditBox(parent, width, height)
  local box = CreateFrame("EditBox", nil, parent, "BackdropTemplate")
  box:SetSize(width, height)
  box:SetBackdrop(BACKDROP_PANEL)
  box:SetBackdropColor(unpack(COLORS.bgLight))
  box:SetBackdropBorderColor(unpack(COLORS.border))
  box:SetFontObject("GameFontHighlightSmall")
  box:SetTextColor(unpack(COLORS.text))
  box:SetTextInsets(8, 8, 0, 0)
  box:SetAutoFocus(false)
  box:SetScript("OnEscapePressed", function(b)
    b:ClearFocus()
  end)
  box:SetScript("OnEditFocusGained", function(b)
    b:SetBackdropBorderColor(unpack(COLORS.accentDim))
  end)
  box:SetScript("OnEditFocusLost", function(b)
    b:SetBackdropBorderColor(unpack(COLORS.border))
  end)
  return box
end

function Kit:CreateCard(parent, height)
  local card = CreateFrame("Frame", nil, parent, "BackdropTemplate")
  card:SetHeight(height)
  card:SetBackdrop(BACKDROP_PANEL)
  card:SetBackdropColor(unpack(COLORS.bgCard))
  card:SetBackdropBorderColor(unpack(COLORS.border))

  function card:SetSelected(selected)
    if selected then
      self:SetBackdropBorderColor(unpack(COLORS.accentDim))
    else
      self:SetBackdropBorderColor(unpack(COLORS.border))
    end
  end

  return card
end

function Kit:CreateDivider(parent)
  local line = parent:CreateTexture(nil, "ARTWORK")
  line:SetColorTexture(unpack(COLORS.border))
  line:SetHeight(1)
  return line
end

--- Movable dark window with title bar, accent underline, close button and
--- position persistence. ESC closes it (added to UISpecialFrames).
function Kit:CreateWindow(key, title, width, height, opts)
  opts = opts or {}
  local name = "DetentionRolls" .. key
  local frame = CreateFrame("Frame", name, UIParent, "BackdropTemplate")
  frame:SetSize(width, height)
  frame:SetFrameStrata(opts.strata or "MEDIUM")
  frame:SetBackdrop(BACKDROP_PANEL)
  frame:SetBackdropColor(unpack(COLORS.bg))
  frame:SetBackdropBorderColor(unpack(COLORS.border))
  frame:SetMovable(true)
  frame:SetClampedToScreen(true)
  frame:EnableMouse(true)

  local titleBar = CreateFrame("Frame", nil, frame, "BackdropTemplate")
  titleBar:SetPoint("TOPLEFT", 1, -1)
  titleBar:SetPoint("TOPRIGHT", -1, -1)
  titleBar:SetHeight(30)
  titleBar:SetBackdrop(BACKDROP_FILL)
  titleBar:SetBackdropColor(unpack(COLORS.bgLight))
  titleBar:EnableMouse(true)
  titleBar:RegisterForDrag("LeftButton")
  titleBar:SetScript("OnDragStart", function()
    frame:StartMoving()
  end)
  titleBar:SetScript("OnDragStop", function()
    frame:StopMovingOrSizing()
    Kit:SavePosition(key, frame)
  end)

  local titleText = self:CreateLabel(titleBar, title, "normal", COLORS.accent)
  titleText:SetPoint("LEFT", 10, 0)

  local accentLine = frame:CreateTexture(nil, "ARTWORK")
  accentLine:SetColorTexture(unpack(COLORS.accentDim))
  accentLine:SetHeight(1)
  accentLine:SetPoint("TOPLEFT", titleBar, "BOTTOMLEFT", 0, 0)
  accentLine:SetPoint("TOPRIGHT", titleBar, "BOTTOMRIGHT", 0, 0)

  local close = CreateFrame("Button", nil, titleBar)
  close:SetSize(24, 24)
  close:SetPoint("RIGHT", -4, 0)
  local closeText = self:CreateLabel(close, "x", "normal", COLORS.textDim)
  closeText:SetPoint("CENTER", 0, 1)
  close:SetScript("OnEnter", function()
    closeText:SetTextColor(unpack(COLORS.danger))
  end)
  close:SetScript("OnLeave", function()
    closeText:SetTextColor(unpack(COLORS.textDim))
  end)
  close:SetScript("OnClick", function()
    frame:Hide()
  end)

  -- content area anchor helpers
  local content = CreateFrame("Frame", nil, frame)
  content:SetPoint("TOPLEFT", titleBar, "BOTTOMLEFT", 10, -8)
  content:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -10, 10)

  frame.titleBar = titleBar
  frame.titleText = titleText
  frame.content = content

  self:RestorePosition(key, frame, opts.defaultX, opts.defaultY)

  if opts.escClosable ~= false then
    tinsert(UISpecialFrames, name)
  end

  frame:Hide()
  return frame
end

--- Multiline text area (for export/import blobs). Returns the container;
--- the EditBox is at `.edit`.
function Kit:CreateTextArea(parent, width, height)
  local container = CreateFrame("Frame", nil, parent, "BackdropTemplate")
  container:SetSize(width, height)
  container:SetBackdrop(BACKDROP_PANEL)
  container:SetBackdropColor(unpack(COLORS.bgLight))
  container:SetBackdropBorderColor(unpack(COLORS.border))

  local scroll = CreateFrame("ScrollFrame", nil, container)
  scroll:SetPoint("TOPLEFT", 6, -6)
  scroll:SetPoint("BOTTOMRIGHT", -6, 6)

  local edit = CreateFrame("EditBox", nil, scroll)
  edit:SetMultiLine(true)
  edit:SetFontObject("GameFontHighlightSmall")
  edit:SetTextColor(unpack(COLORS.text))
  edit:SetWidth(width - 16)
  edit:SetAutoFocus(false)
  edit:SetScript("OnEscapePressed", function(e)
    e:ClearFocus()
  end)
  scroll:SetScrollChild(edit)

  scroll:EnableMouseWheel(true)
  scroll:SetScript("OnMouseWheel", function(s, delta)
    local maxScroll = math.max((edit:GetHeight() or 0) - s:GetHeight(), 0)
    s:SetVerticalScroll(math.min(math.max(s:GetVerticalScroll() - delta * 30, 0), maxScroll))
  end)

  container:EnableMouse(true)
  container:SetScript("OnMouseDown", function()
    edit:SetFocus()
  end)

  container.edit = edit
  return container
end

--- Simple mousewheel scrolling: calls onScroll(delta) with +1/-1.
function Kit:AttachWheelScroll(frame, onScroll)
  frame:EnableMouseWheel(true)
  frame:SetScript("OnMouseWheel", function(_, delta)
    onScroll(-delta)
  end)
end

DR:RegisterModule("UI.Kit", Kit)
