"""
Cross-switch router for camera-to-monitor routing operations
"""
from typing import Optional
from fastapi import APIRouter, Depends, status, HTTPException, Query, Request
from sqlalchemy.ext.asyncio import AsyncSession
import structlog

from models import get_db
from schemas.crossswitch import (
    CrossSwitchRequest,
    CrossSwitchResponse,
    ClearMonitorRequest,
    ClearMonitorResponse,
    RoutingStateResponse,
    RouteHistoryResponse
)
from services.crossswitch_service import CrossSwitchService
from middleware.auth_middleware import (
    require_operator,
    require_viewer,
    get_current_user,
    get_client_ip
)
from models.user import User

logger = structlog.get_logger()

router = APIRouter(
    prefix="/api/v1/crossswitch",
    tags=["crossswitch"]
)


@router.post(
    "",
    response_model=CrossSwitchResponse,
    status_code=status.HTTP_200_OK,
    summary="Execute cross-switch",
    description="Route a camera to a monitor (requires Operator role or higher)",
    dependencies=[Depends(require_operator)]  # Requires at least operator role
)
async def execute_crossswitch(
    request: Request,
    crossswitch_request: CrossSwitchRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_operator)
):
    """
    Execute cross-switch operation (route camera to monitor)

    **Authentication Required:**
    - Minimum role: Operator
    - Viewers cannot execute cross-switching (read-only)

    **Request Body:**
    - `camera_id`: Camera ID to display (must be positive integer)
    - `monitor_id`: Monitor ID to display on (must be positive integer)
    - `mode`: Cross-switch mode (default: 0=normal, optional)

    **Response:**
    - `success`: Whether operation succeeded
    - `message`: Success message
    - `route`: Route information including execution details

    **Side Effects:**
    - Clears any existing camera on the target monitor
    - Creates database record of routing change
    - Creates audit log entry
    - Invalidates monitor cache

    **Errors:**
    - `400 Bad Request`: Invalid camera or monitor ID
    - `403 Forbidden`: User does not have Operator role
    - `404 Not Found`: Camera or monitor not found
    - `500 Internal Server Error`: SDK Bridge communication failure
    """
    crossswitch_service = CrossSwitchService(db)

    logger.info("execute_crossswitch_request",
               user_id=str(current_user.id),
               username=current_user.username,
               camera_id=crossswitch_request.camera_id,
               monitor_id=crossswitch_request.monitor_id,
               mode=crossswitch_request.mode)

    try:
        result = await crossswitch_service.execute_crossswitch(
            camera_id=crossswitch_request.camera_id,
            monitor_id=crossswitch_request.monitor_id,
            user_id=current_user.id,
            username=current_user.username,
            mode=crossswitch_request.mode,
            ip_address=get_client_ip(request)
        )

        logger.info("execute_crossswitch_success",
                   user_id=str(current_user.id),
                   camera_id=crossswitch_request.camera_id,
                   monitor_id=crossswitch_request.monitor_id)

        return result

    except Exception as e:
        logger.error("execute_crossswitch_failed",
                    user_id=str(current_user.id),
                    camera_id=crossswitch_request.camera_id,
                    monitor_id=crossswitch_request.monitor_id,
                    error=str(e),
                    exc_info=True)

        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Cross-switch operation failed: {str(e)}"
        )


@router.post(
    "/clear",
    response_model=ClearMonitorResponse,
    status_code=status.HTTP_200_OK,
    summary="Clear monitor",
    description="Clear camera from monitor (requires Operator role or higher)",
    dependencies=[Depends(require_operator)]  # Requires at least operator role
)
async def clear_monitor(
    request: Request,
    clear_request: ClearMonitorRequest,
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_operator)
):
    """
    Clear monitor (remove camera from monitor)

    **Authentication Required:**
    - Minimum role: Operator
    - Viewers cannot clear monitors (read-only)

    **Request Body:**
    - `monitor_id`: Monitor ID to clear (must be positive integer)

    **Response:**
    - `success`: Whether operation succeeded
    - `message`: Success message
    - `monitor_id`: Monitor ID that was cleared

    **Side Effects:**
    - Marks existing route as cleared in database
    - Creates audit log entry
    - Invalidates monitor cache

    **Errors:**
    - `400 Bad Request`: Invalid monitor ID
    - `403 Forbidden`: User does not have Operator role
    - `404 Not Found`: Monitor not found
    - `500 Internal Server Error`: SDK Bridge communication failure
    """
    crossswitch_service = CrossSwitchService(db)

    logger.info("clear_monitor_request",
               user_id=str(current_user.id),
               username=current_user.username,
               monitor_id=clear_request.monitor_id)

    try:
        result = await crossswitch_service.clear_monitor(
            monitor_id=clear_request.monitor_id,
            user_id=current_user.id,
            username=current_user.username,
            ip_address=get_client_ip(request)
        )

        logger.info("clear_monitor_success",
                   user_id=str(current_user.id),
                   monitor_id=clear_request.monitor_id)

        return result

    except Exception as e:
        logger.error("clear_monitor_failed",
                    user_id=str(current_user.id),
                    monitor_id=clear_request.monitor_id,
                    error=str(e),
                    exc_info=True)

        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Clear monitor operation failed: {str(e)}"
        )


@router.get(
    "/routing",
    response_model=RoutingStateResponse,
    status_code=status.HTTP_200_OK,
    summary="Get routing state",
    description="Get current routing state (active camera-to-monitor mappings)",
    dependencies=[Depends(require_viewer)]  # All authenticated users can view
)
async def get_routing_state(
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_viewer)
):
    """
    Get current routing state (active routes)

    **Authentication Required:**
    - Minimum role: Viewer (all authenticated users can view routing state)

    **Response:**
    - `routes`: List of active route objects
    - `total`: Total number of active routes

    **Route Object:**
    - `id`: Route UUID
    - `camera_id`: Camera ID
    - `monitor_id`: Monitor ID
    - `mode`: Cross-switch mode
    - `executed_at`: When route was executed
    - `executed_by`: User ID who executed
    - `is_active`: Whether route is active (always true for this endpoint)
    - `camera_name`: Camera name (if available)
    - `monitor_name`: Monitor name (if available)
    """
    crossswitch_service = CrossSwitchService(db)

    logger.info("get_routing_state_request",
               user_id=str(current_user.id),
               username=current_user.username)

    result = await crossswitch_service.get_routing_state()

    logger.info("get_routing_state_response",
               user_id=str(current_user.id),
               count=result["total"])

    return result


@router.get(
    "/history",
    response_model=RouteHistoryResponse,
    status_code=status.HTTP_200_OK,
    summary="Get routing history",
    description="Get historical routing records (all routes including cleared)",
    dependencies=[Depends(require_viewer)]  # All authenticated users can view
)
async def get_routing_history(
    limit: int = Query(100, ge=1, le=1000, description="Maximum records to return"),
    offset: int = Query(0, ge=0, description="Number of records to skip"),
    camera_id: Optional[int] = Query(None, gt=0, description="Filter by camera ID"),
    monitor_id: Optional[int] = Query(None, gt=0, description="Filter by monitor ID"),
    db: AsyncSession = Depends(get_db),
    current_user: User = Depends(require_viewer)
):
    """
    Get routing history (all routes including cleared)

    **Authentication Required:**
    - Minimum role: Viewer

    **Query Parameters:**
    - `limit`: Maximum records to return (1-1000, default: 100)
    - `offset`: Number of records to skip (default: 0)
    - `camera_id`: Filter by camera ID (optional)
    - `monitor_id`: Filter by monitor ID (optional)

    **Response:**
    - `history`: List of historical route objects
    - `total`: Total number of historical records (before pagination)
    - `limit`: Applied limit
    - `offset`: Applied offset

    **Use Cases:**
    - Audit trail of all routing changes
    - Investigate when a camera was last displayed on a monitor
    - Track operator actions
    """
    crossswitch_service = CrossSwitchService(db)

    logger.info("get_routing_history_request",
               user_id=str(current_user.id),
               username=current_user.username,
               limit=limit,
               offset=offset,
               camera_id=camera_id,
               monitor_id=monitor_id)

    result = await crossswitch_service.get_routing_history(
        limit=limit,
        offset=offset,
        camera_id=camera_id,
        monitor_id=monitor_id
    )

    logger.info("get_routing_history_response",
               user_id=str(current_user.id),
               count=len(result["history"]),
               total=result["total"])

    return result
