local addonName, addon = ...

local UI = addon.UI
local DB = addon.DB

local function TodayParts()
    local now = date("*t")
    return now.year, now.month, now.day
end

local function SameToday(task)
    if not task or not task.dueDate then return false end
    local y, m, d = TodayParts()
    return task.dueDate.year == y
        and task.dueDate.month == m
        and task.dueDate.day == d
end

local function ApplyFloatingBackdrop(frame, urgent)
    frame:SetBackdrop({
        bgFile = "Interface\\Buttons\\WHITE8X8",
        edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
        edgeSize = 10,
    })

    if urgent then
        frame:SetBackdropColor(0.34, 0.015, 0.02, 0.88)
        frame:SetBackdropBorderColor(0.85, 0.12, 0.12, 1)
    else
        frame:SetBackdropColor(0.025, 0.025, 0.035, 0.82)
        frame:SetBackdropBorderColor(0.25, 0.25, 0.30, 0.95)
    end
end

local function MakeTitle(frame, text)
    local title = frame:CreateFontString(nil, "OVERLAY")
    title:SetFontObject(GameFontNormal)
    title:SetPoint("TOPLEFT", frame, "TOPLEFT", 12, -10)
    title:SetText(text)
    title:SetTextColor(1.0, 0.82, 0.15, 1)
    return title
end

local function AddResizeGrip(frame, lockKey, widthKey, heightKey)
    frame:SetResizable(true)
    frame:SetResizeBounds(240, 120, 900, 900)

    local grip = CreateFrame("Button", nil, frame)
    grip:SetSize(18, 18)
    grip:SetPoint("BOTTOMRIGHT", frame, "BOTTOMRIGHT", -2, 2)
    grip:SetNormalTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Up")
    grip:SetHighlightTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Highlight")
    grip:SetPushedTexture("Interface\\ChatFrame\\UI-ChatIM-SizeGrabber-Down")

    grip:SetScript("OnMouseDown", function()
        if WhatsNextUserData.settings and WhatsNextUserData.settings[lockKey] then
            return
        end
        if not InCombatLockdown() then
            frame:StartSizing("BOTTOMRIGHT")
        end
    end)

    grip:SetScript("OnMouseUp", function()
        frame:StopMovingOrSizing()
        WhatsNextUserData.settings[widthKey] = math.floor(frame:GetWidth() + 0.5)
        WhatsNextUserData.settings[heightKey] = math.floor(frame:GetHeight() + 0.5)
        if UI.RefreshDetachedWindows then
            UI:RefreshDetachedWindows()
        end
    end)

    frame.ResizeGrip = grip
end

local function MakeMovable(frame, lockKey)
    frame:SetMovable(true)
    frame:EnableMouse(true)
    frame:RegisterForDrag("LeftButton")
    frame:SetClampedToScreen(true)

    frame:SetScript("OnDragStart", function(self)
        if WhatsNextUserData.settings and WhatsNextUserData.settings[lockKey] then
            return
        end
        if not InCombatLockdown() then
            self:StartMoving()
        end
    end)

    frame:SetScript("OnDragStop", function(self)
        self:StopMovingOrSizing()
    end)
end

function UI:GetTodayTasksForFloatingWindow()
    local result = {}

    for _, task in ipairs(DB:GetTasks()) do
        if SameToday(task) then
            table.insert(result, task)
        end
    end

    table.sort(result, function(a, b)
        if a.completed ~= b.completed then
            return a.completed ~= true
        end

        local at = DB:GetTaskTimestamp(a) or 9999999999
        local bt = DB:GetTaskTimestamp(b) or 9999999999

        if at == bt then
            return (a.createdAt or 0) < (b.createdAt or 0)
        end

        return at < bt
    end)

    return result
end

function UI:GetTodayTimedTasksForFloatingWindow()
    local result = {}

    for _, task in ipairs(DB:GetTasks()) do
        if SameToday(task)
            and not task.completed
            and DB:TaskHasTime(task)
        then
            table.insert(result, task)
        end
    end

    table.sort(result, function(a, b)
        return (DB:GetTaskTimestamp(a) or 0) < (DB:GetTaskTimestamp(b) or 0)
    end)

    return result
end

function UI:InitializeDetachedWindows()
    if self.TodayTimersWindow or self.TodayTasksWindow then
        return
    end

    WhatsNextUserData.settings = WhatsNextUserData.settings or {}

    --------------------------------------------------------
    -- TODAY TIMERS
    --------------------------------------------------------
    local timers = CreateFrame("Frame", "WhatsNextTodayTimersWindow", UIParent, "BackdropTemplate")
    self.TodayTimersWindow = timers
    timers:SetSize(
        WhatsNextUserData.settings.todayTimersWidth or 330,
        WhatsNextUserData.settings.todayTimersHeight or 190
    )
    timers:SetPoint("TOPRIGHT", UIParent, "TOPRIGHT", -40, -180)
    timers:SetFrameStrata("MEDIUM")

    MakeMovable(timers, "lockTodayTimersWindow")
    AddResizeGrip(
        timers,
        "lockTodayTimersWindow",
        "todayTimersWidth",
        "todayTimersHeight"
    )
    ApplyFloatingBackdrop(timers, false)

    local timerTitle = MakeTitle(timers, "TODAY TIMERS")
    self.TodayTimersTitle = timerTitle

    local timerScroll = CreateFrame("ScrollFrame", nil, timers, "UIPanelScrollFrameTemplate")
    timerScroll:SetPoint("TOPLEFT", timers, "TOPLEFT", 10, -32)
    timerScroll:SetPoint("BOTTOMRIGHT", timers, "BOTTOMRIGHT", -28, 10)

    local timerContent = CreateFrame("Frame", nil, timerScroll)
    timerContent:SetSize(285, 120)
    timerScroll:SetScrollChild(timerContent)
    self.TodayTimersContent = timerContent

    --------------------------------------------------------
    -- TODAY TASKS
    --------------------------------------------------------
    local tasks = CreateFrame("Frame", "WhatsNextTodayTasksWindow", UIParent, "BackdropTemplate")
    self.TodayTasksWindow = tasks
    tasks:SetSize(
        WhatsNextUserData.settings.todayTasksWidth or 380,
        WhatsNextUserData.settings.todayTasksHeight or 300
    )
    tasks:SetPoint("TOPRIGHT", timers, "BOTTOMRIGHT", 0, -12)
    tasks:SetFrameStrata("MEDIUM")

    MakeMovable(tasks, "lockTodayTasksWindow")
    AddResizeGrip(
        tasks,
        "lockTodayTasksWindow",
        "todayTasksWidth",
        "todayTasksHeight"
    )
    ApplyFloatingBackdrop(tasks, false)

    local taskTitle = MakeTitle(tasks, "TODAY TASKS")
    self.TodayTasksTitle = taskTitle

    local taskScroll = CreateFrame("ScrollFrame", nil, tasks, "UIPanelScrollFrameTemplate")
    taskScroll:SetPoint("TOPLEFT", tasks, "TOPLEFT", 10, -32)
    taskScroll:SetPoint("BOTTOMRIGHT", tasks, "BOTTOMRIGHT", -28, 10)

    local taskContent = CreateFrame("Frame", nil, taskScroll)
    taskContent:SetSize(335, 240)
    taskScroll:SetScrollChild(taskContent)
    self.TodayTasksContent = taskContent

    self:ApplyDetachedWindowSettings()
    self:RefreshDetachedWindows()

    local elapsed = 0
    timers:SetScript("OnUpdate", function(_, dt)
        elapsed = elapsed + dt
        if elapsed >= 1 then
            elapsed = 0
            UI:RefreshTodayTimersWindow()
        end
    end)

    local taskElapsed = 0
    tasks:SetScript("OnUpdate", function(_, dt)
        taskElapsed = taskElapsed + dt
        if taskElapsed >= 2 then
            taskElapsed = 0
            UI:RefreshTodayTasksWindow()
        end
    end)
end

function UI:ApplyDetachedWindowSettings()
    if not WhatsNextUserData then return end

    WhatsNextUserData.settings = WhatsNextUserData.settings or {}

    local showTimers = WhatsNextUserData.settings.showTodayTimersWindow ~= false
    local showTasks = WhatsNextUserData.settings.showTodayTasksWindow ~= false
    local lockTimers = WhatsNextUserData.settings.lockTodayTimersWindow == true
    local lockTasks = WhatsNextUserData.settings.lockTodayTasksWindow == true

    if self.TodayTimersWindow then
        if showTimers then
            self.TodayTimersWindow:Show()
        else
            self.TodayTimersWindow:Hide()
        end

        if self.TodayTimersWindow.ResizeGrip then
            self.TodayTimersWindow.ResizeGrip:SetShown(not lockTimers)
        end
    end

    if self.TodayTasksWindow then
        if showTasks then
            self.TodayTasksWindow:Show()
        else
            self.TodayTasksWindow:Hide()
        end

        if self.TodayTasksWindow.ResizeGrip then
            self.TodayTasksWindow.ResizeGrip:SetShown(not lockTasks)
        end
    end

    if self.TodayTimersSettingCheck then
        self.TodayTimersSettingCheck:SetChecked(showTimers)
    end

    if self.TodayTasksSettingCheck then
        self.TodayTasksSettingCheck:SetChecked(showTasks)
    end

    if self.TodayTimersLockCheck then
        self.TodayTimersLockCheck:SetChecked(lockTimers)
    end

    if self.TodayTasksLockCheck then
        self.TodayTasksLockCheck:SetChecked(lockTasks)
    end
end

function UI:SetTodayTimersWindowEnabled(enabled)
    WhatsNextUserData.settings.showTodayTimersWindow = enabled == true
    self:ApplyDetachedWindowSettings()
    self:RefreshTodayTimersWindow()
end

function UI:SetTodayTasksWindowEnabled(enabled)
    WhatsNextUserData.settings.showTodayTasksWindow = enabled == true
    self:ApplyDetachedWindowSettings()
    self:RefreshTodayTasksWindow()
end

function UI:SetTodayTimersWindowLocked(locked)
    WhatsNextUserData.settings.lockTodayTimersWindow = locked == true
    self:ApplyDetachedWindowSettings()
end

function UI:SetTodayTasksWindowLocked(locked)
    WhatsNextUserData.settings.lockTodayTasksWindow = locked == true
    self:ApplyDetachedWindowSettings()
end

function UI:RefreshTodayTimersWindow()
    if not self.TodayTimersContent or not self.TodayTimersWindow then return end
    if WhatsNextUserData.settings.showTodayTimersWindow == false then return end

    self:ClearFrame(self.TodayTimersContent)

    local tasks = self:GetTodayTimedTasksForFloatingWindow()
    local urgent = false
    local y = 0
    local rowHeight = 42
    local contentWidth = math.max(180, self.TodayTimersWindow:GetWidth() - 48)

    for _, task in ipairs(tasks) do
        local remaining = DB:GetRemainingSeconds(task)
        if remaining and remaining <= 600 then
            urgent = true
        end

        local row = CreateFrame("Frame", nil, self.TodayTimersContent)
        row:SetSize(contentWidth, rowHeight)
        row:SetPoint("TOPLEFT", self.TodayTimersContent, "TOPLEFT", 0, y)

        local check = CreateFrame("CheckButton", nil, row, "UICheckButtonTemplate")
        check:SetSize(24, 24)
        check:SetPoint("TOPLEFT", row, "TOPLEFT", 0, 2)
        check:SetChecked(false)
        check:SetScript("OnClick", function(button)
            if button:GetChecked() then
                DB:CompleteTask(task.id)
                UI:RefreshDetachedWindows()
                UI:Refresh()
            end
        end)

        local timeText = row:CreateFontString(nil, "OVERLAY")
        timeText:SetFontObject(GameFontNormal)
        timeText:SetPoint("TOPLEFT", check, "TOPRIGHT", 2, -1)
        timeText:SetWidth(58)
        timeText:SetJustifyH("LEFT")
        timeText:SetText(self:GetTaskTimeText(task))
        timeText:SetTextColor(1.0, 0.82, 0.15, 1)

        local title = row:CreateFontString(nil, "OVERLAY")
        title:SetFontObject(GameFontHighlight)
        title:SetPoint("TOPLEFT", timeText, "TOPRIGHT", 4, 0)
        title:SetPoint("RIGHT", row, "RIGHT", -2, 0)
        title:SetJustifyH("LEFT")
        title:SetWordWrap(false)
        title:SetText(tostring(task.title or ""))

        local remain = row:CreateFontString(nil, "OVERLAY")
        remain:SetFontObject(GameFontNormal)
        remain:SetPoint("TOPLEFT", timeText, "BOTTOMLEFT", 0, -2)
        remain:SetPoint("RIGHT", row, "RIGHT", -2, 0)
        remain:SetJustifyH("LEFT")

        if remaining and remaining < 0 then
            remain:SetText(UI:T("OVERDUE", "OVERDUE") .. " " .. self:FormatRemaining(math.abs(remaining)))
            remain:SetTextColor(1, 0.3, 0.3, 1)
        else
            remain:SetText(self:FormatRemaining(remaining))
            if remaining and remaining <= 600 then
                remain:SetTextColor(1, 0.45, 0.45, 1)
            else
                remain:SetTextColor(0.72, 0.72, 0.76, 1)
            end
        end

        y = y - rowHeight
    end

    if #tasks == 0 then
        local empty = self.TodayTimersContent:CreateFontString(nil, "OVERLAY")
        empty:SetFontObject(GameFontNormal)
        empty:SetPoint("TOPLEFT", self.TodayTimersContent, "TOPLEFT", 0, 0)
        empty:SetText(UI:T("NO_ACTIVE_TIMERS", "NO ACTIVE TIMERS TODAY"))
        empty:SetTextColor(0.65, 0.65, 0.70, 1)
        y = -24
    end

    self.TodayTimersContent:SetWidth(contentWidth)
    self.TodayTimersContent:SetHeight(math.max(self.TodayTimersWindow:GetHeight() - 60, math.abs(y) + 8))

    ApplyFloatingBackdrop(self.TodayTimersWindow, urgent)
end

function UI:RefreshTodayTasksWindow()
    if not self.TodayTasksContent or not self.TodayTasksWindow then return end
    if WhatsNextUserData.settings.showTodayTasksWindow == false then return end

    self:ClearFrame(self.TodayTasksContent)

    local tasks = self:GetTodayTasksForFloatingWindow()
    local y = 0
    local rowHeight = 38
    local contentWidth = math.max(200, self.TodayTasksWindow:GetWidth() - 48)

    for _, task in ipairs(tasks) do
        local row = CreateFrame("Frame", nil, self.TodayTasksContent, "BackdropTemplate")
        row:SetSize(contentWidth, rowHeight)
        row:SetPoint("TOPLEFT", self.TodayTasksContent, "TOPLEFT", 0, y)
        row:SetBackdrop({ bgFile = "Interface\\Buttons\\WHITE8X8" })
        row:SetBackdropColor(0.07, 0.07, 0.09, 0.58)

        local check = CreateFrame("CheckButton", nil, row, "UICheckButtonTemplate")
        check:SetSize(24, 24)
        check:SetPoint("LEFT", row, "LEFT", 2, 0)
        check:SetChecked(task.completed == true)

        check:SetScript("OnClick", function(button)
            if button:GetChecked() then
                DB:CompleteTask(task.id)
            else
                DB:UncompleteTask(task.id)
            end

            UI:RefreshDetachedWindows()
            UI:Refresh()
        end)

        local timeText = row:CreateFontString(nil, "OVERLAY")
        timeText:SetFontObject(GameFontNormal)
        timeText:SetPoint("LEFT", check, "RIGHT", 2, 0)
        timeText:SetWidth(58)
        timeText:SetJustifyH("LEFT")

        if DB:TaskHasTime(task) then
            timeText:SetText(self:GetTaskTimeText(task))
            timeText:SetTextColor(1.0, 0.82, 0.15, 1)
        else
            timeText:SetText("")
        end

        local title = row:CreateFontString(nil, "OVERLAY")
        title:SetFontObject(GameFontHighlight)
        title:SetPoint("LEFT", timeText, "RIGHT", 4, 0)
        title:SetPoint("RIGHT", row, "RIGHT", -4, 0)
        title:SetJustifyH("LEFT")
        title:SetWordWrap(false)
        title:SetText(tostring(task.title or ""))

        if task.completed then
            title:SetTextColor(0.50, 0.50, 0.54, 1)
        else
            title:SetTextColor(0.95, 0.95, 0.96, 1)
        end

        y = y - rowHeight
    end

    if #tasks == 0 then
        local empty = self.TodayTasksContent:CreateFontString(nil, "OVERLAY")
        empty:SetFontObject(GameFontNormal)
        empty:SetPoint("TOPLEFT", self.TodayTasksContent, "TOPLEFT", 0, 0)
        empty:SetText(UI:T("NO_TASKS_TODAY", "NO TASKS FOR TODAY"))
        empty:SetTextColor(0.65, 0.65, 0.70, 1)
        y = -24
    end

    self.TodayTasksContent:SetWidth(contentWidth)
    self.TodayTasksContent:SetHeight(math.max(self.TodayTasksWindow:GetHeight() - 60, math.abs(y) + 8))
end

function UI:RefreshDetachedWindows()
    self:RefreshTodayTimersWindow()
    self:RefreshTodayTasksWindow()
end
