# tests/integration/api/v1/admin/test_auth.py
"""Integration tests for admin authentication endpoints.

Tests the /api/v1/admin/auth/* endpoints.
"""

from datetime import UTC, datetime, timedelta

import pytest
from jose import jwt


@pytest.mark.integration
@pytest.mark.api
@pytest.mark.auth
class TestAdminAuthAPI:
    """Test admin authentication endpoints at /api/v1/admin/auth/*."""

    def test_login_success(self, client, test_admin):
        """Test successful admin login."""
        response = client.post(
            "/api/v1/admin/auth/login",
            json={"email_or_username": test_admin.username, "password": "adminpass123"},
        )

        assert response.status_code == 200
        data = response.json()
        assert "access_token" in data
        assert data["token_type"] == "bearer"
        assert "expires_in" in data
        assert data["user"]["username"] == test_admin.username
        assert data["user"]["email"] == test_admin.email

    def test_login_with_email(self, client, test_admin):
        """Test admin login with email instead of username."""
        response = client.post(
            "/api/v1/admin/auth/login",
            json={"email_or_username": test_admin.email, "password": "adminpass123"},
        )

        assert response.status_code == 200
        data = response.json()
        assert "access_token" in data
        assert data["user"]["email"] == test_admin.email

    def test_login_wrong_password(self, client, test_admin):
        """Test login with wrong password."""
        response = client.post(
            "/api/v1/admin/auth/login",
            json={
                "email_or_username": test_admin.username,
                "password": "wrongpassword",
            },
        )

        assert response.status_code == 401
        data = response.json()
        assert data["error_code"] == "INVALID_CREDENTIALS"

    def test_login_nonexistent_user(self, client):
        """Test login with nonexistent user."""
        response = client.post(
            "/api/v1/admin/auth/login",
            json={"email_or_username": "nonexistent", "password": "password123"},
        )

        assert response.status_code == 401
        data = response.json()
        assert data["error_code"] == "INVALID_CREDENTIALS"

    def test_login_inactive_user(self, client, db, test_admin):
        """Test login with inactive admin account."""
        original_status = test_admin.is_active
        test_admin.is_active = False
        db.commit()

        try:
            response = client.post(
                "/api/v1/admin/auth/login",
                json={
                    "email_or_username": test_admin.username,
                    "password": "adminpass123",
                },
            )

            assert response.status_code == 403
            data = response.json()
            assert data["error_code"] == "USER_NOT_ACTIVE"

        finally:
            test_admin.is_active = original_status
            db.commit()

    def test_login_non_admin_user_rejected(self, client, test_user):
        """Test that non-admin users cannot use admin login."""
        response = client.post(
            "/api/v1/admin/auth/login",
            json={"email_or_username": test_user.username, "password": "testpass123"},
        )

        assert response.status_code == 401
        data = response.json()
        assert data["error_code"] == "INVALID_CREDENTIALS"

    def test_login_validation_error(self, client):
        """Test login with invalid request format."""
        response = client.post(
            "/api/v1/admin/auth/login",
            json={
                "email_or_username": "",  # Empty
            },
        )

        assert response.status_code == 422
        data = response.json()
        assert data["error_code"] == "VALIDATION_ERROR"

    def test_get_current_admin_info(self, client, admin_headers, test_admin):
        """Test getting current admin user info."""
        response = client.get("/api/v1/admin/auth/me", headers=admin_headers)

        assert response.status_code == 200
        data = response.json()
        assert data["username"] == test_admin.username
        assert data["email"] == test_admin.email
        assert data["role"] == "admin"
        assert data["is_active"] is True

    def test_get_current_admin_without_auth(self, client):
        """Test getting current admin without authentication."""
        response = client.get("/api/v1/admin/auth/me")

        assert response.status_code == 401
        data = response.json()
        assert data["error_code"] == "INVALID_TOKEN"

    def test_get_current_admin_invalid_token(self, client):
        """Test getting current admin with invalid token."""
        response = client.get(
            "/api/v1/admin/auth/me", headers={"Authorization": "Bearer invalid_token"}
        )

        assert response.status_code == 401
        data = response.json()
        assert data["error_code"] == "INVALID_TOKEN"

    def test_get_current_admin_expired_token(self, client, test_admin, auth_manager):
        """Test getting current admin with expired token."""
        expired_payload = {
            "sub": str(test_admin.id),
            "username": test_admin.username,
            "email": test_admin.email,
            "role": test_admin.role,
            "exp": datetime.now(UTC) - timedelta(hours=1),
            "iat": datetime.now(UTC) - timedelta(hours=2),
        }

        expired_token = jwt.encode(
            expired_payload, auth_manager.secret_key, algorithm=auth_manager.algorithm
        )

        response = client.get(
            "/api/v1/admin/auth/me",
            headers={"Authorization": f"Bearer {expired_token}"},
        )

        assert response.status_code == 401
        data = response.json()
        assert data["error_code"] == "TOKEN_EXPIRED"

    def test_logout(self, client, admin_headers):
        """Test admin logout."""
        response = client.post("/api/v1/admin/auth/logout", headers=admin_headers)

        assert response.status_code == 200
        data = response.json()
        assert data["message"] == "Logged out successfully"
