"""
Internal API for Backend Communication

This FastAPI application provides internal endpoints for the ROA2WEB backend
to communicate with the Telegram bot service. Main purpose is to save
authentication codes generated in the web frontend.

This API runs alongside the Telegram bot and is accessible only internally
(not exposed to public internet).
"""

import logging
import os
from datetime import datetime
from typing import Optional

from fastapi import APIRouter, HTTPException, status
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field

from backend.modules.telegram.db.operations import create_auth_code, get_auth_code
from backend.modules.telegram.db.database import get_database_stats

logger = logging.getLogger(__name__)

# Initialize APIRouter (converted from FastAPI app for unified backend)
internal_api = APIRouter()


# ============================================================================
# REQUEST/RESPONSE MODELS
# ============================================================================

class SaveAuthCodeRequest(BaseModel):
    """
    Request model for saving an authentication code.
    """
    code: str = Field(
        ...,
        description="8-character authentication code",
        min_length=8,
        max_length=8
    )
    telegram_user_id: int = Field(
        ...,
        description="Telegram user ID (if known, otherwise 0)",
        ge=0
    )
    oracle_username: str = Field(
        ...,
        description="Oracle username to link"
    )
    expires_in_minutes: int = Field(
        default=5,
        description="Code expiration time in minutes",
        ge=1,
        le=60
    )


class SaveAuthCodeResponse(BaseModel):
    """
    Response model for save auth code endpoint.
    """
    success: bool = Field(..., description="Whether the operation succeeded")
    code: str = Field(..., description="The saved authentication code")
    expires_at: Optional[str] = Field(None, description="Expiration timestamp (ISO format)")
    message: Optional[str] = Field(None, description="Additional message")


class VerifyAuthCodeRequest(BaseModel):
    """
    Request model for verifying an authentication code.
    """
    code: str = Field(..., description="Authentication code to verify")


class VerifyAuthCodeResponse(BaseModel):
    """
    Response model for verify auth code endpoint.
    """
    valid: bool = Field(..., description="Whether the code is valid")
    oracle_username: Optional[str] = Field(None, description="Oracle username if valid")
    telegram_user_id: Optional[int] = Field(None, description="Telegram user ID if set")
    message: Optional[str] = Field(None, description="Additional message")


class HealthResponse(BaseModel):
    """
    Response model for health check endpoint.
    """
    status: str = Field(..., description="Service status")
    timestamp: str = Field(..., description="Current timestamp")
    database_stats: Optional[dict] = Field(None, description="Database statistics")


# ============================================================================
# ENDPOINTS
# ============================================================================

@internal_api.post(
    "/internal/save-code",
    response_model=SaveAuthCodeResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Save Authentication Code",
    description="Save an authentication code for Telegram linking (called by backend)"
)
async def save_auth_code(request: SaveAuthCodeRequest):
    """
    Save an authentication code to SQLite database.

    This endpoint is called by the FastAPI backend when a user generates
    a linking code in the web frontend.

    **Flow:**
    1. User logs in to web frontend
    2. User clicks "Link Telegram Account"
    3. Backend generates 8-character code
    4. Backend calls this endpoint to save code
    5. Backend returns code to user for display
    6. User sends code to Telegram bot via /start command

    Args:
        request: SaveAuthCodeRequest with code, oracle_username, etc.

    Returns:
        SaveAuthCodeResponse with success status and code details

    Raises:
        HTTPException 400: If code already exists or invalid data
        HTTPException 500: If database operation fails
    """
    try:
        logger.info(
            f"Saving auth code for Oracle user: {request.oracle_username}, "
            f"code: {request.code}"
        )

        # Check if code already exists
        existing_code = await get_auth_code(request.code)

        if existing_code:
            logger.warning(f"Code {request.code} already exists")
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"Code {request.code} already exists. Generate a new unique code."
            )

        # Create auth code in database
        success = await create_auth_code(
            code=request.code,
            telegram_user_id=request.telegram_user_id,
            oracle_username=request.oracle_username,
            expires_in_minutes=request.expires_in_minutes
        )

        if not success:
            logger.error(f"Failed to save auth code {request.code}")
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="Failed to save authentication code to database"
            )

        # Calculate expiration time
        from datetime import timedelta
        expires_at = (datetime.now() + timedelta(minutes=request.expires_in_minutes)).isoformat()

        logger.info(f"Auth code {request.code} saved successfully")

        return SaveAuthCodeResponse(
            success=True,
            code=request.code,
            expires_at=expires_at,
            message=f"Code saved successfully, expires in {request.expires_in_minutes} minutes"
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error saving auth code: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Internal server error: {str(e)}"
        )


@internal_api.post(
    "/internal/verify-code",
    response_model=VerifyAuthCodeResponse,
    summary="Verify Authentication Code",
    description="Verify if an authentication code is valid (without using it)"
)
async def verify_auth_code(request: VerifyAuthCodeRequest):
    """
    Verify if an authentication code exists and is valid.

    This is a read-only check that does NOT mark the code as used.
    Useful for backend to verify codes before user links Telegram account.

    Args:
        request: VerifyAuthCodeRequest with code to verify

    Returns:
        VerifyAuthCodeResponse with validation status

    Raises:
        HTTPException 404: If code not found
    """
    try:
        logger.info(f"Verifying auth code: {request.code}")

        code_data = await get_auth_code(request.code)

        if not code_data:
            return VerifyAuthCodeResponse(
                valid=False,
                message="Code not found"
            )

        # Check if code is expired
        expires_at_str = code_data.get('expires_at')
        expires_at = datetime.fromisoformat(expires_at_str) if expires_at_str else None

        is_expired = expires_at and datetime.now() >= expires_at
        is_used = code_data.get('used', 0) == 1

        if is_expired:
            return VerifyAuthCodeResponse(
                valid=False,
                oracle_username=code_data.get('oracle_username'),
                message="Code expired"
            )

        if is_used:
            return VerifyAuthCodeResponse(
                valid=False,
                oracle_username=code_data.get('oracle_username'),
                message="Code already used"
            )

        # Code is valid
        return VerifyAuthCodeResponse(
            valid=True,
            oracle_username=code_data.get('oracle_username'),
            telegram_user_id=code_data.get('telegram_user_id'),
            message="Code is valid"
        )

    except Exception as e:
        logger.error(f"Error verifying auth code: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Internal server error: {str(e)}"
        )


@internal_api.get(
    "/internal/health",
    response_model=HealthResponse,
    summary="Health Check",
    description="Check if the internal API and database are healthy"
)
async def health_check():
    """
    Health check endpoint.

    Returns service status and database statistics.

    Returns:
        HealthResponse with status and stats
    """
    try:
        # Get database stats
        stats = await get_database_stats()

        return HealthResponse(
            status="healthy",
            timestamp=datetime.now().isoformat(),
            database_stats=stats
        )

    except Exception as e:
        logger.error(f"Health check failed: {e}", exc_info=True)
        return HealthResponse(
            status="unhealthy",
            timestamp=datetime.now().isoformat(),
            database_stats={"error": str(e)}
        )


@internal_api.get(
    "/internal/stats",
    summary="Database Statistics",
    description="Get detailed database statistics"
)
async def get_stats():
    """
    Get detailed database statistics.

    Returns:
        JSON with database statistics
    """
    try:
        stats = await get_database_stats()

        return JSONResponse(
            status_code=status.HTTP_200_OK,
            content={
                "success": True,
                "timestamp": datetime.now().isoformat(),
                "stats": stats
            }
        )

    except Exception as e:
        logger.error(f"Error getting stats: {e}", exc_info=True)
        return JSONResponse(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            content={
                "success": False,
                "error": str(e)
            }
        )


# ============================================================================
# EXCEPTION HANDLERS
# ============================================================================

# ============================================================================
# NOTE: Exception handlers and startup/shutdown events removed
# These are FastAPI-specific and don't work with APIRouter
# The unified backend (main.py) handles these at the app level
# ============================================================================

# @internal_api.exception_handler(Exception) - Not supported by APIRouter
# async def global_exception_handler(request, exc):
#     """Global exception handler - moved to main.py"""
#     pass

# @internal_api.on_event("startup") - Not supported by APIRouter
# async def startup_event():
#     """Startup event - handled by main.py lifespan"""
#     pass

# @internal_api.on_event("shutdown") - Not supported by APIRouter
# async def shutdown_event():
#     """Shutdown event - handled by main.py lifespan"""
#     pass


# Export the APIRouter
__all__ = ['internal_api']
