CREATE TABLE IF NOT EXISTS release_versions (
    id UUID PRIMARY KEY,
    cluster_id UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
    product TEXT NOT NULL,
    version TEXT NOT NULL,
    channel TEXT NOT NULL DEFAULT 'dev',
    status TEXT NOT NULL DEFAULT 'active',
    compatibility JSONB NOT NULL DEFAULT '{}'::jsonb,
    changelog TEXT,
    created_by_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    authority_payload JSONB NOT NULL DEFAULT '{}'::jsonb,
    authority_signature JSONB NOT NULL DEFAULT '{}'::jsonb,
    UNIQUE (cluster_id, product, version, channel)
);

CREATE TABLE IF NOT EXISTS release_artifacts (
    id UUID PRIMARY KEY,
    release_id UUID NOT NULL REFERENCES release_versions(id) ON DELETE CASCADE,
    cluster_id UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
    product TEXT NOT NULL,
    version TEXT NOT NULL,
    os TEXT NOT NULL,
    arch TEXT NOT NULL,
    install_type TEXT NOT NULL,
    kind TEXT NOT NULL,
    url TEXT NOT NULL,
    sha256 TEXT NOT NULL,
    size_bytes BIGINT NOT NULL DEFAULT 0,
    signature TEXT,
    metadata JSONB NOT NULL DEFAULT '{}'::jsonb,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    UNIQUE (release_id, os, arch, install_type, kind)
);

CREATE TABLE IF NOT EXISTS node_update_desired_policies (
    cluster_id UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
    node_id UUID NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,
    product TEXT NOT NULL,
    channel TEXT NOT NULL DEFAULT 'dev',
    target_version TEXT,
    strategy TEXT NOT NULL DEFAULT 'manual',
    enabled BOOLEAN NOT NULL DEFAULT false,
    rollback_allowed BOOLEAN NOT NULL DEFAULT true,
    health_window_seconds INTEGER NOT NULL DEFAULT 180,
    updated_by_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    PRIMARY KEY (cluster_id, node_id, product)
);

CREATE TABLE IF NOT EXISTS node_update_status_reports (
    id UUID PRIMARY KEY,
    cluster_id UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
    node_id UUID NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,
    product TEXT NOT NULL,
    current_version TEXT NOT NULL DEFAULT '',
    target_version TEXT NOT NULL DEFAULT '',
    phase TEXT NOT NULL,
    status TEXT NOT NULL,
    attempt_id TEXT NOT NULL DEFAULT '',
    error_message TEXT,
    rollback_version TEXT,
    payload JSONB NOT NULL DEFAULT '{}'::jsonb,
    observed_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS release_versions_lookup_idx
    ON release_versions (cluster_id, product, channel, status, created_at DESC);

CREATE INDEX IF NOT EXISTS release_artifacts_match_idx
    ON release_artifacts (release_id, os, arch, install_type);

CREATE INDEX IF NOT EXISTS node_update_status_reports_latest_idx
    ON node_update_status_reports (cluster_id, node_id, product, observed_at DESC);
