# 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 Healthcheck API Client

This module provides a clean, modern interface for healthcheck operations using the v4 API
with Okta authentication. This replaces legacy v3 healthcheck functions with:
- get_organization_healthcheck(organization_id) -> returns OrganizationHealthcheck
- get_connection_healthcheck(connection_id) -> returns ConnectionHealthcheck
- post_bulk_healthcheck(bulk_request) -> returns BulkHealthcheckResponse
- get_healthcheck_status() -> returns HealthcheckStatusResponse
"""

import getpass
from typing import Any

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

from src.api.authenticated import get_authenticated, post_authenticated
from src.exceptions import APIError

console = Console()


# V4 Pydantic Models - Direct mapping to documented API responses


class HealthCheck(BaseModel):
    """Individual health check as documented in API."""

    name: str = Field(..., description="Health check name")
    status: str = Field(..., description="Health check status")
    message: str | None = Field(None, description="Health check message")
    duration_ms: float | None = Field(None, description="Check duration in milliseconds")
    timestamp: str | None = Field(None, description="Check timestamp")
    details: dict[str, Any] = Field(default_factory=dict, description="Additional check details")

    class Config:
        extra = "allow"


class HealthcheckSummary(BaseModel):
    """Summary of health checks as documented in API."""

    total_checks: int = Field(0, description="Total number of checks")
    healthy_count: int = Field(0, description="Number of healthy checks")
    degraded_count: int = Field(0, description="Number of degraded checks")
    unhealthy_count: int = Field(0, description="Number of unhealthy checks")

    class Config:
        extra = "allow"


class ConnectionHealthcheck(BaseModel):
    """Connection healthcheck response as documented in API."""

    connection_id: str = Field(..., description="Connection identifier")
    status: str = Field(..., description="Health status")
    overall_score: float | None = Field(None, description="Overall health score")
    duration_ms: float = Field(..., description="Total check duration in milliseconds")
    timestamp: str = Field(..., description="ISO 8601 timestamp")
    success: bool = Field(..., description="Whether healthcheck completed successfully")
    checks: list[HealthCheck] = Field(default_factory=list, description="Individual health checks")
    summary: HealthcheckSummary | None = Field(None, description="Health check summary")
    metadata: dict[str, Any] | None = Field(None, description="Connection metadata")

    class Config:
        extra = "allow"


class OrganizationSummary(BaseModel):
    """Organization health summary statistics."""

    total_connections: int = Field(..., description="Total connections in org")
    healthy_count: int = Field(..., description="Connections with 'healthy' status")
    unhealthy_count: int = Field(..., description="Connections with 'unhealthy' status")
    warning_count: int = Field(..., description="Connections with 'warning' status")
    unknown_count: int = Field(..., description="Connections with 'unknown' status")

    class Config:
        extra = "allow"


class OrganizationHealthcheck(BaseModel):
    """Organization healthcheck response as documented in API."""

    organization_id: str = Field(..., description="CloudZero organization UUID")
    status: str = Field(..., description="Overall org health status")
    overall_score: float = Field(..., description="Aggregate health score 0-100")
    duration_ms: float = Field(..., description="Total check duration")
    timestamp: str = Field(..., description="ISO 8601 timestamp")
    success: bool = Field(..., description="Whether check completed")
    summary: OrganizationSummary = Field(..., description="Summary statistics")
    connections: list[ConnectionHealthcheck] = Field(default_factory=list, description="Connection health results")
    error: str | None = Field(None, description="Present only on failures")

    class Config:
        extra = "allow"


class BulkHealthcheckRequest(BaseModel):
    """Bulk healthcheck request as documented in API."""

    entity_ids: list[str] = Field(..., description="List of entity IDs to check")
    entity_type: str = Field(..., description="Type of entities (connection/organization)")
    include_details: bool = Field(True, description="Whether to include detailed health information")

    class Config:
        extra = "allow"


class BulkHealthcheckResult(BaseModel):
    """Individual result in bulk healthcheck response."""

    entity_id: str = Field(..., description="Entity identifier")
    status: str = Field(..., description="Health status")
    overall_score: float = Field(..., description="Overall health score")

    class Config:
        extra = "allow"


class BulkHealthcheckSummary(BaseModel):
    """Summary statistics for bulk healthcheck as documented in API."""

    # Make fields optional with defaults to handle incomplete responses
    checked_entities: int = Field(0, description="Number of entities checked")
    healthy_count: int = Field(0, description="Number of healthy entities")
    degraded_count: int = Field(0, description="Number of degraded entities")
    unhealthy_count: int = Field(0, description="Number of unhealthy entities")

    # Additional fields that might come from API
    total_requested: int | None = Field(None, description="Total entities requested")
    total_processed: int | None = Field(None, description="Total entities processed")
    total_healthy: int | None = Field(None, description="Total healthy entities")
    total_unhealthy: int | None = Field(None, description="Total unhealthy entities")
    total_degraded: int | None = Field(None, description="Total degraded entities")

    class Config:
        extra = "allow"


class BulkHealthcheckResponse(BaseModel):
    """Bulk healthcheck response as documented in API."""

    # Make core fields optional to handle varying API responses
    entity_type: str | None = Field(None, description="Type of entities checked")
    summary: BulkHealthcheckSummary | None = Field(None, description="Summary statistics")

    # Results can come in different formats from the API
    results: dict[str, Any] | list[dict[str, Any]] | None = Field(None, description="Healthcheck results")
    connections: list[ConnectionHealthcheck] = Field(default_factory=list, description="Parsed connection results")
    organizations: list[OrganizationHealthcheck] = Field(default_factory=list, description="Parsed organization results")

    # Error tracking
    errors: list[dict[str, Any]] = Field(default_factory=list, description="Processing errors")
    failed_entities: list[str] = Field(default_factory=list, description="Failed entity IDs")

    # Metadata
    timestamp: str | None = Field(None, description="Response timestamp")
    success: bool = Field(True, description="Whether the bulk healthcheck succeeded")

    class Config:
        extra = "allow"


class HealthcheckSystem(BaseModel):
    """Healthcheck system information."""

    status: str = Field(..., description="System status")
    version: str = Field(..., description="System version")
    uptime_hours: float = Field(..., description="System uptime in hours")
    last_restart: str = Field(..., description="Last restart timestamp")

    class Config:
        extra = "allow"


class HealthcheckStatistics(BaseModel):
    """Healthcheck system statistics."""

    total_checks_today: int = Field(..., description="Total checks performed today")
    average_response_time_ms: float = Field(..., description="Average response time")
    success_rate_percentage: float = Field(..., description="Success rate percentage")

    class Config:
        extra = "allow"


class HealthcheckStatusResponse(BaseModel):
    """Healthcheck system status response as documented in API."""

    healthcheck_system: HealthcheckSystem = Field(..., description="System information")
    capabilities: list[str] = Field(..., description="System capabilities")
    statistics: HealthcheckStatistics = Field(..., description="System statistics")
    timestamp: str = Field(..., description="Response timestamp")
    success: bool = Field(..., description="Whether the status check succeeded")

    class Config:
        extra = "allow"


# API Client Functions


def get_organization_healthcheck(organization_id: str, include_details: bool = True, debug: bool = False) -> OrganizationHealthcheck:
    """
    Get organization healthcheck using v4 API.

    Args:
        organization_id: Organization identifier
        include_details: Whether to include detailed health information
        debug: Whether to show debug information

    Returns:
        OrganizationHealthcheck: Organization health status and connection details

    Raises:
        APIError: If the API request fails
        ValueError: If the response format is invalid
    """
    if debug:
        console.print(f"[cyan]DEBUG: Fetching organization healthcheck via V4 API for {organization_id}[/]")

    try:
        # Build query parameters
        params = {}
        if not include_details:
            params["include_details"] = "false"

        # Make authenticated request to v4 organization healthcheck endpoint
        response_data = get_authenticated(endpoint_path=f"healthcheck/organization/{organization_id}", params=params, debug=debug)

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

        # Validate response with Pydantic model
        return OrganizationHealthcheck(**response_data)

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


def get_connection_healthcheck(connection_id: str, include_details: bool = True, debug: bool = False) -> ConnectionHealthcheck:
    """
    Get connection healthcheck using v4 API.

    Args:
        connection_id: Connection identifier
        include_details: Whether to include detailed health information
        debug: Whether to show debug information

    Returns:
        ConnectionHealthcheck: Connection health status and details

    Raises:
        APIError: If the API request fails
        ValueError: If the response format is invalid
    """
    if debug:
        console.print(f"[cyan]DEBUG: Fetching connection healthcheck via V4 API for {connection_id}[/]")

    try:
        # Build query parameters
        params = {}
        if not include_details:
            params["include_details"] = "false"

        # Make authenticated request to v4 connection healthcheck endpoint
        response_data = get_authenticated(endpoint_path=f"healthcheck/connection/{connection_id}", params=params, debug=debug)

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

        # Validate response with Pydantic model
        return ConnectionHealthcheck(**response_data)

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


def post_bulk_healthcheck(entity_type: str, entity_ids: list[str], include_details: bool = True, debug: bool = False) -> BulkHealthcheckResponse:
    """
    Perform bulk healthcheck using v4 API.

    Args:
        entity_type: Type of entities ('connections' or 'organizations')
        entity_ids: List of entity IDs to check
        include_details: Whether to include detailed health information
        debug: Whether to show debug information

    Returns:
        BulkHealthcheckResponse: Bulk healthcheck results

    Raises:
        APIError: If the API request fails
        ValueError: If the request parameters are invalid
    """
    if debug:
        console.print(f"[cyan]DEBUG: Performing bulk healthcheck via V4 API for {len(entity_ids)} {entity_type}[/]")

    if not entity_ids:
        raise ValueError("Entity IDs list cannot be empty")

    if entity_type not in ["connection", "organization", "connections", "organizations"]:
        # Accept both singular and plural forms for backward compatibility
        raise ValueError(f"Invalid entity_type: {entity_type}. Must be 'connection' or 'organization'")

    # Normalize to singular form for API
    if entity_type == "connections":
        entity_type = "connection"
    elif entity_type == "organizations":
        entity_type = "organization"

    try:
        # Build the request payload
        payload = {"entity_type": entity_type, "entity_ids": entity_ids, "include_details": include_details}

        # Get CLI version and user for tracking
        from src import __version__ as cli_version

        params = {"reported_version": cli_version, "reported_user": getpass.getuser()}

        if debug:
            console.print(f"[cyan]DEBUG: Bulk healthcheck payload: {payload}[/]")

        # Make authenticated request to v4 bulk healthcheck endpoint
        if debug:
            console.print(f"[cyan]DEBUG: Making POST request to healthcheck/bulk with payload: {payload}[/]")
        response_data = post_authenticated(endpoint_path="healthcheck/bulk", json_data=payload, params=params, debug=debug)

        if debug:
            console.print(
                f"[cyan]DEBUG: Raw API response type: {type(response_data)}, keys: {response_data.keys() if isinstance(response_data, dict) else 'not a dict'}[/]"
            )
            if isinstance(response_data, dict):
                console.print(f"[cyan]DEBUG: Response summary: {response_data.get('summary')}[/]")
                console.print(
                    f"[cyan]DEBUG: Response results type: {type(response_data.get('results'))}, length: {len(response_data.get('results', []))}[/]"
                )
            console.print(f"[cyan]DEBUG: Raw API response: {response_data}[/]")

        # Validate response with Pydantic model
        response = BulkHealthcheckResponse(**response_data)

        # Post-process: convert results into connections or organizations
        if debug:
            console.print(f"[cyan]DEBUG: Processing {len(response.results) if response.results else 0} results[/]")
        if response.results:
            # Results can be a list or dict - handle both
            results_list = response.results if isinstance(response.results, list) else list(response.results.values())

            for result in results_list:
                if debug:
                    console.print(
                        f"[cyan]DEBUG: Processing result with entity_id={result.get('entity_id')}, entity_type={result.get('entity_type')}[/]"
                    )
                # Map the result to connection healthcheck format
                if result.get("entity_type") == "connection" or entity_type == "connection":
                    try:
                        # Create connection healthcheck from result
                        connection = ConnectionHealthcheck(**result)
                        response.connections.append(connection)
                        if debug:
                            console.print(f"[cyan]DEBUG: Successfully created ConnectionHealthcheck for {result.get('connection_id')}[/]")
                    except ValidationError as e:
                        if debug:
                            console.print(f"[yellow]DEBUG: Could not parse connection result: {e}[/]")
                            console.print(f"[yellow]DEBUG: Result data: {result}[/]")
                elif result.get("entity_type") == "organization" or entity_type == "organization":
                    # Create an OrganizationHealthcheck from the result
                    try:
                        org = OrganizationHealthcheck(**result)
                        response.organizations.append(org)
                    except Exception as e:
                        if debug:
                            console.print(f"[yellow]DEBUG: Could not parse organization result: {e}[/]")
                            console.print(f"[yellow]DEBUG: Result data: {result}[/]")

        return response

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


def get_healthcheck_status(debug: bool = False) -> HealthcheckStatusResponse:
    """
    Get healthcheck system status using v4 API.

    Args:
        debug: Whether to show debug information

    Returns:
        HealthcheckStatusResponse: Healthcheck system status

    Raises:
        APIError: If the API request fails
        ValueError: If the response format is invalid
    """
    if debug:
        console.print("[cyan]DEBUG: Fetching healthcheck system status via V4 API[/]")

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

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

        # Validate response with Pydantic model
        return HealthcheckStatusResponse(**response_data)

    except APIError:
        # Re-raise API errors as-is
        raise
    except ValidationError as e:
        if debug:
            console.print(f"[red]DEBUG: Response validation failed: {e}[/]")
        raise APIError(f"Invalid response format from v4 API: {e}") from e
    except Exception as e:
        error_msg = f"Failed to get healthcheck system status: {str(e)}"
        if debug:
            console.print(f"[red]DEBUG: Unexpected error: {error_msg}[/]")
        raise APIError(error_msg) from e


# Legacy compatibility functions for migration support


def get_healthcheck_v4(connection_id: str, debug: bool = False) -> dict[str, Any]:
    """
    Legacy compatibility function that returns connection healthcheck as dict.

    This function provides backward compatibility during the v3->v4 migration.

    Args:
        connection_id: Connection identifier
        debug: Whether to show debug information

    Returns:
        dict: Connection healthcheck data as dictionary
    """
    if debug:
        console.print(f"[cyan]DEBUG: Using legacy compatibility function for connection {connection_id}[/]")

    healthcheck = get_connection_healthcheck(connection_id, debug=debug)
    return healthcheck.model_dump()


def get_healthcheck_bulk_v4(entity_ids: list[str], debug: bool = False) -> dict[str, Any]:
    """
    Legacy compatibility function that returns bulk healthcheck as dict.

    This function provides backward compatibility during the v3->v4 migration.

    Args:
        entity_ids: List of connection IDs
        debug: Whether to show debug information

    Returns:
        dict: Bulk healthcheck data as dictionary
    """
    if debug:
        console.print(f"[cyan]DEBUG: Using legacy compatibility function for {len(entity_ids)} connections[/]")

    # Assume connections for backward compatibility (use singular form)
    bulk_response = post_bulk_healthcheck("connection", entity_ids, debug=debug)

    # Transform to legacy format
    legacy_response = {
        "results": [conn.model_dump() for conn in bulk_response.connections],
        "total_connections": bulk_response.summary.total_processed if bulk_response.summary else len(bulk_response.connections),
        "healthy_connections": bulk_response.summary.total_healthy if bulk_response.summary else 0,
        "unhealthy_connections": bulk_response.summary.total_unhealthy if bulk_response.summary else 0,
        "success": True,
    }

    return legacy_response
