# -*- coding: utf-8 -*-
# Copyright (c) 2025 ContextForge Contributors.
# SPDX-License-Identifier: Apache-2.0

"""Location: ./tests/playwright/security/test_sso_management.py
Copyright 2026
SPDX-License-Identifier: Apache-2.0
Authors: Mihai Criveti

SSO Provider Management E2E Tests.

Tests SSO provider CRUD operations through the /auth/sso/admin REST API.
These tests are skipped if SSO endpoints are not available in the test environment.
"""

# Future
from __future__ import annotations

# Standard
import logging
import uuid

# Third-Party
from playwright.sync_api import APIRequestContext
import pytest

logger = logging.getLogger(__name__)

SSO_ADMIN_PATH = "/auth/sso/admin/providers"


def _make_provider_data(provider_id: str | None = None) -> dict:
    """Generate test SSO provider configuration."""
    pid = provider_id or f"test-sso-{uuid.uuid4().hex[:8]}"
    return {
        "id": pid,
        "name": pid,
        "display_name": "Test SSO Provider",
        "provider_type": "oidc",
        "client_id": "test-client-id",
        "client_secret": "test-client-secret",
        "authorization_url": "https://auth.example.com/authorize",
        "token_url": "https://auth.example.com/token",
        "userinfo_url": "https://auth.example.com/userinfo",
        "scope": "openid profile email",
    }


def _sso_available(admin_api: APIRequestContext) -> bool:
    """Check if SSO admin endpoints are available."""
    resp = admin_api.get(SSO_ADMIN_PATH)
    return resp.status != 404


# ---------------------------------------------------------------------------
# SSO Provider CRUD
# ---------------------------------------------------------------------------


class TestSSOProviderLifecycle:
    """Test SSO provider create/read/update/delete operations."""

    @pytest.fixture(autouse=True)
    def _skip_if_sso_unavailable(self, admin_api: APIRequestContext):
        """Skip all tests in this class if SSO endpoints are not available."""
        if not _sso_available(admin_api):
            pytest.skip("SSO admin endpoints not available in this environment")

    @pytest.fixture(scope="class")
    def sso_provider(self, admin_api: APIRequestContext):
        """Create an SSO provider for lifecycle tests, cleanup after class."""
        if not _sso_available(admin_api):
            pytest.skip("SSO admin endpoints not available in this environment")
        data = _make_provider_data()
        resp = admin_api.post(SSO_ADMIN_PATH, data=data)
        assert resp.status in (200, 201), f"Failed to create SSO provider: {resp.status} {resp.text()}"
        provider = resp.json()
        yield provider
        try:
            admin_api.delete(f"{SSO_ADMIN_PATH}/{data['id']}")
        except Exception:
            pass

    def test_create_sso_provider(self, admin_api: APIRequestContext):
        """Admin can create an OIDC SSO provider."""
        data = _make_provider_data()
        resp = admin_api.post(SSO_ADMIN_PATH, data=data)
        assert resp.status in (200, 201)
        # Cleanup
        admin_api.delete(f"{SSO_ADMIN_PATH}/{data['id']}")

    def test_list_sso_providers(self, admin_api: APIRequestContext, sso_provider: dict):
        """Admin can list all SSO providers."""
        resp = admin_api.get(SSO_ADMIN_PATH)
        assert resp.status == 200
        providers = resp.json()
        assert isinstance(providers, list)

    def test_update_sso_provider(self, admin_api: APIRequestContext, sso_provider: dict):
        """Admin can update an SSO provider's display name."""
        provider_id = sso_provider.get("id") or sso_provider.get("name")
        resp = admin_api.put(
            f"{SSO_ADMIN_PATH}/{provider_id}",
            data={"display_name": "Updated SSO Provider"},
        )
        assert resp.status == 200

    def test_delete_sso_provider(self, admin_api: APIRequestContext):
        """Admin can delete an SSO provider."""
        data = _make_provider_data()
        admin_api.post(SSO_ADMIN_PATH, data=data)
        resp = admin_api.delete(f"{SSO_ADMIN_PATH}/{data['id']}")
        assert resp.status in (200, 204)

    def test_non_admin_denied_sso_create(self, non_admin_api: APIRequestContext):
        """Non-admin user cannot create SSO providers."""
        data = _make_provider_data()
        resp = non_admin_api.post(SSO_ADMIN_PATH, data=data)
        assert resp.status in (401, 403), f"Non-admin should be denied, got {resp.status}"
