# 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 CUR Validation Rules API Client

This module provides interface to CUR validation rules management endpoints.
"""

from typing import Any

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

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

console = Console()


# Pydantic Models matching backend schema


class CURValidationRule(BaseModel):
    """Individual validation rule for a CUR field."""

    rule_id: str = Field(..., description="Unique identifier for this rule")
    field_name: str = Field(..., description="CUR field to validate")
    allowed_values: list[str] = Field(..., description="List of acceptable values")
    validation_level: str = Field(..., description="required or recommended")
    error_message_template: str = Field(..., description="Error message template")
    enabled: bool = Field(True, description="Whether this rule is active")

    model_config = ConfigDict(extra="allow")


class CURValidationRuleSet(BaseModel):
    """Complete set of CUR validation rules."""

    rule_set_id: str = Field(..., description="Unique identifier for this rule set")
    rule_set_name: str = Field(..., description="Human-readable name")
    rule_set_version: str = Field(..., description="Version identifier")
    description: str = Field(..., description="Description of what these rules enforce")
    PK: str = Field(..., description="DynamoDB partition key")
    SK: str = Field(..., description="DynamoDB sort key")
    rules: list[CURValidationRule] = Field(..., description="List of validation rules")
    created: str = Field(..., description="ISO 8601 timestamp")
    last_updated: str = Field(..., description="ISO 8601 timestamp")
    updated_by: str | None = Field(None, description="User who last updated")
    ttl: int | None = Field(None, description="Unix timestamp for TTL")
    ttl_iso8601: str | None = Field(None, description="Human-readable TTL")

    model_config = ConfigDict(extra="allow")


# API Client Functions


def get_cur_validation_rules(debug: bool = False) -> CURValidationRuleSet:
    """
    Get CUR validation rules from backend.

    Args:
        debug: Whether to show debug information

    Returns:
        CURValidationRuleSet: Current validation rule set

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

    try:
        response_data = get_authenticated(endpoint_path="system/cur-validation-rules", debug=debug)

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

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

    except APIError:
        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 CUR validation rules: {str(e)}"
        if debug:
            console.print(f"[red]DEBUG: Unexpected error: {error_msg}[/]")
        raise APIError(error_msg) from e


def update_cur_validation_rules(rule_set: dict[str, Any], debug: bool = False) -> CURValidationRuleSet:
    """
    Update CUR validation rules in backend.

    Args:
        rule_set: Updated rule set data
        debug: Whether to show debug information

    Returns:
        CURValidationRuleSet: Updated validation rule set

    Raises:
        APIError: If the API request fails
        ValueError: If the request or response is invalid
    """
    if debug:
        console.print("[cyan]DEBUG: Updating CUR validation rules via V4 API[/]")

    try:
        response_data = post_authenticated(endpoint_path="system/cur-validation-rules", json_data=rule_set, debug=debug)

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

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

    except APIError:
        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 update CUR validation rules: {str(e)}"
        if debug:
            console.print(f"[red]DEBUG: Unexpected error: {error_msg}[/]")
        raise APIError(error_msg) from e


def reset_cur_validation_rules(debug: bool = False) -> CURValidationRuleSet:
    """
    Reset CUR validation rules to defaults.

    Args:
        debug: Whether to show debug information

    Returns:
        CURValidationRuleSet: Default validation rule set

    Raises:
        APIError: If the API request fails
        ValueError: If the response format is invalid
    """
    if debug:
        console.print("[cyan]DEBUG: Resetting CUR validation rules via V4 API[/]")

    try:
        response_data = post_authenticated(endpoint_path="system/cur-validation-rules/reset", json_data={}, debug=debug)

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

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

    except APIError:
        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 reset CUR validation rules: {str(e)}"
        if debug:
            console.print(f"[red]DEBUG: Unexpected error: {error_msg}[/]")
        raise APIError(error_msg) from e
