"""
Convexity SDK - Compare API Key Scope Behavior

This sample creates two user-scoped API keys and compares behavior:
- Key A: org=READ, project=READ
- Key B: org=ADMIN, project=ADMIN

It then calls the same endpoints with each key to show authorization differences.

Prerequisites:
- A base API key in CONVEXITY_API_KEY with enough privilege to create/revoke API keys.
- Set CONVEXITY_ORG_SLUG and CONVEXITY_PROJECT_SLUG (or rely on defaults)
    to choose the target tenant context for token creation.
"""

from __future__ import annotations

import os
import sys

from convexity_api_client.errors import UnexpectedStatus

from convexity_sdk import ConvexityClient
from convexity_sdk.exceptions import ConvexityError, PermissionError


def run_check(label: str, fn) -> None:
    try:
        fn()
        print(f"✅ {label}: allowed")
    except UnexpectedStatus as exc:
        if exc.status_code == 403:
            print(f"⛔ {label}: denied ({exc})")
            return
        print(f"⚠️  {label}: unexpected status ({exc})")
    except PermissionError as exc:
        print(f"⛔ {label}: denied ({exc})")
    except ConvexityError as exc:
        print(f"⚠️  {label}: sdk error ({exc})")


def main() -> None:
    org_slug = os.getenv("CONVEXITY_ORG_SLUG", "convexity-sdk-samples")
    project_slug = os.getenv("CONVEXITY_PROJECT_SLUG", "griffin-it")

    owner = ConvexityClient()
    read_client: ConvexityClient | None = None
    admin_client: ConvexityClient | None = None
    read_key_id: str | None = None
    admin_key_id: str | None = None

    try:
        org = owner.organizations.get_by_slug(org_slug)
        if org is None or not hasattr(org, "id"):
            print(f'ERROR: Organization "{org_slug}" not found.', file=sys.stderr)
            raise SystemExit(1)

        project = owner.projects.get_by_slug(org.id, project_slug)
        if project is None or not hasattr(project, "id"):
            print(f'ERROR: Project "{project_slug}" not found in org "{org_slug}".', file=sys.stderr)
            raise SystemExit(1)

        print(f"Using tenant context: org={org.slug} (id={org.id}), project={project.slug} (id={project.id})")
        print("Creating demo keys...")
        read_key = owner.api_keys.create(
            name="sdk-scope-demo-read",
            scopes={"org": "READ", "project": "READ"},
        )
        admin_key = owner.api_keys.create(
            name="sdk-scope-demo-admin",
            scopes={"org": "ADMIN", "project": "ADMIN"},
        )
        read_key_id = read_key.id
        admin_key_id = admin_key.id

        print("READ key prefix:", read_key.key_prefix)
        print("ADMIN key prefix:", admin_key.key_prefix)

        read_client = ConvexityClient(api_key=read_key.key, base_url=owner.base_url)
        admin_client = ConvexityClient(api_key=admin_key.key, base_url=owner.base_url)

        print("\n--- READ-scoped key checks ---")
        run_check("READ key can list organizations", lambda: read_client.organizations.list())
        run_check("READ key can list projects", lambda: read_client.projects.list())
        run_check("READ key can list api keys (expected: denied)", lambda: read_client.api_keys.list())

        print("\n--- ADMIN-scoped key checks ---")
        run_check("ADMIN key can list organizations", lambda: admin_client.organizations.list())
        run_check("ADMIN key can list projects", lambda: admin_client.projects.list())
        run_check("ADMIN key can list api keys (expected: allowed)", lambda: admin_client.api_keys.list())
    finally:
        print("\nCleaning up demo keys...")
        if read_key_id:
            owner.api_keys.revoke(read_key_id)
        if admin_key_id:
            owner.api_keys.revoke(admin_key_id)

        if read_client is not None:
            read_client.close()
        if admin_client is not None:
            admin_client.close()
        owner.close()

    print("Done.")


if __name__ == "__main__":
    main()
