"""Example usage of BaseAPIClient for making authenticated API requests.

This example demonstrates:
1. Creating a custom API client by inheriting BaseAPIClient
2. Making requests with automatic authentication header injection
3. Using API key and MetaInfo JWT for authentication

Usage
-----
Start the server first:
    uv run examples/transfer/credential_middleware_example.py

Then run this client:
    uv run examples/transfer/base_sdk_example.py

Run specific example:
    uv run examples/transfer/base_sdk_example.py 1
    uv run examples/transfer/base_sdk_example.py 2

List available examples:
    uv run examples/transfer/base_sdk_example.py --list
"""

import asyncio
import os
import sys
from pathlib import Path

# Set NO_PROXY to allow localhost connections
os.environ["NO_PROXY"] = "localhost,127.0.0.1"

# Add package to path for local development
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src"))


async def example_1_basic_client():
    """Example 1: Basic API client without authentication."""
    print("=== Example 1: Basic API Client (No Auth) ===")

    from hezor_common.transfer.base_sdk.base_api_client import BaseAPIClient

    # Create client without authentication
    async with BaseAPIClient(base_url="http://localhost:8888") as client:
        # Call public endpoint
        response = await client.get("/")
        data = response.json()
        print("✓ Public endpoint response:")
        print(f"  Message: {data['message']}")
        print()

        # Generate test token
        token_response = await client.get("/generate-token")
        token_data = token_response.json()
        print("✓ Generated test JWT token:")
        print(f"  Subject: {token_data['meta_info']['subject']}")
        print(f"  Token (first 50 chars): {token_data['jwt_token'][:50]}...")
        print()

    print()


async def example_2_client_with_api_key():
    """Example 2: API client with API key authentication."""
    print("=== Example 2: Client with API Key ===")

    from hezor_common.transfer.base_sdk.base_api_client import BaseAPIClient

    # Create client with API key
    async with BaseAPIClient(
        base_url="http://localhost:8888",
        api_key="test-api-key",
    ) as client:
        # Call protected endpoint that requires API key
        response = await client.get("/protected")
        data = response.json()
        print("✓ Protected endpoint (API key) response:")
        print(f"  Message: {data['message']}")
        print(f"  API Key Prefix: {data['api_key_prefix']}")
        print()

        # Call flexible endpoint with API key
        flex_response = await client.get("/flexible")
        flex_data = flex_response.json()
        print("✓ Flexible endpoint response:")
        print(f"  Message: {flex_data['message']}")
        print(f"  Auth Type: {flex_data['auth_type']}")
        print()

    print()


async def example_3_client_with_metainfo():
    """Example 3: API client with MetaInfo JWT authentication."""
    print("=== Example 3: Client with MetaInfo JWT ===")

    from hezor_common.transfer.base_sdk.base_api_client import BaseAPIClient
    from hezor_common.transfer.base_sdk.meta_info import MetaInfo

    # Create MetaInfo
    meta = MetaInfo(
        subject="client_user",
        subject_code="client_123",
        caller_id="base_sdk_example",
        data_coverage="202401-202412",
        creation_slug="example_client",
        creation_name="示例客户端",
    )

    # Create client with MetaInfo
    async with BaseAPIClient(
        base_url="http://localhost:8888",
        meta_info=meta,
    ) as client:
        # Call endpoint that requires MetaInfo
        response = await client.get("/user-info")
        data = response.json()
        print("✓ User info endpoint (MetaInfo) response:")
        if "message" in data:
            print(f"  Message: {data['message']}")
            print(f"  Subject: {data['user']['subject']}")
            print(f"  Subject Code: {data['user']['subject_code']}")
            print(f"  Caller ID: {data['user']['caller_id']}")
        else:
            print(f"  Response: {data}")
        print()

        # Call flexible endpoint with MetaInfo
        flex_response = await client.get("/flexible")
        flex_data = flex_response.json()
        print("✓ Flexible endpoint response:")
        print(f"  Message: {flex_data['message']}")
        print(f"  Auth Type: {flex_data['auth_type']}")
        print(f"  Subject: {flex_data['subject']}")
        print()

    print()


async def example_4_custom_client_class():
    """Example 4: Create custom API client by inheriting BaseAPIClient."""
    print("=== Example 4: Custom API Client Class ===")

    import httpx

    from hezor_common.transfer.base_sdk.base_api_client import BaseAPIClient
    from hezor_common.transfer.base_sdk.meta_info import MetaInfo

    class ExampleAPIClient(BaseAPIClient):
        """Custom API client for the example server."""

        async def get_root_info(self) -> httpx.Response:
            """Get root endpoint information."""
            return await self.get("/")

        async def generate_test_token(self) -> httpx.Response:
            """Generate a test JWT token."""
            return await self.get("/generate-token")

        async def check_protected(self) -> httpx.Response:
            """Check protected endpoint (requires API key)."""
            return await self.get("/protected")

        async def get_user_info(self) -> httpx.Response:
            """Get user information (requires MetaInfo)."""
            return await self.get("/user-info")

        async def check_flexible(self) -> httpx.Response:
            """Check flexible endpoint (requires either credential)."""
            return await self.get("/flexible")

        async def check_optional(self) -> httpx.Response:
            """Check optional endpoint (credentials optional)."""
            return await self.get("/optional")

    # Use custom client with both credentials
    meta = MetaInfo(
        subject="custom_client_user",
        subject_code="custom_123",
        caller_id="custom_api_client",
        data_coverage="202401-202412",
        creation_slug="custom_example",
        creation_name="自定义客户端",
    )

    async with ExampleAPIClient(
        base_url="http://localhost:8888",
        api_key="test-api-key",
        meta_info=meta,
    ) as client:
        # Use custom methods
        root = await client.get_root_info()
        root_data = root.json()
        print("✓ Root info:")
        print(f"  Message: {root_data['message']}")
        print()

        protected = await client.check_protected()
        protected_data = protected.json()
        print("✓ Protected endpoint:")
        print(f"  Message: {protected_data['message']}")
        print()

        user_info = await client.get_user_info()
        user_data = user_info.json()
        print("✓ User info:")
        print(f"  Subject: {user_data['user']['subject']}")
        print()

        flexible = await client.check_flexible()
        flex_data = flexible.json()
        print("✓ Flexible endpoint:")
        print(f"  Auth Type: {flex_data['auth_type']}")
        print(f"  Message: {flex_data['message']}")
        print()

        optional = await client.check_optional()
        optional_data = optional.json()
        print("✓ Optional endpoint:")
        print(f"  Message: {optional_data['message']}")
        print()

    print()


async def example_5_error_handling():
    """Example 5: Error handling with different credentials."""
    print("=== Example 5: Error Handling ===")

    from hezor_common.transfer.base_sdk.base_api_client import BaseAPIClient

    # Test 1: No credentials on protected endpoint
    print("Test 1: Calling protected endpoint without API key")
    async with BaseAPIClient(base_url="http://localhost:8888") as client:
        try:
            response = await client.get("/protected")
            response.raise_for_status()
            print("  ✗ Should have raised an error")
        except Exception as e:
            print(f"  ✓ Expected error: {type(e).__name__}")
    print()

    # Test 2: Any API key is accepted by the middleware (it only extracts, doesn't validate)
    print("Test 2: Calling protected endpoint with any API key (middleware accepts all)")
    async with BaseAPIClient(
        base_url="http://localhost:8888",
        api_key="any-key-works",
    ) as client:
        response = await client.get("/protected")
        response.raise_for_status()
        data = response.json()
        print(f"  ✓ Response: {data['message']}")
    print()

    # Test 3: Optional endpoint without credentials (should work)
    print("Test 3: Calling optional endpoint without credentials")
    async with BaseAPIClient(base_url="http://localhost:8888") as client:
        response = await client.get("/optional")
        data = response.json()
        print(f"  ✓ Response: {data['message']}")
    print()

    print()


def list_examples():
    """List all available examples."""
    examples = {
        1: ("Basic API client (no auth)", example_1_basic_client),
        2: ("Client with API key", example_2_client_with_api_key),
        3: ("Client with MetaInfo JWT", example_3_client_with_metainfo),
        4: ("Custom API client class", example_4_custom_client_class),
        5: ("Error handling", example_5_error_handling),
    }

    print("Available examples:")
    for num, (name, _) in examples.items():
        print(f"  {num}. {name}")
    print()
    print("Usage:")
    print(f"  uv run {sys.argv[0]} [example_number]")
    print(f"  uv run {sys.argv[0]}              # Run all examples")
    print(f"  uv run {sys.argv[0]} --list       # List examples")
    print()
    print("Note: Make sure the server is running first:")
    print("  uv run examples/transfer/credential_middleware_example.py")

    return examples


async def main():
    """Run examples based on command line arguments."""
    examples = {
        1: ("Basic API client (no auth)", example_1_basic_client),
        2: ("Client with API key", example_2_client_with_api_key),
        3: ("Client with MetaInfo JWT", example_3_client_with_metainfo),
        4: ("Custom API client class", example_4_custom_client_class),
        5: ("Error handling", example_5_error_handling),
    }

    # Parse command line arguments
    if len(sys.argv) > 1:
        arg = sys.argv[1]

        if arg in ["--list", "-l", "list"]:
            list_examples()
            return

        try:
            example_num = int(arg)
            if example_num not in examples:
                print(f"Error: Example {example_num} not found.")
                print()
                list_examples()
                sys.exit(1)

            # Run single example
            name, func = examples[example_num]
            print("=" * 60)
            print(f"BaseAPIClient - Example {example_num}")
            print("=" * 60)
            print()
            await func()
            print("=" * 60)
            print(f"Example {example_num} completed successfully!")
            print("=" * 60)
            return

        except ValueError:
            print(f"Error: Invalid argument '{arg}'")
            print()
            list_examples()
            sys.exit(1)

    # Run all examples
    print("=" * 60)
    print("BaseAPIClient - Usage Examples")
    print("=" * 60)
    print()

    for func in [
        example_1_basic_client,
        example_2_client_with_api_key,
        example_3_client_with_metainfo,
        example_4_custom_client_class,
        example_5_error_handling,
    ]:
        await func()

    print("=" * 60)
    print("All examples completed successfully!")
    print("=" * 60)


if __name__ == "__main__":
    asyncio.run(main())
