-- HousingDecorGuide/UI/Tabs/HDG_ProjectsTab.lua
-- Top-level Projects tab. View-state machine:
--   landing   — empty state (no captured rooms yet) or pre-capture
--   architect — 2D blueprint canvas + floor switcher + room detail side panel

local _, privateDB = ...

local M = {}

-- Bound lazily in Init (widget modules load AFTER this file in the TOC).
local BudgetStrip, Breadcrumb, Canvas, FloorSwitch, SidePanel, CrateDetail, Palette, Landing
local Store, IDs

local function _faction()
    local f = UnitFactionGroup("player")
    if f == "Alliance" then return "alliance" elseif f == "Horde" then return "horde" end
    return nil
end

local function _currentHouseID()
    local f = _faction()
    if not f then return nil end
    return "house:" .. f
end

local function _hasRooms()
    local h = _currentHouseID()
    if not h then return false end
    local entries = Store.GetRoomsForHouse(h)
    return #entries > 0
end

function M:Init(mainFrame)
    if self._initialized then return end
    self._initialized = true

    -- Bind widget references lazily so TOC order doesn't matter.
    BudgetStrip = privateDB.HDG_BudgetStrip
    Breadcrumb  = privateDB.HDG_Breadcrumb
    Canvas      = privateDB.HDG_ArchitectCanvas
    FloorSwitch = privateDB.HDG_FloorSwitcher
    SidePanel   = privateDB.HDG_RoomSidePanel
    CrateDetail = privateDB.HDG_CrateDetail
    Palette     = privateDB.HDG_PlanPalette
    Landing     = privateDB.HDG_ProjectsLanding
    Store       = privateDB.HDG_ProjectsStore
    IDs         = privateDB.HDG_ProjectsIDs

    local UI = _G.HousingDecorGuide and _G.HousingDecorGuide.UI
    local layout = UI and UI:TabPanel(mainFrame, { hasHeaderBar = false })
    self.panel = layout and layout.frame or mainFrame
    self.panel:Hide()

    -- Budget strip docks at very top
    self.budget = BudgetStrip
    self.budget:Create(self.panel)

    -- Breadcrumb under strip
    local bcHost = CreateFrame("Frame", nil, self.panel)
    bcHost:SetPoint("TOPLEFT",  self.budget.frame, "BOTTOMLEFT",  0, 0)
    bcHost:SetPoint("TOPRIGHT", self.budget.frame, "BOTTOMRIGHT", 0, 0)
    bcHost:SetHeight(22)
    self.bcHost = bcHost
    self.breadcrumb = Breadcrumb
    self.breadcrumb:Create(bcHost)

    -- Content host (everything below breadcrumb)
    local content = CreateFrame("Frame", nil, self.panel)
    content:SetPoint("TOPLEFT",     bcHost,      "BOTTOMLEFT",  0, -2)
    content:SetPoint("BOTTOMRIGHT", self.panel,  "BOTTOMRIGHT", 0,  0)
    self.content = content

    -- Architect view: canvas + floor switcher + side panel layered on content
    self.canvas = Canvas
    self.canvas:Create(content)
    self.floors = FloorSwitch
    self.floors:Create(content)
    self.sidePanel = SidePanel
    self.sidePanel:Create(content)
    self.crateDetail = CrateDetail
    self.crateDetail:Create(content)
    self.palette = Palette
    self.palette:Create(content)

    self.canvas:SetOnRoomClick(function(roomID)
        Store.SetUIField("selectedRoomID", roomID)
        Store.SetUIField("selectedCrateID", nil)
        self.crateDetail:Hide()
        self.sidePanel:Show(roomID)
        self:_RefreshBreadcrumb()
    end)
    self.sidePanel:SetOnCrateOpen(function(crateID)
        Store.SetUIField("selectedCrateID", crateID)
        self.sidePanel:Hide()
        self.crateDetail:Show(crateID)
        self:_RefreshBreadcrumb()
    end)
    self.crateDetail:SetOnBack(function()
        Store.SetUIField("selectedCrateID", nil)
        self.crateDetail:Hide()
        local ui = Store.GetUI()
        if ui.selectedRoomID then self.sidePanel:Show(ui.selectedRoomID) end
        self:_RefreshBreadcrumb()
    end)

    -- Crate deletion (from any source) pops us back to the room view.
    local g = _G.HousingDecorGuide
    local bus = g and g.EventBus
    if bus and bus.Register then
        bus:Register("HDG_COLLECTION_DELETED", function(payload)
            if not (payload and payload.type == "crate") then return end
            local ui = Store.GetUI()
            if ui.selectedCrateID == payload.collID then
                Store.SetUIField("selectedCrateID", nil)
                self.crateDetail:Hide()
                if ui.selectedRoomID then self.sidePanel:Show(ui.selectedRoomID) end
                self:_RefreshBreadcrumb()
            end
        end)

        -- Plan mode is a canvas-only surface; the room/crate side panels
        -- aren't reachable there (no clickable rooms). Hide them on entry
        -- and clear the persisted selections so reflect resumes cleanly.
        -- Show the shape palette; hide it on Reflect.
        bus:Register("HDG_PROJECTS_MODE_CHANGED", function(payload)
            if not payload then return end
            if payload.mode == "plan" then
                Store.SetUIField("selectedRoomID",  nil)
                Store.SetUIField("selectedCrateID", nil)
                if self.sidePanel   then self.sidePanel:Hide()   end
                if self.crateDetail then self.crateDetail:Hide() end
                if self.palette     then self.palette:Show(self.activeFloor or 1) end
            else
                if self.palette     then self.palette:Hide() end
            end
            self:_RefreshBreadcrumb()
        end)
    end
    self.floors:SetOnFloorSelected(function(floor)
        self:_SetActiveFloor(floor)
    end)

    -- Landing view: empty-state fallback only
    self.landing = Landing
    self.landing:Create(content)

    -- Subscribe to capture events so the tab re-evaluates landing-vs-architect
    -- when rooms are first captured (otherwise Tab stays in empty-state mode
    -- while Landing's own subscriber re-shows its list).
    local g = _G.HousingDecorGuide
    local bus = g and g.EventBus
    if bus and bus.Register then
        local function _resync()
            if self.panel and self.panel:IsShown() then self:Show() end
        end
        bus:Register("HDG_PROJECTS_CAPTURE_COMPLETE",  _resync)
        bus:Register("HDG_PROJECTS_TOPOLOGY_UPDATED",  _resync)
    end
end

function M:_SetActiveFloor(floor)
    -- Floor switch invalidates the previous selection (the selected room may
    -- be on a different floor). Clear the side panel + persisted selection
    -- so the breadcrumb and panel match the floor the user is now viewing.
    if self.activeFloor and self.activeFloor ~= floor then
        Store.SetUIField("selectedRoomID", nil)
        if self.sidePanel and self.sidePanel.Hide then self.sidePanel:Hide() end
    end
    self.activeFloor = floor
    self.canvas:Refresh(floor)
    self.floors:Refresh(_currentHouseID(), floor)
    if self.palette then self.palette:SetFloor(floor) end
    self:_RefreshBreadcrumb()
end

function M:_RefreshBreadcrumb()
    local segments = {
        { label = "Projects",  key = "projects"  },
        { label = "Architect", key = "architect" },
    }
    local houseID = _currentHouseID()
    if houseID then
        local faction = IDs.parseHouseID(houseID) or ""
        local title = faction:gsub("^%l", string.upper)
        segments[#segments + 1] = { label = title, key = "house" }
    end
    if self.activeFloor then
        segments[#segments + 1] = { label = "F" .. self.activeFloor, key = "floor" }
    end
    local ui = Store.GetUI()
    if ui.selectedRoomID then
        local parsed = IDs.parsePath(ui.selectedRoomID) or {}
        segments[#segments + 1] = {
            label = "Room " .. (parsed.roomShortID or "?"),
            key   = "room",
        }
    end
    if ui.selectedCrateID then
        local store = _G.HousingDecorGuide and _G.HousingDecorGuide.Store
        local coll = store and store.Collection_Get and store:Collection_Get(ui.selectedCrateID)
        segments[#segments + 1] = {
            label = "Crate" .. (coll and coll.name and (": " .. coll.name) or ""),
            key   = "crate",
        }
    end
    self.breadcrumb:SetSegments(segments, function(key, _)
        if key == "architect" or key == "house" or key == "floor" or key == "projects" then
            -- Pop back: clear all selections
            Store.SetUIField("selectedRoomID", nil)
            Store.SetUIField("selectedCrateID", nil)
            self.sidePanel:Hide()
            if self.crateDetail then self.crateDetail:Hide() end
            self:_RefreshBreadcrumb()
        elseif key == "room" then
            -- Pop crate detail, keep room
            Store.SetUIField("selectedCrateID", nil)
            if self.crateDetail then self.crateDetail:Hide() end
            local ui2 = Store.GetUI()
            if ui2.selectedRoomID then self.sidePanel:Show(ui2.selectedRoomID) end
            self:_RefreshBreadcrumb()
        end
    end)
end

function M:Show()
    if not self.panel then return end
    self.panel:Show()
    self.budget:Refresh()

    if _hasRooms() then
        -- Architect view
        self.landing:Hide()
        if self.canvas.frame then self.canvas.frame:Show() end
        if self.floors.frame then self.floors.frame:Show() end

        local ui = Store.GetUI()
        local floor = ui.selectedFloor or 1
        self:_SetActiveFloor(floor)

        if ui.selectedCrateID then
            self.sidePanel:Hide()
            self.crateDetail:Show(ui.selectedCrateID)
        elseif ui.selectedRoomID then
            self.crateDetail:Hide()
            self.sidePanel:Show(ui.selectedRoomID)
        else
            self.sidePanel:Hide()
            self.crateDetail:Hide()
        end
    else
        -- Landing (empty state)
        if self.canvas.frame then self.canvas.frame:Hide() end
        if self.floors.frame then self.floors.frame:Hide() end
        self.sidePanel:Hide()
        self.landing:Show()
        self.breadcrumb:SetSegments({ { label = "Projects", key = "projects" } }, nil)
    end
end

function M:Hide()
    if self.landing     and self.landing.Hide      then self.landing:Hide()        end
    if self.sidePanel                              then self.sidePanel:Hide()      end
    if self.crateDetail                            then self.crateDetail:Hide()    end
    if self.canvas      and self.canvas.frame      then self.canvas.frame:Hide()   end
    if self.floors      and self.floors.frame      then self.floors.frame:Hide()   end
    if self.panel                                  then self.panel:Hide()          end
end

privateDB.HDG_ProjectsTab = M
