# Copyright (c) CloudZero - ALL RIGHTS RESERVED - PROPRIETARY AND CONFIDENTIAL
# Unauthorized copying of this file and/or project, via any medium is strictly prohibited.
# Direct all questions to legal@cloudzero.com
#

"""
V4 Authentication API Client

This module provides a clean, modern interface for authentication verification using the v4 API
with Okta authentication. This replaces legacy authentication functions with:
- verify_authentication() -> returns AuthVerifyResponse with comprehensive user data
- get_user_profile() -> extract user profile from authentication
- get_user_groups() -> extract user groups from authentication

Matches V4 API specification for /czops/v4/auth/verify endpoint with enhanced
user information, group memberships with source tracking, token metadata,
and backward compatibility fields.
"""

from pydantic import BaseModel, Field, ValidationError
from rich.console import Console

from src.api.authenticated import get_authenticated
from src.exceptions import APIError
from src.schemas.v4_errors import V4ErrorResponse, is_v4_error_response

console = Console()


# V4 Pydantic Models - Exact API contract matching V4 specification
class UserProfile(BaseModel):
    """User profile information from authentication tokens matching V4 API spec."""

    user_id: str = Field(..., description="Unique user identifier")
    subject: str = Field(..., description="Okta subject identifier")
    email: str = Field(..., description="User's email address")
    email_verified: bool | None = Field(None, description="Whether email is verified")
    full_name: str | None = Field(None, description="User's full name")
    first_name: str | None = Field(None, description="User's first name")
    last_name: str | None = Field(None, description="User's last name")
    preferred_username: str | None = Field(None, description="User's preferred username")
    department: str | None = Field(None, description="User's department")
    title: str | None = Field(None, description="User's job title")
    locale: str | None = Field(None, description="User's locale")
    timezone: str | None = Field(None, description="User's timezone")

    class Config:
        extra = "allow"  # Allow additional fields from backend


class GroupMembership(BaseModel):
    """Individual group membership with source tracking matching V4 API spec."""

    group_name: str = Field(..., description="Group name/identifier")
    verified: bool = Field(..., description="Whether group membership is verified")
    source: str = Field(..., description="Token source: access_token, id_token, or merged")

    class Config:
        extra = "allow"  # Allow additional fields from backend


class GroupsSummary(BaseModel):
    """Summary of user's group memberships matching V4 API spec."""

    total_groups: int = Field(..., description="Total number of groups")
    verified_groups: int = Field(..., description="Number of verified groups")
    groups_by_source: dict[str, int] = Field(..., description="Groups count by source")
    dual_token_enhancement: bool = Field(..., description="Whether dual token was used")
    context_groups_count: int = Field(..., description="Groups available in context")
    group_names: list[str] = Field(..., description="List of all group names")
    verification_status: str = Field(..., description="Overall verification status")

    class Config:
        extra = "allow"  # Allow additional fields from backend


class TokenMetadata(BaseModel):
    """Token metadata and authentication information matching V4 API spec."""

    dual_token_used: bool = Field(..., description="Whether dual token authentication was used")
    access_token_present: bool = Field(..., description="Whether access token is present")
    id_token_present: bool = Field(..., description="Whether ID token is present")
    token_sources: str | None = Field(None, description="Token sources information")
    scopes: list[str] = Field(default_factory=list, description="Token scopes")

    class Config:
        extra = "allow"  # Allow additional fields from backend


class TokenLifecycle(BaseModel):
    """Token lifecycle and expiration information matching V4 API spec."""

    issued_at: int | None = Field(None, description="Token issued at timestamp")
    expires_at: int | None = Field(None, description="Token expires at timestamp")
    auth_time: int | None = Field(None, description="Authentication time timestamp")
    not_before: int | None = Field(None, description="Not before timestamp")
    session_expires_in: int | None = Field(None, description="Session expiration in seconds")
    is_expired: bool = Field(default=False, description="Whether token is expired")

    class Config:
        extra = "allow"  # Allow additional fields from backend


class SecurityContext(BaseModel):
    """Security context information matching V4 API spec."""

    client_id: str | None = Field(None, description="OAuth client ID")
    issuer: str | None = Field(None, description="Token issuer")
    audience: str | None = Field(None, description="Token audience")
    authentication_methods: list[str] = Field(default_factory=list, description="Authentication methods used")
    identity_provider: str | None = Field(None, description="Identity provider used")

    class Config:
        extra = "allow"  # Allow additional fields from backend


class AuthVerifyResponse(BaseModel):
    """Comprehensive authentication verification response exactly matching V4 API specification."""

    authenticated: bool = Field(..., description="Whether user is authenticated")
    status: str = Field(..., description="Authentication status")
    message: str = Field(..., description="Authentication status message")

    # Enhanced user information (V4 API spec)
    user_profile: UserProfile = Field(..., description="Comprehensive user profile")
    group_memberships: list[GroupMembership] = Field(..., description="Group memberships with verification")
    groups_summary: GroupsSummary = Field(..., description="Groups summary information")

    # Token and security information (V4 API spec)
    token_metadata: TokenMetadata = Field(..., description="Token metadata")
    token_lifecycle: TokenLifecycle | None = Field(None, description="Token lifecycle information")
    security_context: SecurityContext | None = Field(None, description="Security context")

    # Legacy compatibility fields (V4 API spec - maintained for backward compatibility)
    email: str = Field(..., description="User email (legacy compatibility)")
    user_id: str = Field(..., description="User ID (legacy compatibility)")
    sub: str = Field(..., description="Subject ID (legacy compatibility)")
    exp: int | None = Field(None, description="Expiration timestamp (legacy compatibility)")
    iat: int | None = Field(None, description="Issued at timestamp (legacy compatibility)")
    user_department: str | None = Field(None, description="User department (legacy compatibility)")
    user_groups: list[str] = Field(..., description="User groups list (legacy compatibility)")
    user_full_name: str | None = Field(None, description="Full name (legacy compatibility)")
    user_title: str | None = Field(None, description="User title (legacy compatibility)")

    # Request tracking (V4 API spec)
    request_id: str | None = Field(None, description="Unique request identifier")
    timestamp: str | None = Field(None, description="Response timestamp")

    class Config:
        extra = "allow"  # Allow additional fields from backend for forward compatibility


def verify_authentication(debug: bool = False) -> AuthVerifyResponse:
    """
    Verify authentication status and retrieve comprehensive user information using v4 API.

    This function calls the /czops/v4/auth/verify endpoint to get detailed authentication
    information including user profile, group memberships with source tracking,
    token metadata, and security context.

    Args:
        debug: Whether to show debug information

    Returns:
        AuthVerifyResponse: Comprehensive authentication verification data

    Raises:
        APIError: If the API request fails or authentication is invalid
        ValueError: If the response format is invalid
    """
    if debug:
        console.print("[cyan]DEBUG: Verifying authentication via V4 API (/czops/v4/auth/verify)[/]")

    try:
        # Make authenticated request to v4 auth verify endpoint
        response_data = get_authenticated(endpoint_path="auth/verify", debug=debug)

        if debug:
            console.print(f"[cyan]DEBUG: Raw API response: {response_data}[/]")

        # Check if response is an error response
        if is_v4_error_response(response_data):
            error_response = V4ErrorResponse(**response_data)
            if debug:
                console.print(f"[red]DEBUG: API returned error: {error_response.error}[/]")
                console.print(f"[red]DEBUG: Error code: {error_response.error_code}[/]")
                console.print(f"[red]DEBUG: Details: {error_response.details}[/]")
            raise APIError(f"Authentication verification failed: {error_response.error} ({error_response.error_code})")

        # Validate successful response with Pydantic model
        auth_response = AuthVerifyResponse(**response_data)

        if debug:
            if auth_response.authenticated:
                console.print(f"[green]DEBUG: Successfully authenticated user {auth_response.user_profile.email}[/]")
                console.print(f"[cyan]DEBUG: User has {len(auth_response.group_memberships)} group memberships[/]")
                console.print(f"[cyan]DEBUG: Dual token used: {auth_response.token_metadata.dual_token_used}[/]")
            else:
                console.print(f"[yellow]DEBUG: Authentication failed: {auth_response.message}[/]")

        return auth_response

    except APIError:
        # Re-raise API errors as-is (includes V4 error responses)
        raise
    except ValidationError as e:
        if debug:
            console.print(f"[red]DEBUG: Response validation failed: {e}[/]")
        raise APIError(f"Invalid response format from v4 auth API: {e}") from e
    except Exception as e:
        error_msg = f"Failed to verify authentication: {str(e)}"
        if debug:
            console.print(f"[red]DEBUG: Unexpected error in auth verification: {error_msg}[/]")
        raise APIError(error_msg) from e


def get_user_profile(auth_response: AuthVerifyResponse) -> UserProfile:
    """
    Extract user profile information from authentication response.

    Args:
        auth_response: Authentication response from verify_authentication()

    Returns:
        UserProfile: User profile information

    Raises:
        ValueError: If authentication response is invalid
    """
    if not auth_response.authenticated:
        raise ValueError("User is not authenticated")

    return auth_response.user_profile


def get_user_groups(auth_response: AuthVerifyResponse) -> list[str]:
    """
    Extract user groups from authentication response.

    Args:
        auth_response: Authentication response from verify_authentication()

    Returns:
        list[str]: List of user group names

    Raises:
        ValueError: If authentication response is invalid
    """
    if not auth_response.authenticated:
        raise ValueError("User is not authenticated")

    return auth_response.user_groups


def get_verified_groups(auth_response: AuthVerifyResponse) -> list[GroupMembership]:
    """
    Extract verified group memberships with source tracking from authentication response.

    Args:
        auth_response: Authentication response from verify_authentication()

    Returns:
        list[GroupMembership]: List of verified group memberships

    Raises:
        ValueError: If authentication response is invalid
    """
    if not auth_response.authenticated:
        raise ValueError("User is not authenticated")

    return [group for group in auth_response.group_memberships if group.verified]
