using Theriapolis.Core.Tactical;
using Theriapolis.Core.World;

namespace Theriapolis.Core.Dungeons;

/// <summary>
/// Phase 7 M1 — runtime view of an interior dungeon. Generated lazily on
/// the player's first entry to a PoI; persisted modifications live on
/// <see cref="Theriapolis.Core.Persistence.DungeonStateSnapshot"/> and
/// re-apply on reload.
///
/// The dungeon owns its own bounded tactical-tile array (the scene-swap
/// model from Phase 7 plan §4.2): movement, combat, dialogue, and save/load
/// all work the same as the surface, but the renderer reads tiles from
/// <see cref="Tiles"/> instead of the chunk streamer.
///
/// Coordinate space: <c>Tiles[x, y]</c> where <c>x ∈ [0, W)</c> and
/// <c>y ∈ [0, H)</c>. Every <see cref="Room"/>'s AABB falls within these
/// bounds; corridor tiles between rooms are also in this array.
/// </summary>
public sealed class Dungeon
{
    /// <summary>Source PoI id. Identity for save lookups.</summary>
    public int       PoiId       { get; }

    /// <summary>Dungeon type — drives art family, default loot tier, etc.</summary>
    public PoiType   Type        { get; }

    /// <summary>The tactical-tile grid in dungeon-local coordinates.</summary>
    public TacticalTile[,] Tiles { get; }

    /// <summary>Every room in layout order. <c>Rooms[i].Id == i</c>.</summary>
    public Room[]    Rooms       { get; }

    /// <summary>
    /// Door-anchored connections between rooms. Authoritative for
    /// reachability — the graph is undirected (a connection from A→B is
    /// implicit B→A; do not double-store).
    /// </summary>
    public RoomConnection[] Connections { get; }

    /// <summary>
    /// Dungeon-local tile coords of the entrance. The player spawns here
    /// on enter and exits when they cross this tile inbound from inside.
    /// </summary>
    public (int X, int Y) EntranceTile { get; }

    /// <summary>Width of the tile array (dungeon-local tiles).</summary>
    public int W => Tiles.GetLength(0);
    /// <summary>Height of the tile array (dungeon-local tiles).</summary>
    public int H => Tiles.GetLength(1);

    public Dungeon(
        int poiId,
        PoiType type,
        TacticalTile[,] tiles,
        Room[] rooms,
        RoomConnection[] connections,
        (int X, int Y) entranceTile)
    {
        PoiId        = poiId;
        Type         = type;
        Tiles        = tiles;
        Rooms        = rooms;
        Connections  = connections;
        EntranceTile = entranceTile;
    }
}
