-- =============================================================================
-- Migration: Pipeline & Stage System + Legacy roundId → stageId transition
-- =============================================================================

-- =====================================================
-- 1. NEW ENUM TYPES
-- =====================================================

DO $$ BEGIN CREATE TYPE "StageType" AS ENUM ('INTAKE', 'FILTER', 'EVALUATION', 'SELECTION', 'LIVE_FINAL', 'RESULTS'); EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN CREATE TYPE "TrackKind" AS ENUM ('MAIN', 'AWARD', 'SHOWCASE'); EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN CREATE TYPE "RoutingMode" AS ENUM ('PARALLEL', 'EXCLUSIVE', 'POST_MAIN'); EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN CREATE TYPE "StageStatus" AS ENUM ('STAGE_DRAFT', 'STAGE_ACTIVE', 'STAGE_CLOSED', 'STAGE_ARCHIVED'); EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN CREATE TYPE "ProjectStageStateValue" AS ENUM ('PENDING', 'IN_PROGRESS', 'PASSED', 'REJECTED', 'ROUTED', 'COMPLETED', 'WITHDRAWN'); EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN CREATE TYPE "DecisionMode" AS ENUM ('JURY_VOTE', 'AWARD_MASTER_DECISION', 'ADMIN_DECISION'); EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN CREATE TYPE "OverrideReasonCode" AS ENUM ('DATA_CORRECTION', 'POLICY_EXCEPTION', 'JURY_CONFLICT', 'SPONSOR_DECISION', 'ADMIN_DISCRETION'); EXCEPTION WHEN duplicate_object THEN NULL; END $$;

-- Add new values to existing UserRole enum
ALTER TYPE "UserRole" ADD VALUE IF NOT EXISTS 'AWARD_MASTER';
ALTER TYPE "UserRole" ADD VALUE IF NOT EXISTS 'AUDIENCE';

-- =====================================================
-- 2. NEW TABLES: Pipeline infrastructure
-- =====================================================

-- Pipeline
CREATE TABLE IF NOT EXISTS "Pipeline" (
    "id" TEXT NOT NULL,
    "programId" TEXT NOT NULL,
    "name" TEXT NOT NULL,
    "slug" TEXT NOT NULL,
    "status" TEXT NOT NULL DEFAULT 'DRAFT',
    "settingsJson" JSONB,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,

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

CREATE UNIQUE INDEX IF NOT EXISTS "Pipeline_slug_key" ON "Pipeline"("slug");
CREATE INDEX IF NOT EXISTS "Pipeline_programId_idx" ON "Pipeline"("programId");
CREATE INDEX IF NOT EXISTS "Pipeline_status_idx" ON "Pipeline"("status");

-- Track
CREATE TABLE IF NOT EXISTS "Track" (
    "id" TEXT NOT NULL,
    "pipelineId" TEXT NOT NULL,
    "name" TEXT NOT NULL,
    "slug" TEXT NOT NULL,
    "kind" "TrackKind" NOT NULL DEFAULT 'MAIN',
    "routingMode" "RoutingMode",
    "decisionMode" "DecisionMode",
    "sortOrder" INTEGER NOT NULL DEFAULT 0,
    "settingsJson" JSONB,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,

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

CREATE UNIQUE INDEX IF NOT EXISTS "Track_pipelineId_slug_key" ON "Track"("pipelineId", "slug");
CREATE UNIQUE INDEX IF NOT EXISTS "Track_pipelineId_sortOrder_key" ON "Track"("pipelineId", "sortOrder");
CREATE INDEX IF NOT EXISTS "Track_pipelineId_idx" ON "Track"("pipelineId");
CREATE INDEX IF NOT EXISTS "Track_kind_idx" ON "Track"("kind");

-- Stage
CREATE TABLE IF NOT EXISTS "Stage" (
    "id" TEXT NOT NULL,
    "trackId" TEXT NOT NULL,
    "stageType" "StageType" NOT NULL,
    "name" TEXT NOT NULL,
    "slug" TEXT NOT NULL,
    "status" "StageStatus" NOT NULL DEFAULT 'STAGE_DRAFT',
    "sortOrder" INTEGER NOT NULL DEFAULT 0,
    "configJson" JSONB,
    "windowOpenAt" TIMESTAMP(3),
    "windowCloseAt" TIMESTAMP(3),
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,

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

CREATE UNIQUE INDEX IF NOT EXISTS "Stage_trackId_slug_key" ON "Stage"("trackId", "slug");
CREATE UNIQUE INDEX IF NOT EXISTS "Stage_trackId_sortOrder_key" ON "Stage"("trackId", "sortOrder");
CREATE INDEX IF NOT EXISTS "Stage_trackId_idx" ON "Stage"("trackId");
CREATE INDEX IF NOT EXISTS "Stage_stageType_idx" ON "Stage"("stageType");
CREATE INDEX IF NOT EXISTS "Stage_status_idx" ON "Stage"("status");

-- StageTransition
CREATE TABLE IF NOT EXISTS "StageTransition" (
    "id" TEXT NOT NULL,
    "fromStageId" TEXT NOT NULL,
    "toStageId" TEXT NOT NULL,
    "isDefault" BOOLEAN NOT NULL DEFAULT false,
    "guardJson" JSONB,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

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

CREATE UNIQUE INDEX IF NOT EXISTS "StageTransition_fromStageId_toStageId_key" ON "StageTransition"("fromStageId", "toStageId");
CREATE INDEX IF NOT EXISTS "StageTransition_fromStageId_idx" ON "StageTransition"("fromStageId");
CREATE INDEX IF NOT EXISTS "StageTransition_toStageId_idx" ON "StageTransition"("toStageId");

-- ProjectStageState
CREATE TABLE IF NOT EXISTS "ProjectStageState" (
    "id" TEXT NOT NULL,
    "projectId" TEXT NOT NULL,
    "trackId" TEXT NOT NULL,
    "stageId" TEXT NOT NULL,
    "state" "ProjectStageStateValue" NOT NULL DEFAULT 'PENDING',
    "enteredAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "exitedAt" TIMESTAMP(3),
    "metadataJson" JSONB,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,

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

CREATE UNIQUE INDEX IF NOT EXISTS "ProjectStageState_projectId_trackId_stageId_key" ON "ProjectStageState"("projectId", "trackId", "stageId");
CREATE INDEX IF NOT EXISTS "ProjectStageState_projectId_idx" ON "ProjectStageState"("projectId");
CREATE INDEX IF NOT EXISTS "ProjectStageState_trackId_idx" ON "ProjectStageState"("trackId");
CREATE INDEX IF NOT EXISTS "ProjectStageState_stageId_idx" ON "ProjectStageState"("stageId");
CREATE INDEX IF NOT EXISTS "ProjectStageState_state_idx" ON "ProjectStageState"("state");
CREATE INDEX IF NOT EXISTS "ProjectStageState_projectId_trackId_idx" ON "ProjectStageState"("projectId", "trackId");

-- RoutingRule
CREATE TABLE IF NOT EXISTS "RoutingRule" (
    "id" TEXT NOT NULL,
    "pipelineId" TEXT NOT NULL,
    "name" TEXT NOT NULL,
    "scope" TEXT NOT NULL DEFAULT 'global',
    "sourceTrackId" TEXT,
    "destinationTrackId" TEXT NOT NULL,
    "destinationStageId" TEXT,
    "predicateJson" JSONB NOT NULL,
    "priority" INTEGER NOT NULL DEFAULT 0,
    "isActive" BOOLEAN NOT NULL DEFAULT true,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,

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

CREATE INDEX IF NOT EXISTS "RoutingRule_pipelineId_idx" ON "RoutingRule"("pipelineId");
CREATE INDEX IF NOT EXISTS "RoutingRule_priority_idx" ON "RoutingRule"("priority");
CREATE INDEX IF NOT EXISTS "RoutingRule_isActive_idx" ON "RoutingRule"("isActive");

-- Cohort
CREATE TABLE IF NOT EXISTS "Cohort" (
    "id" TEXT NOT NULL,
    "stageId" TEXT NOT NULL,
    "name" TEXT NOT NULL,
    "votingMode" TEXT NOT NULL DEFAULT 'simple',
    "isOpen" BOOLEAN NOT NULL DEFAULT false,
    "windowOpenAt" TIMESTAMP(3),
    "windowCloseAt" TIMESTAMP(3),
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,

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

CREATE INDEX IF NOT EXISTS "Cohort_stageId_idx" ON "Cohort"("stageId");
CREATE INDEX IF NOT EXISTS "Cohort_isOpen_idx" ON "Cohort"("isOpen");

-- CohortProject
CREATE TABLE IF NOT EXISTS "CohortProject" (
    "id" TEXT NOT NULL,
    "cohortId" TEXT NOT NULL,
    "projectId" TEXT NOT NULL,
    "sortOrder" INTEGER NOT NULL DEFAULT 0,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

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

CREATE UNIQUE INDEX IF NOT EXISTS "CohortProject_cohortId_projectId_key" ON "CohortProject"("cohortId", "projectId");
CREATE INDEX IF NOT EXISTS "CohortProject_cohortId_idx" ON "CohortProject"("cohortId");
CREATE INDEX IF NOT EXISTS "CohortProject_projectId_idx" ON "CohortProject"("projectId");
CREATE INDEX IF NOT EXISTS "CohortProject_sortOrder_idx" ON "CohortProject"("sortOrder");

-- LiveProgressCursor
CREATE TABLE IF NOT EXISTS "LiveProgressCursor" (
    "id" TEXT NOT NULL,
    "stageId" TEXT NOT NULL,
    "sessionId" TEXT NOT NULL,
    "activeProjectId" TEXT,
    "activeOrderIndex" INTEGER NOT NULL DEFAULT 0,
    "isPaused" BOOLEAN NOT NULL DEFAULT false,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,

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

CREATE UNIQUE INDEX IF NOT EXISTS "LiveProgressCursor_stageId_key" ON "LiveProgressCursor"("stageId");
CREATE UNIQUE INDEX IF NOT EXISTS "LiveProgressCursor_sessionId_key" ON "LiveProgressCursor"("sessionId");
CREATE INDEX IF NOT EXISTS "LiveProgressCursor_sessionId_idx" ON "LiveProgressCursor"("sessionId");

-- OverrideAction
CREATE TABLE IF NOT EXISTS "OverrideAction" (
    "id" TEXT NOT NULL,
    "entityType" TEXT NOT NULL,
    "entityId" TEXT NOT NULL,
    "previousValue" JSONB,
    "newValueJson" JSONB NOT NULL,
    "reasonCode" "OverrideReasonCode" NOT NULL,
    "reasonText" TEXT,
    "actorId" TEXT NOT NULL,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

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

CREATE INDEX IF NOT EXISTS "OverrideAction_entityType_entityId_idx" ON "OverrideAction"("entityType", "entityId");
CREATE INDEX IF NOT EXISTS "OverrideAction_actorId_idx" ON "OverrideAction"("actorId");
CREATE INDEX IF NOT EXISTS "OverrideAction_reasonCode_idx" ON "OverrideAction"("reasonCode");
CREATE INDEX IF NOT EXISTS "OverrideAction_createdAt_idx" ON "OverrideAction"("createdAt");

-- DecisionAuditLog
CREATE TABLE IF NOT EXISTS "DecisionAuditLog" (
    "id" TEXT NOT NULL,
    "eventType" TEXT NOT NULL,
    "entityType" TEXT NOT NULL,
    "entityId" TEXT NOT NULL,
    "actorId" TEXT,
    "detailsJson" JSONB,
    "snapshotJson" JSONB,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,

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

CREATE INDEX IF NOT EXISTS "DecisionAuditLog_eventType_idx" ON "DecisionAuditLog"("eventType");
CREATE INDEX IF NOT EXISTS "DecisionAuditLog_entityType_entityId_idx" ON "DecisionAuditLog"("entityType", "entityId");
CREATE INDEX IF NOT EXISTS "DecisionAuditLog_actorId_idx" ON "DecisionAuditLog"("actorId");
CREATE INDEX IF NOT EXISTS "DecisionAuditLog_createdAt_idx" ON "DecisionAuditLog"("createdAt");

-- NotificationPolicy
CREATE TABLE IF NOT EXISTS "NotificationPolicy" (
    "id" TEXT NOT NULL,
    "eventType" TEXT NOT NULL,
    "channel" TEXT NOT NULL DEFAULT 'EMAIL',
    "templateId" TEXT,
    "isActive" BOOLEAN NOT NULL DEFAULT true,
    "configJson" JSONB,
    "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updatedAt" TIMESTAMP(3) NOT NULL,

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

CREATE UNIQUE INDEX IF NOT EXISTS "NotificationPolicy_eventType_key" ON "NotificationPolicy"("eventType");
CREATE INDEX IF NOT EXISTS "NotificationPolicy_eventType_idx" ON "NotificationPolicy"("eventType");
CREATE INDEX IF NOT EXISTS "NotificationPolicy_isActive_idx" ON "NotificationPolicy"("isActive");

-- =====================================================
-- 3. DROP roundId FK constraints (roundId is now a raw legacy field)
-- =====================================================

ALTER TABLE "EvaluationForm" DROP CONSTRAINT IF EXISTS "EvaluationForm_roundId_fkey";
ALTER TABLE "Assignment" DROP CONSTRAINT IF EXISTS "Assignment_roundId_fkey";
ALTER TABLE "GracePeriod" DROP CONSTRAINT IF EXISTS "GracePeriod_roundId_fkey";
ALTER TABLE "FileRequirement" DROP CONSTRAINT IF EXISTS "FileRequirement_roundId_fkey";
ALTER TABLE "FilteringRule" DROP CONSTRAINT IF EXISTS "FilteringRule_roundId_fkey";
ALTER TABLE "FilteringResult" DROP CONSTRAINT IF EXISTS "FilteringResult_roundId_fkey";
ALTER TABLE "FilteringJob" DROP CONSTRAINT IF EXISTS "FilteringJob_roundId_fkey";
ALTER TABLE "AssignmentJob" DROP CONSTRAINT IF EXISTS "AssignmentJob_roundId_fkey";
ALTER TABLE "ReminderLog" DROP CONSTRAINT IF EXISTS "ReminderLog_roundId_fkey";
ALTER TABLE "ConflictOfInterest" DROP CONSTRAINT IF EXISTS "ConflictOfInterest_roundId_fkey";
ALTER TABLE "EvaluationSummary" DROP CONSTRAINT IF EXISTS "EvaluationSummary_roundId_fkey";
ALTER TABLE "EvaluationDiscussion" DROP CONSTRAINT IF EXISTS "EvaluationDiscussion_roundId_fkey";
ALTER TABLE "LiveVotingSession" DROP CONSTRAINT IF EXISTS "LiveVotingSession_roundId_fkey";
ALTER TABLE "Project" DROP CONSTRAINT IF EXISTS "Project_roundId_fkey";
ALTER TABLE "ProjectFile" DROP CONSTRAINT IF EXISTS "ProjectFile_roundId_fkey";
ALTER TABLE "TaggingJob" DROP CONSTRAINT IF EXISTS "TaggingJob_roundId_fkey";
ALTER TABLE "Message" DROP CONSTRAINT IF EXISTS "Message_roundId_fkey";

-- Make TaggingJob.roundId nullable
DO $$ BEGIN ALTER TABLE "TaggingJob" ALTER COLUMN "roundId" DROP NOT NULL; EXCEPTION WHEN others THEN NULL; END $$;

-- Drop Round and RoundTemplate tables and their enums (models retired in Phase 6)
DROP TABLE IF EXISTS "RoundTemplate" CASCADE;
DROP TABLE IF EXISTS "Round" CASCADE;
DROP TYPE IF EXISTS "RoundStatus";
DROP TYPE IF EXISTS "RoundType";

-- =====================================================
-- 4. ALTER EXISTING TABLES: Make roundId nullable, add stageId
-- =====================================================

-- EvaluationForm: roundId NOT NULL → nullable, add stageId NOT NULL
DO $$ BEGIN ALTER TABLE "EvaluationForm" ALTER COLUMN "roundId" DROP NOT NULL; EXCEPTION WHEN others THEN NULL; END $$;
ALTER TABLE "EvaluationForm" ADD COLUMN IF NOT EXISTS "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
DO $$ BEGIN ALTER TABLE "EvaluationForm" ALTER COLUMN "stageId" DROP DEFAULT; EXCEPTION WHEN others THEN NULL; END $$;
DROP INDEX IF EXISTS "EvaluationForm_roundId_version_key";
CREATE UNIQUE INDEX IF NOT EXISTS "EvaluationForm_stageId_version_key" ON "EvaluationForm"("stageId", "version");
CREATE INDEX IF NOT EXISTS "EvaluationForm_stageId_isActive_idx" ON "EvaluationForm"("stageId", "isActive");

-- Assignment: roundId NOT NULL → nullable, add stageId NOT NULL
DO $$ BEGIN ALTER TABLE "Assignment" ALTER COLUMN "roundId" DROP NOT NULL; EXCEPTION WHEN others THEN NULL; END $$;
ALTER TABLE "Assignment" ADD COLUMN IF NOT EXISTS "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
DO $$ BEGIN ALTER TABLE "Assignment" ALTER COLUMN "stageId" DROP DEFAULT; EXCEPTION WHEN others THEN NULL; END $$;
DROP INDEX IF EXISTS "Assignment_userId_projectId_roundId_key";
CREATE UNIQUE INDEX IF NOT EXISTS "Assignment_userId_projectId_stageId_key" ON "Assignment"("userId", "projectId", "stageId");
CREATE INDEX IF NOT EXISTS "Assignment_stageId_idx" ON "Assignment"("stageId");

-- GracePeriod: roundId NOT NULL → nullable, add stageId NOT NULL
DO $$ BEGIN ALTER TABLE "GracePeriod" ALTER COLUMN "roundId" DROP NOT NULL; EXCEPTION WHEN others THEN NULL; END $$;
ALTER TABLE "GracePeriod" ADD COLUMN IF NOT EXISTS "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
DO $$ BEGIN ALTER TABLE "GracePeriod" ALTER COLUMN "stageId" DROP DEFAULT; EXCEPTION WHEN others THEN NULL; END $$;
CREATE INDEX IF NOT EXISTS "GracePeriod_stageId_idx" ON "GracePeriod"("stageId");
CREATE INDEX IF NOT EXISTS "GracePeriod_stageId_userId_extendedUntil_idx" ON "GracePeriod"("stageId", "userId", "extendedUntil");

-- FileRequirement: roundId NOT NULL → nullable, add stageId NOT NULL
DO $$ BEGIN ALTER TABLE "FileRequirement" ALTER COLUMN "roundId" DROP NOT NULL; EXCEPTION WHEN others THEN NULL; END $$;
ALTER TABLE "FileRequirement" ADD COLUMN IF NOT EXISTS "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
DO $$ BEGIN ALTER TABLE "FileRequirement" ALTER COLUMN "stageId" DROP DEFAULT; EXCEPTION WHEN others THEN NULL; END $$;
CREATE INDEX IF NOT EXISTS "FileRequirement_stageId_idx" ON "FileRequirement"("stageId");

-- FilteringRule: roundId NOT NULL → nullable, add stageId NOT NULL
DO $$ BEGIN ALTER TABLE "FilteringRule" ALTER COLUMN "roundId" DROP NOT NULL; EXCEPTION WHEN others THEN NULL; END $$;
ALTER TABLE "FilteringRule" ADD COLUMN IF NOT EXISTS "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
DO $$ BEGIN ALTER TABLE "FilteringRule" ALTER COLUMN "stageId" DROP DEFAULT; EXCEPTION WHEN others THEN NULL; END $$;
CREATE INDEX IF NOT EXISTS "FilteringRule_stageId_idx" ON "FilteringRule"("stageId");

-- FilteringResult: roundId NOT NULL → nullable, add stageId NOT NULL
DO $$ BEGIN ALTER TABLE "FilteringResult" ALTER COLUMN "roundId" DROP NOT NULL; EXCEPTION WHEN others THEN NULL; END $$;
ALTER TABLE "FilteringResult" ADD COLUMN IF NOT EXISTS "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
DO $$ BEGIN ALTER TABLE "FilteringResult" ALTER COLUMN "stageId" DROP DEFAULT; EXCEPTION WHEN others THEN NULL; END $$;
DROP INDEX IF EXISTS "FilteringResult_roundId_projectId_key";
CREATE UNIQUE INDEX IF NOT EXISTS "FilteringResult_stageId_projectId_key" ON "FilteringResult"("stageId", "projectId");
CREATE INDEX IF NOT EXISTS "FilteringResult_stageId_idx" ON "FilteringResult"("stageId");

-- FilteringJob: roundId NOT NULL → nullable, add stageId NOT NULL
DO $$ BEGIN ALTER TABLE "FilteringJob" ALTER COLUMN "roundId" DROP NOT NULL; EXCEPTION WHEN others THEN NULL; END $$;
ALTER TABLE "FilteringJob" ADD COLUMN IF NOT EXISTS "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
DO $$ BEGIN ALTER TABLE "FilteringJob" ALTER COLUMN "stageId" DROP DEFAULT; EXCEPTION WHEN others THEN NULL; END $$;
CREATE INDEX IF NOT EXISTS "FilteringJob_stageId_idx" ON "FilteringJob"("stageId");

-- AssignmentJob: roundId NOT NULL → nullable, add stageId NOT NULL
DO $$ BEGIN ALTER TABLE "AssignmentJob" ALTER COLUMN "roundId" DROP NOT NULL; EXCEPTION WHEN others THEN NULL; END $$;
ALTER TABLE "AssignmentJob" ADD COLUMN IF NOT EXISTS "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
DO $$ BEGIN ALTER TABLE "AssignmentJob" ALTER COLUMN "stageId" DROP DEFAULT; EXCEPTION WHEN others THEN NULL; END $$;
CREATE INDEX IF NOT EXISTS "AssignmentJob_stageId_idx" ON "AssignmentJob"("stageId");

-- ReminderLog: roundId NOT NULL → nullable, add stageId NOT NULL
DO $$ BEGIN ALTER TABLE "ReminderLog" ALTER COLUMN "roundId" DROP NOT NULL; EXCEPTION WHEN others THEN NULL; END $$;
ALTER TABLE "ReminderLog" ADD COLUMN IF NOT EXISTS "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
DO $$ BEGIN ALTER TABLE "ReminderLog" ALTER COLUMN "stageId" DROP DEFAULT; EXCEPTION WHEN others THEN NULL; END $$;
DROP INDEX IF EXISTS "ReminderLog_roundId_userId_type_key";
CREATE UNIQUE INDEX IF NOT EXISTS "ReminderLog_stageId_userId_type_key" ON "ReminderLog"("stageId", "userId", "type");
CREATE INDEX IF NOT EXISTS "ReminderLog_stageId_idx" ON "ReminderLog"("stageId");

-- ConflictOfInterest: roundId NOT NULL → nullable (no stageId on this table)
DO $$ BEGIN ALTER TABLE "ConflictOfInterest" ALTER COLUMN "roundId" DROP NOT NULL; EXCEPTION WHEN others THEN NULL; END $$;

-- EvaluationSummary: roundId NOT NULL → nullable, add stageId NOT NULL
DO $$ BEGIN ALTER TABLE "EvaluationSummary" ALTER COLUMN "roundId" DROP NOT NULL; EXCEPTION WHEN others THEN NULL; END $$;
ALTER TABLE "EvaluationSummary" ADD COLUMN IF NOT EXISTS "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
DO $$ BEGIN ALTER TABLE "EvaluationSummary" ALTER COLUMN "stageId" DROP DEFAULT; EXCEPTION WHEN others THEN NULL; END $$;
DROP INDEX IF EXISTS "EvaluationSummary_projectId_roundId_key";
CREATE UNIQUE INDEX IF NOT EXISTS "EvaluationSummary_projectId_stageId_key" ON "EvaluationSummary"("projectId", "stageId");
CREATE INDEX IF NOT EXISTS "EvaluationSummary_stageId_idx" ON "EvaluationSummary"("stageId");

-- EvaluationDiscussion: roundId NOT NULL → nullable, add stageId NOT NULL
DO $$ BEGIN ALTER TABLE "EvaluationDiscussion" ALTER COLUMN "roundId" DROP NOT NULL; EXCEPTION WHEN others THEN NULL; END $$;
ALTER TABLE "EvaluationDiscussion" ADD COLUMN IF NOT EXISTS "stageId" TEXT NOT NULL DEFAULT '__placeholder__';
DO $$ BEGIN ALTER TABLE "EvaluationDiscussion" ALTER COLUMN "stageId" DROP DEFAULT; EXCEPTION WHEN others THEN NULL; END $$;
DROP INDEX IF EXISTS "EvaluationDiscussion_projectId_roundId_key";
CREATE UNIQUE INDEX IF NOT EXISTS "EvaluationDiscussion_projectId_stageId_key" ON "EvaluationDiscussion"("projectId", "stageId");
CREATE INDEX IF NOT EXISTS "EvaluationDiscussion_stageId_idx" ON "EvaluationDiscussion"("stageId");

-- Message: add stageId (nullable)
ALTER TABLE "Message" ADD COLUMN IF NOT EXISTS "stageId" TEXT;
CREATE INDEX IF NOT EXISTS "Message_stageId_idx" ON "Message"("stageId");

-- LiveVotingSession: roundId NOT NULL → nullable, add stageId (nullable, unique)
DO $$ BEGIN ALTER TABLE "LiveVotingSession" ALTER COLUMN "roundId" DROP NOT NULL; EXCEPTION WHEN others THEN NULL; END $$;
ALTER TABLE "LiveVotingSession" ADD COLUMN IF NOT EXISTS "stageId" TEXT;
CREATE UNIQUE INDEX IF NOT EXISTS "LiveVotingSession_stageId_key" ON "LiveVotingSession"("stageId");

-- =====================================================
-- 5. FOREIGN KEY CONSTRAINTS: New tables
-- =====================================================

DO $$ BEGIN ALTER TABLE "Pipeline" ADD CONSTRAINT "Pipeline_programId_fkey" FOREIGN KEY ("programId") REFERENCES "Program"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "Track" ADD CONSTRAINT "Track_pipelineId_fkey" FOREIGN KEY ("pipelineId") REFERENCES "Pipeline"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "Stage" ADD CONSTRAINT "Stage_trackId_fkey" FOREIGN KEY ("trackId") REFERENCES "Track"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "StageTransition" ADD CONSTRAINT "StageTransition_fromStageId_fkey" FOREIGN KEY ("fromStageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "StageTransition" ADD CONSTRAINT "StageTransition_toStageId_fkey" FOREIGN KEY ("toStageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "ProjectStageState" ADD CONSTRAINT "ProjectStageState_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "ProjectStageState" ADD CONSTRAINT "ProjectStageState_trackId_fkey" FOREIGN KEY ("trackId") REFERENCES "Track"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "ProjectStageState" ADD CONSTRAINT "ProjectStageState_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "RoutingRule" ADD CONSTRAINT "RoutingRule_pipelineId_fkey" FOREIGN KEY ("pipelineId") REFERENCES "Pipeline"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "RoutingRule" ADD CONSTRAINT "RoutingRule_sourceTrackId_fkey" FOREIGN KEY ("sourceTrackId") REFERENCES "Track"("id") ON DELETE SET NULL ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "RoutingRule" ADD CONSTRAINT "RoutingRule_destinationTrackId_fkey" FOREIGN KEY ("destinationTrackId") REFERENCES "Track"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "Cohort" ADD CONSTRAINT "Cohort_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "CohortProject" ADD CONSTRAINT "CohortProject_cohortId_fkey" FOREIGN KEY ("cohortId") REFERENCES "Cohort"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "CohortProject" ADD CONSTRAINT "CohortProject_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "LiveProgressCursor" ADD CONSTRAINT "LiveProgressCursor_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;

-- =====================================================
-- 6. FOREIGN KEY CONSTRAINTS: stageId on altered tables
-- =====================================================

DO $$ BEGIN ALTER TABLE "EvaluationForm" ADD CONSTRAINT "EvaluationForm_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "Assignment" ADD CONSTRAINT "Assignment_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "GracePeriod" ADD CONSTRAINT "GracePeriod_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "FileRequirement" ADD CONSTRAINT "FileRequirement_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "FilteringRule" ADD CONSTRAINT "FilteringRule_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "FilteringResult" ADD CONSTRAINT "FilteringResult_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "FilteringJob" ADD CONSTRAINT "FilteringJob_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "AssignmentJob" ADD CONSTRAINT "AssignmentJob_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "ReminderLog" ADD CONSTRAINT "ReminderLog_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "EvaluationSummary" ADD CONSTRAINT "EvaluationSummary_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "EvaluationDiscussion" ADD CONSTRAINT "EvaluationDiscussion_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "Message" ADD CONSTRAINT "Message_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE SET NULL ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
DO $$ BEGIN ALTER TABLE "LiveVotingSession" ADD CONSTRAINT "LiveVotingSession_stageId_fkey" FOREIGN KEY ("stageId") REFERENCES "Stage"("id") ON DELETE CASCADE ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;

-- =====================================================
-- 7. SpecialAward: add trackId (nullable, unique)
-- =====================================================

ALTER TABLE "SpecialAward" ADD COLUMN IF NOT EXISTS "trackId" TEXT;
CREATE UNIQUE INDEX IF NOT EXISTS "SpecialAward_trackId_key" ON "SpecialAward"("trackId");
DO $$ BEGIN ALTER TABLE "SpecialAward" ADD CONSTRAINT "SpecialAward_trackId_fkey" FOREIGN KEY ("trackId") REFERENCES "Track"("id") ON DELETE SET NULL ON UPDATE CASCADE; EXCEPTION WHEN duplicate_object THEN NULL; END $$;
