-- Fleet data model — License → Host → Instance (with optional Cluster)
--
-- ADDITIVE: existing server_connections / server_config / server_stats are
-- left untouched so the current single-server panel keeps working. The
-- host-agent consumer writes BOTH the legacy connection row and these fleet
-- tables during the transition; the panel migrates to the fleet tables in a
-- later phase.
--
-- Shape mirrors the host agent's wire protocol v2 heartbeat:
--   host{} block          → agent_hosts
--   instances[] entries   → game_instances
-- Host metrics (CPU/RAM/disk) live on the HOST, not duplicated per instance.
--
-- Named `agent_hosts` (not `hosts`) to avoid collision with the existing B2B
-- `hosts` table (hosting-partner companies) — different concept entirely.

-----------------------------------------------------------
-- AGENT_HOSTS — one Corrosion host agent / one machine
-----------------------------------------------------------
CREATE TABLE IF NOT EXISTS agent_hosts (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    license_id UUID NOT NULL REFERENCES licenses(id) ON DELETE CASCADE,
    -- Natural key until enrollment issues a stable host identity.
    hostname VARCHAR(255) NOT NULL DEFAULT '',
    agent_version VARCHAR(64),
    agent_commit VARCHAR(64),
    os VARCHAR(32),
    arch VARCHAR(32),
    status VARCHAR(20) NOT NULL DEFAULT 'offline'
        CHECK (status IN ('connected', 'degraded', 'offline')),
    last_heartbeat_at TIMESTAMPTZ,
    cpu_percent DOUBLE PRECISION,
    cpu_cores INTEGER,
    mem_total_mb BIGINT,
    mem_used_mb BIGINT,
    uptime_seconds BIGINT,
    disks JSONB,  -- [{ "mount": "/", "total_mb": n, "free_mb": n }]
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE (license_id, hostname)
);
CREATE INDEX IF NOT EXISTS idx_agent_hosts_license ON agent_hosts(license_id);

-----------------------------------------------------------
-- INSTANCE CLUSTERS — optional grouping (Soulmask main/child, Dune battlegroup)
-- Reserved now; cluster logic ships with those game adapters.
-----------------------------------------------------------
CREATE TABLE IF NOT EXISTS instance_clusters (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    license_id UUID NOT NULL REFERENCES licenses(id) ON DELETE CASCADE,
    game VARCHAR(32) NOT NULL,
    name VARCHAR(255) NOT NULL,
    topology VARCHAR(32),  -- main_client | battlegroup
    config JSONB,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_clusters_license ON instance_clusters(license_id);

-----------------------------------------------------------
-- GAME INSTANCES — one game server process / orchestrated unit.
-- The billing unit (plans count instances).
-----------------------------------------------------------
CREATE TABLE IF NOT EXISTS game_instances (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    license_id UUID NOT NULL REFERENCES licenses(id) ON DELETE CASCADE,
    host_id UUID REFERENCES agent_hosts(id) ON DELETE SET NULL,
    cluster_id UUID REFERENCES instance_clusters(id) ON DELETE SET NULL,
    -- The agent's instance slug; the NATS subject segment.
    agent_instance_id VARCHAR(64) NOT NULL,
    game VARCHAR(32) NOT NULL,
    label VARCHAR(255),
    -- running | stopped | starting | stopping | crashed
    -- | configured | missing_root | unmanaged | unknown
    state VARCHAR(32) NOT NULL DEFAULT 'unknown',
    root_path TEXT,
    uptime_seconds BIGINT NOT NULL DEFAULT 0,
    last_seen_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE (license_id, agent_instance_id)
);
CREATE INDEX IF NOT EXISTS idx_instances_license ON game_instances(license_id);
CREATE INDEX IF NOT EXISTS idx_instances_host ON game_instances(host_id);

-----------------------------------------------------------
-- INSTANCE STATS — per-instance time series (game metrics).
-- Populated once game-level telemetry (player count/FPS via RCON/plugin) is
-- collected; the host heartbeat carries host metrics, not game metrics.
-----------------------------------------------------------
CREATE TABLE IF NOT EXISTS instance_stats (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    instance_id UUID NOT NULL REFERENCES game_instances(id) ON DELETE CASCADE,
    license_id UUID NOT NULL REFERENCES licenses(id) ON DELETE CASCADE,
    player_count INTEGER NOT NULL DEFAULT 0,
    max_players INTEGER NOT NULL DEFAULT 0,
    fps DOUBLE PRECISION NOT NULL DEFAULT 0,
    memory_usage_mb INTEGER NOT NULL DEFAULT 0,
    recorded_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_instance_stats_instance
    ON instance_stats(instance_id, recorded_at DESC);
