#!/usr/bin/env python3
"""
Proof of Concept: External API Authentication Test
Tests the external authentication API at https://pj-auth-api.vercel.app
"""

import asyncio
import json
from datetime import datetime
from typing import Dict, Any, Optional
import httpx
from pydantic import BaseModel, Field


class UserInfo(BaseModel):
    """User information from external API"""
    id: str
    name: str
    email: str
    job_title: Optional[str] = Field(None, alias="jobTitle")
    office_location: Optional[str] = Field(None, alias="officeLocation")
    business_phones: list[str] = Field(default_factory=list, alias="businessPhones")


class AuthSuccessData(BaseModel):
    """Successful authentication response data"""
    access_token: str
    id_token: str
    expires_in: int
    token_type: str
    user_info: UserInfo = Field(alias="userInfo")
    issued_at: str = Field(alias="issuedAt")
    expires_at: str = Field(alias="expiresAt")


class AuthSuccessResponse(BaseModel):
    """Successful authentication response"""
    success: bool
    message: str
    data: AuthSuccessData
    timestamp: str


class AuthErrorResponse(BaseModel):
    """Failed authentication response"""
    success: bool
    error: str
    code: str
    timestamp: str


class ExternalAuthClient:
    """Client for external authentication API"""

    def __init__(self, base_url: str = "https://pj-auth-api.vercel.app", timeout: int = 30):
        self.base_url = base_url
        self.timeout = timeout
        self.endpoint = "/api/auth/login"

    async def authenticate(self, username: str, password: str) -> Dict[str, Any]:
        """
        Authenticate user with external API

        Args:
            username: User email/username
            password: User password

        Returns:
            Authentication result dictionary
        """
        url = f"{self.base_url}{self.endpoint}"

        print(f"ℹ Endpoint: POST {url}")
        print(f"ℹ Username: {username}")
        print(f"ℹ Timestamp: {datetime.now().isoformat()}")
        print()

        async with httpx.AsyncClient() as client:
            try:
                # Make authentication request
                start_time = datetime.now()
                response = await client.post(
                    url,
                    json={"username": username, "password": password},
                    timeout=self.timeout
                )
                elapsed = (datetime.now() - start_time).total_seconds()

                # Print response details
                print("Response Details:")
                print(f"  Status Code: {response.status_code}")
                print(f"  Response Time: {elapsed:.3f}s")
                print(f"  Content-Type: {response.headers.get('content-type', 'N/A')}")
                print()

                # Parse response
                response_data = response.json()
                print("Response Body:")
                print(json.dumps(response_data, indent=2, ensure_ascii=False))
                print()

                # Handle success/failure
                if response.status_code == 200:
                    auth_response = AuthSuccessResponse(**response_data)
                    return {
                        "success": True,
                        "status_code": response.status_code,
                        "data": auth_response.dict(),
                        "user_display_name": auth_response.data.user_info.name,
                        "user_email": auth_response.data.user_info.email,
                        "token": auth_response.data.access_token,
                        "expires_in": auth_response.data.expires_in,
                        "expires_at": auth_response.data.expires_at
                    }
                elif response.status_code == 401:
                    error_response = AuthErrorResponse(**response_data)
                    return {
                        "success": False,
                        "status_code": response.status_code,
                        "error": error_response.error,
                        "code": error_response.code
                    }
                else:
                    return {
                        "success": False,
                        "status_code": response.status_code,
                        "error": f"Unexpected status code: {response.status_code}",
                        "response": response_data
                    }

            except httpx.TimeoutException:
                print(f"❌ Request timeout after {self.timeout} seconds")
                return {
                    "success": False,
                    "error": "Request timeout",
                    "code": "TIMEOUT"
                }
            except httpx.RequestError as e:
                print(f"❌ Request error: {e}")
                return {
                    "success": False,
                    "error": str(e),
                    "code": "REQUEST_ERROR"
                }
            except Exception as e:
                print(f"❌ Unexpected error: {e}")
                return {
                    "success": False,
                    "error": str(e),
                    "code": "UNKNOWN_ERROR"
                }


async def test_authentication():
    """Test authentication with different scenarios"""
    client = ExternalAuthClient()

    # Test scenarios
    test_cases = [
        {
            "name": "Valid Credentials (Example)",
            "username": "ymirliu@panjit.com.tw",
            "password": "correct_password",  # Replace with actual password for testing
            "expected": "success"
        },
        {
            "name": "Invalid Credentials",
            "username": "test@example.com",
            "password": "wrong_password",
            "expected": "failure"
        }
    ]

    for i, test_case in enumerate(test_cases, 1):
        print(f"{'='*60}")
        print(f"Test Case {i}: {test_case['name']}")
        print(f"{'='*60}")

        result = await client.authenticate(
            username=test_case["username"],
            password=test_case["password"]
        )

        # Analyze result
        print("\nAnalysis:")
        if result["success"]:
            print("✅ Authentication successful")
            print(f"  User: {result.get('user_display_name', 'N/A')}")
            print(f"  Email: {result.get('user_email', 'N/A')}")
            print(f"  Token expires in: {result.get('expires_in', 0)} seconds")
            print(f"  Expires at: {result.get('expires_at', 'N/A')}")
        else:
            print("❌ Authentication failed")
            print(f"  Error: {result.get('error', 'Unknown error')}")
            print(f"  Code: {result.get('code', 'N/A')}")

        print("\n")


async def test_token_validation():
    """Test token validation and refresh logic"""
    # This would be implemented when we have a valid token
    print("Token validation test - To be implemented with actual tokens")
    pass


def main():
    """Main entry point"""
    print("External Authentication API Test")
    print("================================\n")

    # Run tests
    asyncio.run(test_authentication())

    print("\nTest completed!")
    print("\nNotes for implementation:")
    print("1. Use httpx for async HTTP requests (already in requirements)")
    print("2. Store tokens securely (consider encryption)")
    print("3. Implement automatic token refresh before expiration")
    print("4. Handle network failures with retry logic")
    print("5. Map external user ID to local user records")
    print("6. Display user 'name' field in UI instead of username")


if __name__ == "__main__":
    main()