-- HousingDecorGuide/tests/test_auto_layout.lua
---@diagnostic disable: undefined-global
package.path = "./?.lua;../Core/?.lua;" .. package.path

local AL = dofile("../Core/HDG_AutoLayout.lua")
local t = require("test_helpers")

-- AutoLayout takes a connections graph (built by canvas from doorID matching).
-- Tests construct the graph explicitly — no inference from cardinals.
local function room(shape) return { shape = shape } end
local function conn(fromID, fromDir, toID, toDir)
    return { fromID = fromID, fromDir = fromDir, toID = toID, toDir = toDir }
end

-- ============================================================================
-- _pickSeed
-- ============================================================================
t.describe("HDG_AutoLayout._pickSeed", function()
    t.it("entry-shaped room wins regardless of connection count", function()
        local rooms = {
            ["entry"] = room("entry"),
            ["hub"]   = room("cross_shape"),
            ["leaf"]  = room("closet_xs"),
        }
        local connections = {
            conn("hub", "N", "leaf", "S"),
            conn("hub", "S", "entry", "N"),
            conn("hub", "E", "leaf", "W"),  -- give hub more connections
        }
        t.assert_eq(AL._pickSeed(rooms, connections), "entry")
    end)

    t.it("hub fallback: most-connected room wins when no entry", function()
        local rooms = {
            ["hub"]   = room("cross_shape"),
            ["leaf"]  = room("closet_xs"),
            ["chain"] = room("closet_xs"),
        }
        local connections = {
            conn("hub", "N", "chain", "S"),
            conn("hub", "S", "leaf", "N"),
        }
        t.assert_eq(AL._pickSeed(rooms, connections), "hub")
    end)

    t.it("alphabetical tiebreak when connection counts match", function()
        local rooms = {
            ["b_room"] = room("octagon_m"),
            ["a_room"] = room("octagon_m"),
        }
        t.assert_eq(AL._pickSeed(rooms, {}), "a_room")
    end)

    t.it("empty input returns nil", function()
        t.assert_nil(AL._pickSeed({}))
    end)
end)

-- ============================================================================
-- compute
-- ============================================================================
t.describe("HDG_AutoLayout.compute", function()
    t.it("single isolated room placed at origin", function()
        local r = AL.compute({ rooms = { ["r1"] = room("closet_xs") }, connections = {} })
        t.assert_table_eq(r.layout["r1"].cell, { x = 0, y = 0 })
    end)

    t.it("Entry + Cross: Cross placed north of Entry per connection cardinal", function()
        local rooms = {
            ["entry"] = room("entry"),
            ["cross"] = room("cross_shape"),
        }
        local connections = { conn("entry", "N", "cross", "S") }
        local r = AL.compute({ rooms = rooms, connections = connections })
        t.assert_table_eq(r.layout["entry"].cell, { x = 0, y = 0 })
        t.assert_eq(r.layout["cross"].cell.x, 0)
        t.assert_truthy(r.layout["cross"].cell.y < 0, "Cross north of Entry (negative y)")
    end)

    t.it("Cross hub with 4 cardinal leaves", function()
        local rooms = {
            ["hub"]   = room("cross_shape"),
            ["north"] = room("closet_xs"),
            ["east"]  = room("closet_xs"),
            ["south"] = room("closet_xs"),
            ["west"]  = room("closet_xs"),
        }
        local connections = {
            conn("hub", "N", "north", "S"),
            conn("hub", "E", "east",  "W"),
            conn("hub", "S", "south", "N"),
            conn("hub", "W", "west",  "E"),
        }
        local r = AL.compute({ rooms = rooms, connections = connections })
        t.assert_truthy(r.layout["north"].cell.y < r.layout["hub"].cell.y, "north of hub")
        t.assert_truthy(r.layout["south"].cell.y > r.layout["hub"].cell.y, "south of hub")
        t.assert_truthy(r.layout["east"].cell.x  > r.layout["hub"].cell.x, "east of hub")
        t.assert_truthy(r.layout["west"].cell.x  < r.layout["hub"].cell.x, "west of hub")
    end)

    t.it("Backbone chain: Cross → Hallway → Stairwell follows the connections", function()
        -- This is the case that broke the old guess-from-cardinals BFS:
        -- given Cross-N → Hallway-S and Hallway-N → Stairwell-S as explicit
        -- connections, the chain must place Hallway between Cross and Stairwell.
        local rooms = {
            ["cross"]    = room("cross_shape"),
            ["hallway"]  = room("hallway"),
            ["stairwell"]= room("stairwell_right"),
        }
        local connections = {
            conn("cross",   "N", "hallway",   "S"),
            conn("hallway", "N", "stairwell", "S"),
        }
        local r = AL.compute({ rooms = rooms, connections = connections })
        t.assert_truthy(r.layout["hallway"].cell.y   < r.layout["cross"].cell.y,   "Hallway north of Cross")
        t.assert_truthy(r.layout["stairwell"].cell.y < r.layout["hallway"].cell.y, "Stairwell north of Hallway")
    end)

    t.it("disconnected rooms placed without overlap", function()
        local rooms = {
            ["a"] = room("closet_xs"),
            ["b"] = room("closet_xs"),
            ["c"] = room("closet_xs"),
        }
        local r = AL.compute({ rooms = rooms, connections = {} })
        local seen = {}
        for id, info in pairs(r.layout) do
            local key = info.cell.x .. "," .. info.cell.y
            t.assert_nil(seen[key], "collision at " .. key)
            seen[key] = id
        end
    end)

    t.it("empty input returns empty layout", function()
        local r = AL.compute({ rooms = {}, connections = {} })
        t.assert_eq(next(r.layout), nil)
    end)
end)

t.run_all()
