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

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

Session security and CSRF-related tests for admin auth cookies.
"""

# Future
from __future__ import annotations

# Standard
from urllib.parse import urlparse

# Third-Party
import pytest

# First-Party
from mcpgateway.admin import ADMIN_CSRF_COOKIE_NAME, ADMIN_CSRF_HEADER_NAME
from mcpgateway.config import settings


def _expected_samesite() -> str:
    value = (settings.cookie_samesite or "lax").strip().lower()
    return {"lax": "Lax", "strict": "Strict", "none": "None"}.get(value, "Lax")


class TestSessionAndCSRFSecurity:
    """Session cookie hardening and CSRF protection expectations."""

    @staticmethod
    def _logout_headers(page) -> dict[str, str]:
        """Build CSRF/origin headers for logout mutation requests."""
        headers: dict[str, str] = {}
        csrf_cookie = next((cookie for cookie in page.context.cookies() if cookie["name"] == ADMIN_CSRF_COOKIE_NAME), None)
        if csrf_cookie and csrf_cookie.get("value"):
            headers[ADMIN_CSRF_HEADER_NAME] = csrf_cookie["value"]

        parsed = urlparse(page.url or "")
        if parsed.scheme and parsed.netloc:
            origin = f"{parsed.scheme}://{parsed.netloc}"
            headers["Origin"] = origin
            headers["Referer"] = f"{origin}/admin"

        return headers

    def test_admin_session_cookie_has_security_attributes(self, admin_page):
        if not settings.auth_required:
            pytest.skip("Authentication is disabled; session cookie hardening is not applicable.")

        page = admin_page.page
        jwt_cookie = next((cookie for cookie in page.context.cookies() if cookie["name"] == "jwt_token"), None)
        assert jwt_cookie is not None, "Expected jwt_token cookie after admin authentication"
        assert jwt_cookie["httpOnly"] is True
        assert jwt_cookie["sameSite"] == _expected_samesite()

    def test_logout_clears_session_cookie(self, admin_page):
        if not settings.auth_required:
            pytest.skip("Authentication is disabled; logout cookie clearing is not applicable.")

        page = admin_page.page
        before = next((cookie for cookie in page.context.cookies() if cookie["name"] == "jwt_token"), None)
        if before is None:
            pytest.skip("No jwt_token cookie present before logout in this environment.")

        response = page.request.post("/admin/logout", headers=self._logout_headers(page))
        assert response.status in (200, 302, 303), f"Unexpected logout status: {response.status}"

        after = next((cookie for cookie in page.context.cookies() if cookie["name"] == "jwt_token"), None)
        assert after is None or not after.get("value"), "jwt_token cookie should be cleared by logout"

    def test_cross_origin_state_change_without_csrf_token_is_rejected(self, admin_page):
        if not settings.auth_required:
            pytest.skip("Authentication is disabled; CSRF protections are not applicable.")

        page = admin_page.page
        response = page.request.post(
            "/admin/logout",
            headers={"Origin": "https://evil.example"},
        )
        assert response.status in (400, 403), f"Cross-origin POST should be rejected, got {response.status}"
