"""Example usage of FastAPI credential extraction middleware.

This example demonstrates a simple FastAPI server with:
- CredentialMiddleware for extracting API key and MetaInfo JWT
- Public routes (no authentication)
- Protected routes (require API key or MetaInfo)
- Optional authentication routes

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

Test with curl:
    # Public route (no auth required)
    curl http://localhost:8888/

    # Generate test JWT token
    curl http://localhost:8888/generate-token

    # Protected route (requires API key)
    curl -H "Authorization: Bearer test-api-key" http://localhost:8888/protected

    # Protected route (requires MetaInfo JWT)
    curl -H "X-META-INFO: <jwt_token>" http://localhost:8888/user-info

    # Optional auth route
    curl http://localhost:8888/optional
    curl -H "X-META-INFO: <jwt_token>" http://localhost:8888/optional
"""

import sys
from pathlib import Path

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


def main():
    """Run FastAPI server with credential middleware."""
    from fastapi import Depends, FastAPI

    from hezor_common.transfer.base_sdk.constants import (
        ANONYMOUS_HEADER_PRIVATE_KEY,
        ANONYMOUS_HEADER_PRIVATE_KEY_PASSWORD,
    )
    from hezor_common.transfer.base_sdk.meta_info import MetaInfo
    from hezor_common.transfer.middlewares import (
        CredentialMiddleware,
        get_meta_info,
        require_api_key,
        require_credentials,
        require_meta_info,
    )

    app = FastAPI(
        title="Credential Middleware Example",
        description="Example server demonstrating credential extraction and validation",
    )

    # Add credential middleware - no configuration needed, uses anonymous key by default
    app.add_middleware(CredentialMiddleware)

    @app.get("/")
    async def root():
        """Public route - no authentication required."""
        return {
            "message": "Welcome to Credential Middleware Example",
            "endpoints": {
                "public": {
                    "/": "This endpoint",
                    "/generate-token": "Generate a test JWT token",
                },
                "protected": {
                    "/protected": "Requires API key (Authorization: Bearer test-api-key)",
                    "/user-info": "Requires MetaInfo JWT (X-META-INFO header)",
                    "/flexible": "Requires either API key or MetaInfo",
                },
                "optional": {
                    "/optional": "Optional authentication",
                },
            },
        }

    @app.get("/generate-token")
    async def generate_token():
        """Generate a test JWT token for testing."""
        # Create test MetaInfo
        meta = MetaInfo(
            subject="test_user",
            subject_code="user_123",
            caller_id="example_caller",
            data_coverage="202401-202412",
            creation_slug="test_creation",
            creation_name="测试创建",
        )

        # Generate JWT using anonymous key
        jwt_header = meta.to_request_header(
            private_key_pem=ANONYMOUS_HEADER_PRIVATE_KEY,
            password=ANONYMOUS_HEADER_PRIVATE_KEY_PASSWORD,
            expires_in=3600,
        )

        jwt_token = jwt_header["X-META-INFO"]

        return {
            "message": "Test JWT token generated",
            "meta_info": {
                "subject": meta.subject,
                "subject_code": meta.subject_code,
                "caller_id": meta.caller_id,
            },
            "jwt_token": jwt_token,
            "usage": f'curl -H "X-META-INFO: {jwt_token}" http://localhost:8888/user-info',
        }

    @app.get("/protected")
    async def protected_route(api_key: str = Depends(require_api_key)):
        """Protected route - requires valid API key."""
        return {
            "message": "API key validated successfully",
            "api_key_prefix": f"{api_key[:6]}***",
        }

    @app.get("/user-info")
    async def user_info(meta: MetaInfo = Depends(require_meta_info)):
        """Protected route - requires valid MetaInfo JWT."""
        return {
            "message": "MetaInfo validated successfully",
            "user": {
                "subject": meta.subject,
                "subject_code": meta.subject_code,
                "caller_id": meta.caller_id,
                "data_coverage": meta.data_coverage,
                "creation": {
                    "slug": meta.creation_slug,
                    "name": meta.creation_name,
                },
            },
        }

    @app.get("/flexible")
    async def flexible_route(cred: tuple = Depends(require_credentials)):
        """Flexible route - accepts either API key or MetaInfo."""
        api_key, meta_info = cred

        if api_key and meta_info:
            return {
                "message": "Both credentials provided",
                "auth_type": "api_key + meta_info",
                "api_key_prefix": f"{api_key[:6]}***",
                "subject": meta_info.subject,
            }
        elif api_key:
            return {
                "message": "API key authentication",
                "auth_type": "api_key",
                "api_key_prefix": f"{api_key[:6]}***",
            }
        else:
            return {
                "message": "MetaInfo authentication",
                "auth_type": "meta_info",
                "subject": meta_info.subject,
            }

    @app.get("/optional")
    async def optional_route(meta: MetaInfo | None = Depends(get_meta_info)):
        """Optional authentication - provides different data based on auth status."""
        if meta:
            return {
                "message": "Authenticated request",
                "user": {
                    "subject": meta.subject,
                    "subject_code": meta.subject_code,
                },
            }
        return {
            "message": "Anonymous request",
            "tip": "Provide X-META-INFO header to access user information",
        }

    # Run server
    print("=" * 60)
    print("Starting FastAPI server with CredentialMiddleware")
    print("=" * 60)
    print()
    print("Server: http://localhost:8888")
    print("Docs:   http://localhost:8888/docs")
    print()
    print("Quick start:")
    print("  1. Visit http://localhost:8888/ for available endpoints")
    print("  2. Get test token: curl http://localhost:8888/generate-token")
    print("  3. Test protected route with API key:")
    print('     curl -H "Authorization: Bearer test-api-key" http://localhost:8888/protected')
    print()

    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8888)


if __name__ == "__main__":
    main()
