-- Phase 2: Game server lifecycle and node enrollment

-- New enums
DO $$ BEGIN
  CREATE TYPE "ServerEdition" AS ENUM ('JAVA', 'BEDROCK');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE "SoftwareFamily" AS ENUM ('VANILLA', 'PAPER', 'PURPUR', 'FABRIC', 'FORGE', 'NEOFORGE', 'QUILT', 'BEDROCK_DEDICATED');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  CREATE TYPE "AllocationStatus" AS ENUM ('ACTIVE', 'RELEASED');
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

-- Extend GameNodeStatus
ALTER TYPE "GameNodeStatus" ADD VALUE IF NOT EXISTS 'UNREACHABLE';

-- Game servers: add columns
ALTER TABLE "game_servers" ADD COLUMN IF NOT EXISTS "edition" "ServerEdition" NOT NULL DEFAULT 'JAVA';
ALTER TABLE "game_servers" ADD COLUMN IF NOT EXISTS "softwareFamily" "SoftwareFamily" NOT NULL DEFAULT 'VANILLA';
ALTER TABLE "game_servers" ADD COLUMN IF NOT EXISTS "minecraftVersion" TEXT NOT NULL DEFAULT '1.21.1';
ALTER TABLE "game_servers" ADD COLUMN IF NOT EXISTS "eulaAccepted" BOOLEAN NOT NULL DEFAULT false;
ALTER TABLE "game_servers" ADD COLUMN IF NOT EXISTS "hostPort" INTEGER;
ALTER TABLE "game_servers" ADD COLUMN IF NOT EXISTS "containerId" TEXT;
ALTER TABLE "game_servers" ADD COLUMN IF NOT EXISTS "dataPath" TEXT;
ALTER TABLE "game_servers" ADD COLUMN IF NOT EXISTS "ramMb" INTEGER NOT NULL DEFAULT 1024;

-- Game nodes: enrollment + heartbeat
ALTER TABLE "game_nodes" ADD COLUMN IF NOT EXISTS "lastHeartbeatAt" TIMESTAMPTZ(3);
ALTER TABLE "game_nodes" ADD COLUMN IF NOT EXISTS "agentVersion" TEXT;
ALTER TABLE "game_nodes" ADD COLUMN IF NOT EXISTS "enrollmentTokenHash" TEXT;
ALTER TABLE "game_nodes" ADD COLUMN IF NOT EXISTS "enrolledAt" TIMESTAMPTZ(3);

-- State transitions: audit fields
ALTER TABLE "game_server_state_transitions" ADD COLUMN IF NOT EXISTS "correlationId" TEXT;
ALTER TABLE "game_server_state_transitions" ADD COLUMN IF NOT EXISTS "actorId" TEXT;
ALTER TABLE "game_server_state_transitions" ADD COLUMN IF NOT EXISTS "errorCode" TEXT;
ALTER TABLE "game_server_state_transitions" ADD COLUMN IF NOT EXISTS "errorMessage" TEXT;

-- Allocations
CREATE TABLE IF NOT EXISTS "game_server_allocations" (
    "id" TEXT NOT NULL,
    "serverId" TEXT NOT NULL,
    "nodeId" TEXT NOT NULL,
    "hostPort" INTEGER NOT NULL,
    "ramMbReserved" INTEGER NOT NULL,
    "status" "AllocationStatus" NOT NULL DEFAULT 'ACTIVE',
    "createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMPTZ(3) NOT NULL,

    CONSTRAINT "game_server_allocations_pkey" PRIMARY KEY ("id")
);

CREATE UNIQUE INDEX IF NOT EXISTS "game_server_allocations_serverId_key" ON "game_server_allocations"("serverId");
CREATE UNIQUE INDEX IF NOT EXISTS "game_server_allocations_nodeId_hostPort_key" ON "game_server_allocations"("nodeId", "hostPort");
CREATE INDEX IF NOT EXISTS "game_server_allocations_nodeId_idx" ON "game_server_allocations"("nodeId");

DO $$ BEGIN
  ALTER TABLE "game_server_allocations" ADD CONSTRAINT "game_server_allocations_serverId_fkey" FOREIGN KEY ("serverId") REFERENCES "game_servers"("id") ON DELETE CASCADE ON UPDATE CASCADE;
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

DO $$ BEGIN
  ALTER TABLE "game_server_allocations" ADD CONSTRAINT "game_server_allocations_nodeId_fkey" FOREIGN KEY ("nodeId") REFERENCES "game_nodes"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

-- Free plan seed
INSERT INTO "plans" ("id", "name", "slug", "description", "isFree", "isActive", "maxRamMb", "maxCpuCores", "maxStorageMb", "createdAt", "updatedAt")
SELECT gen_random_uuid()::text, 'Free', 'free', 'Free tier with limited resources', true, true, 2048, 1, 5120, NOW(), NOW()
WHERE NOT EXISTS (SELECT 1 FROM "plans" WHERE "slug" = 'free');
