"""Example of using OnePasswordSettings with Pydantic.

This example demonstrates how to use OnePasswordSettings for automatic
secret injection in Pydantic Settings classes.

Prerequisites:
- 1Password CLI installed (op command available)
- User authenticated (op signin completed)
- Test vault and items set up in 1Password
"""

from pydantic import Field
from pydantic_settings import SettingsConfigDict

from scottzach1.onepassword_cli import OnePasswordSettings


class DatabaseConfig(OnePasswordSettings):
    """Database configuration with automatic secret injection."""

    host: str = "op://vault/database/host"
    port: int = 5432
    username: str = "op://vault/database/username"
    password: str = "op://vault/database/password"
    database: str = "myapp"

    @property
    def connection_string(self) -> str:
        """Build a database connection string."""
        return f"postgresql://{self.username}:{self.password}@{self.host}:{self.port}/{self.database}"


class APIConfig(OnePasswordSettings):
    """API configuration with automatic secret injection."""

    api_key: str = "op://vault/api/key"
    api_secret: str = "op://vault/api/secret"
    endpoint: str = "https://api.example.com"
    timeout: int = 30
    retries: int = 3


class AppSettings(OnePasswordSettings):
    """Application settings with automatic secret injection.

    This class demonstrates various features:
    - Automatic secret injection from 1Password
    - Type preservation for non-secret values
    - Field validators
    - Nested configuration models
    - Environment variable support
    """

    # Application settings
    app_name: str = "MyApp"
    debug: bool = False
    log_level: str = "INFO"

    # Secrets with defaults
    secret_key: str = "op://vault/app/secret_key"
    jwt_secret: str = "op://vault/app/jwt_secret"

    # Configuration with validation
    port: int = Field(default=8080, ge=1, le=65535)
    workers: int = Field(default=4, ge=1, le=32)

    # Nested configuration
    database: DatabaseConfig
    api: APIConfig


class EnvSettings(OnePasswordSettings):
    """Settings loaded from environment variables with automatic secret injection.

    Environment variables with the APP_ prefix will be loaded:
    - APP_DATABASE_URL: Database connection string
    - APP_API_KEY: API key
    - APP_DEBUG: Debug mode flag
    """

    model_config = SettingsConfigDict(
        env_prefix="APP_",
        env_file=".env",
        env_file_encoding="utf-8",
    )

    database_url: str
    api_key: str
    debug: bool = False


def example_basic_settings() -> None:
    """Example of basic settings with automatic secret injection."""
    print("Example 1: Basic Settings")
    print("-" * 50)

    try:
        # Create settings - secrets are automatically injected
        settings = AppSettings(
            database=DatabaseConfig(),
            api=APIConfig(),
        )

        print(f"App name: {settings.app_name}")
        print(f"Debug: {settings.debug}")
        print(f"Port: {settings.port}")
        print(f"Workers: {settings.workers}")
        print(f"Secret key length: {len(settings.secret_key)} characters")
        print(f"Database host: {settings.database.host}")
        print(f"Database port: {settings.database.port}")
        print(f"API endpoint: {settings.api.endpoint}")
        print(f"API timeout: {settings.api.timeout}")
    except Exception as e:
        print(f"Error: {e}")

    print()


def example_database_config() -> None:
    """Example of database configuration with connection string."""
    print("Example 2: Database Configuration")
    print("-" * 50)

    try:
        # Create database configuration
        db_config = DatabaseConfig()

        print(f"Host: {db_config.host}")
        print(f"Port: {db_config.port}")
        print(f"Database: {db_config.database}")
        print(f"Username length: {len(db_config.username)} characters")
        print(f"Password length: {len(db_config.password)} characters")
        print(f"Connection string: {db_config.connection_string}")
    except Exception as e:
        print(f"Error: {e}")

    print()


def example_override_defaults() -> None:
    """Example of overriding default values."""
    print("Example 3: Override Defaults")
    print("-" * 50)

    try:
        # Override default values while keeping secret injection
        settings = AppSettings(
            app_name="CustomApp",
            debug=True,
            port=9000,
            workers=8,
            database=DatabaseConfig(
                host="custom.example.com",
                port=3306,
                database="custom_db",
            ),
            api=APIConfig(
                endpoint="https://custom-api.example.com",
                timeout=60,
            ),
        )

        print(f"App name: {settings.app_name}")
        print(f"Debug: {settings.debug}")
        print(f"Port: {settings.port}")
        print(f"Workers: {settings.workers}")
        print(f"Database host: {settings.database.host}")
        print(f"Database port: {settings.database.port}")
        print(f"API endpoint: {settings.api.endpoint}")
    except Exception as e:
        print(f"Error: {e}")

    print()


def example_env_settings() -> None:
    """Example of loading settings from environment variables."""
    print("Example 4: Environment Variable Settings")
    print("-" * 50)

    print("Set these environment variables to test:")
    print('  export APP_DATABASE_URL="op://vault/database/url"')
    print('  export APP_API_KEY="op://vault/api/key"')
    print('  export APP_DEBUG="true"')
    print()

    try:
        # Load settings from environment variables
        settings = EnvSettings()

        print(f"Database URL length: {len(settings.database_url)} characters")
        print(f"API Key length: {len(settings.api_key)} characters")
        print(f"Debug: {settings.debug}")
    except Exception as e:
        print(f"Note: {e}")
        print("(This is expected if environment variables are not set)")

    print()


def example_validation() -> None:
    """Example of Pydantic validation after secret injection."""
    print("Example 5: Validation After Secret Injection")
    print("-" * 50)

    try:
        # Valid port
        settings = AppSettings(
            port=8080,
            database=DatabaseConfig(),
            api=APIConfig(),
        )
        print(f"Valid port: {settings.port}")

        # This would fail validation
        try:
            _invalid_settings = AppSettings(
                port=99999,  # Port out of range
                database=DatabaseConfig(),
                api=APIConfig(),
            )
        except Exception as e:
            print(f"Invalid port error (expected): {type(e).__name__}")

    except Exception as e:
        print(f"Error: {e}")

    print()


def example_type_preservation() -> None:
    """Example showing that non-secret types are preserved."""
    print("Example 6: Type Preservation")
    print("-" * 50)

    try:
        settings = AppSettings(
            database=DatabaseConfig(),
            api=APIConfig(),
        )

        print(f"Port: {settings.port} (type: {type(settings.port).__name__})")
        print(f"Workers: {settings.workers} (type: {type(settings.workers).__name__})")
        print(f"Debug: {settings.debug} (type: {type(settings.debug).__name__})")
        print(f"Database port: {settings.database.port} (type: {type(settings.database.port).__name__})")
        print(f"API timeout: {settings.api.timeout} (type: {type(settings.api.timeout).__name__})")
    except Exception as e:
        print(f"Error: {e}")

    print()


def main() -> None:
    """Run all examples."""
    print("=" * 50)
    print("Pydantic Settings with 1Password Examples")
    print("=" * 50)
    print()

    # Run all examples
    example_basic_settings()
    example_database_config()
    example_override_defaults()
    example_env_settings()
    example_validation()
    example_type_preservation()

    print("=" * 50)
    print("Examples completed!")
    print("=" * 50)


if __name__ == "__main__":
    main()
