"""Migration 030 — the global-scope grant (§22 three-tier S3).

Proves: `memberships.scope_type` now admits 'global' alongside 'project' and
'collection' (§B.2's four-layer resolver), existing rows survive the rebuild,
and the UNIQUE(scope_type, scope_id, user_id) shape is preserved.
Template: test_migration_029_collections.py.
"""
from __future__ import annotations

import sqlite3
import tempfile
from pathlib import Path

import pytest

from app import db


class _Cfg:
    def __init__(self, path):
        self.database_path = path


def _fresh_db():
    d = tempfile.mkdtemp()
    path = Path(d) / "t.db"
    db.run_migrations(_Cfg(str(path)))
    return db.connect(str(path))


def _add_user(conn, uid, login):
    conn.execute(
        "INSERT INTO users (id, gitea_id, gitea_login, display_name, role) "
        "VALUES (?, ?, ?, ?, 'contributor')",
        (uid, uid, login, login.capitalize()),
    )


def test_global_scope_type_is_accepted():
    conn = _fresh_db()
    _add_user(conn, 1, "cleo")
    # global grant — the new tier — is accepted.
    conn.execute(
        "INSERT INTO memberships (scope_type, scope_id, user_id, role) "
        "VALUES ('global', '*', 1, 'contributor')"
    )
    row = conn.execute(
        "SELECT scope_type, scope_id, role FROM memberships WHERE user_id = 1"
    ).fetchone()
    assert row["scope_type"] == "global"
    assert row["scope_id"] == "*"
    assert row["role"] == "contributor"


def test_project_and_collection_scopes_still_accepted():
    conn = _fresh_db()
    _add_user(conn, 1, "ben")
    conn.execute(
        "INSERT INTO memberships (scope_type, scope_id, user_id, role) "
        "VALUES ('project', 'default', 1, 'owner')"
    )
    conn.execute(
        "INSERT INTO memberships (scope_type, scope_id, user_id, role) "
        "VALUES ('collection', 'default', 1, 'contributor')"
    )
    n = conn.execute("SELECT COUNT(*) AS n FROM memberships WHERE user_id = 1").fetchone()["n"]
    assert n == 2


def test_unknown_scope_type_still_rejected():
    conn = _fresh_db()
    _add_user(conn, 1, "x")
    with pytest.raises(sqlite3.IntegrityError):
        conn.execute(
            "INSERT INTO memberships (scope_type, scope_id, user_id, role) "
            "VALUES ('deployment', '*', 1, 'owner')"
        )


def test_one_global_grant_per_user():
    conn = _fresh_db()
    _add_user(conn, 1, "cleo")
    conn.execute(
        "INSERT INTO memberships (scope_type, scope_id, user_id, role) "
        "VALUES ('global', '*', 1, 'contributor')"
    )
    with pytest.raises(sqlite3.IntegrityError):
        conn.execute(
            "INSERT INTO memberships (scope_type, scope_id, user_id, role) "
            "VALUES ('global', '*', 1, 'owner')"
        )
