"""Tests for app.core.security — password hashing, JWT token creation and decoding"""

import pytest
from unittest.mock import patch


class TestPasswordHashing:
    def test_hash_and_verify(self):
        from app.core.security import hash_password, verify_password
        hashed = hash_password("my_secret_pwd")
        assert hashed != "my_secret_pwd"
        assert verify_password("my_secret_pwd", hashed) is True

    def test_verify_wrong_password(self):
        from app.core.security import hash_password, verify_password
        hashed = hash_password("correct")
        assert verify_password("wrong", hashed) is False

    def test_hash_is_unique_per_call(self):
        from app.core.security import hash_password
        h1 = hash_password("same")
        h2 = hash_password("same")
        assert h1 != h2  # bcrypt uses different salts


class TestAccessToken:
    def test_create_and_decode(self):
        from app.core.security import create_access_token, decode_token
        token = create_access_token("user-1", "tenant-1", "admin")
        payload = decode_token(token)
        assert payload["sub"] == "user-1"
        assert payload["tid"] == "tenant-1"
        assert payload["role"] == "admin"
        assert payload["type"] == "access"
        assert payload.get("platform_role") is None
        assert "jti" in payload
        assert "iat" in payload
        assert "exp" in payload

    def test_superuser(self):
        from app.core.security import create_access_token, decode_token
        token = create_access_token("admin", "tenant-1", "owner", platform_role="platform_owner")
        payload = decode_token(token)
        assert payload.get("platform_role") == "platform_owner"

    def test_expiration(self):
        from app.core.security import create_access_token
        from app.config import settings
        token = create_access_token("user-1", "tenant-1", "viewer")
        import jwt
        payload = jwt.decode(token, settings.JWT_SECRET, algorithms=[settings.JWT_ALGORITHM], options={"verify_exp": False})
        assert payload["sub"] == "user-1"


class TestRefreshToken:
    def test_create_and_decode(self):
        from app.core.security import create_refresh_token, decode_token
        token, jti = create_refresh_token("user-1", "tenant-1")
        payload = decode_token(token)
        assert payload["sub"] == "user-1"
        assert payload["tid"] == "tenant-1"
        assert payload["type"] == "refresh"
        assert payload["jti"] == jti

    def test_default_role(self):
        from app.core.security import create_refresh_token, decode_token
        token, _ = create_refresh_token("user-1", "tenant-1")
        payload = decode_token(token)
        assert payload["role"] == "viewer"

    def test_superuser(self):
        from app.core.security import create_refresh_token, decode_token
        token, _ = create_refresh_token("user-1", "tenant-1", platform_role="platform_owner")
        payload = decode_token(token)
        assert payload.get("platform_role") == "platform_owner"


class TestDecodeToken:
    def test_invalid_token_raises(self):
        from app.core.security import decode_token
        import jwt
        with pytest.raises(jwt.InvalidTokenError):
            decode_token("not-a-valid-jwt")

    def test_wrong_algorithm(self):
        from app.core.security import decode_token
        import jwt
        from app.config import settings
        # Encode with wrong algorithm
        token = jwt.encode({"sub": "test"}, "wrong-secret", algorithm="HS256")
        with pytest.raises(jwt.InvalidTokenError):
            decode_token(token)
