"""Shared test fixtures for YUKKA package tests."""

import base64
import json
from datetime import UTC, datetime, timedelta
from unittest.mock import MagicMock, Mock

import pytest
from httpx import Response

from yukka.auth import Token


def create_jwt_token(
    email: str = "test@yukkalab.com",
    groups: list[str] | None = None,
    exp_offset_seconds: int = 3600,
    iat_offset_seconds: int = 0,
) -> str:
    """Create a valid JWT token for testing.

    Args:
        email: Email to encode in payload
        groups: Groups to encode in payload
        exp_offset_seconds: Seconds from now until expiration (positive = future)
        iat_offset_seconds: Seconds from now for issued-at (negative = past)

    Returns:
        JWT token string
    """
    if groups is None:
        groups = ["users", "quant"]

    now = datetime.now(tz=UTC)
    payload = {
        "exp": (now + timedelta(seconds=exp_offset_seconds)).timestamp(),
        "iat": (now + timedelta(seconds=iat_offset_seconds)).timestamp(),
        "email": email,
        "groups": groups,
    }

    # Create minimal valid JWT structure (header.payload.signature)
    header = base64.urlsafe_b64encode(json.dumps({"alg": "HS256", "typ": "JWT"}).encode()).decode().rstrip("=")
    payload_b64 = base64.urlsafe_b64encode(json.dumps(payload).encode()).decode().rstrip("=")
    signature = "fake_signature_for_testing"

    return f"{header}.{payload_b64}.{signature}"


@pytest.fixture
def valid_token_str() -> str:
    """Return a valid JWT token string that expires in 1 hour."""
    return create_jwt_token(exp_offset_seconds=3600)


@pytest.fixture
def expired_token_str() -> str:
    """Return an expired JWT token string."""
    return create_jwt_token(exp_offset_seconds=-3600)


@pytest.fixture
def valid_token(valid_token_str: str) -> Token:
    """Return a valid Token instance."""
    return Token.from_token(valid_token_str)


@pytest.fixture
def expired_token(expired_token_str: str) -> Token:
    """Return an expired Token instance."""
    return Token.from_token(expired_token_str)


@pytest.fixture
def mock_http_client() -> MagicMock:
    """Return a mock httpx.Client."""
    return MagicMock()


@pytest.fixture
def mock_response_factory():
    """Factory fixture for creating mock HTTP responses."""

    def _create_response(
        status_code: int = 200,
        json_data: dict | list | None = None,
        raise_for_status_error: Exception | None = None,
    ) -> Mock:
        response = Mock(spec=Response)
        response.status_code = status_code
        response.json.return_value = json_data or {}

        if raise_for_status_error:
            response.raise_for_status.side_effect = raise_for_status_error
        else:
            response.raise_for_status.return_value = None

        return response

    return _create_response


@pytest.fixture
def sample_isin_resolution_response() -> dict:
    """Return a sample ISIN resolution API response."""
    return {
        "DE0005190003": {"compound_key": "company:bmw"},
        "US0378331005": {"compound_key": "company:apple"},
    }
