"""
Monitor router for monitor discovery and information
"""
from fastapi import APIRouter, Depends, status, HTTPException, Query
from fastapi.responses import JSONResponse
import structlog

from schemas.monitor import MonitorListResponse, MonitorDetailResponse
from services.monitor_service import MonitorService
from middleware.auth_middleware import require_viewer, get_current_user
from models.user import User

logger = structlog.get_logger()

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


@router.get(
    "",
    response_model=MonitorListResponse,
    status_code=status.HTTP_200_OK,
    summary="List all monitors",
    description="Get list of all monitors (video outputs) from GeViScope",
    dependencies=[Depends(require_viewer)]  # Requires at least viewer role
)
async def list_monitors(
    use_cache: bool = Query(True, description="Use Redis cache (60s TTL)"),
    current_user: User = Depends(require_viewer)
):
    """
    Get list of all monitors from GeViScope SDK Bridge

    **Authentication Required:**
    - Minimum role: Viewer (all authenticated users can read monitors)

    **Query Parameters:**
    - `use_cache`: Use Redis cache (default: true, TTL: 60s)

    **Response:**
    - `monitors`: List of monitor objects
    - `total`: Total number of monitors

    **Caching:**
    - Results are cached in Redis for 60 seconds
    - Set `use_cache=false` to bypass cache and fetch fresh data

    **Monitor Object:**
    - `id`: Monitor ID (output channel number)
    - `name`: Monitor name
    - `description`: Monitor description
    - `status`: Monitor status (active, idle, offline, unknown)
    - `current_camera_id`: Currently displayed camera ID (None if idle)
    - `last_update`: Last update timestamp
    """
    monitor_service = MonitorService()

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

    result = await monitor_service.list_monitors(use_cache=use_cache)

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

    return result


@router.get(
    "/{monitor_id}",
    response_model=MonitorDetailResponse,
    status_code=status.HTTP_200_OK,
    summary="Get monitor details",
    description="Get detailed information about a specific monitor",
    dependencies=[Depends(require_viewer)]  # Requires at least viewer role
)
async def get_monitor(
    monitor_id: int,
    use_cache: bool = Query(True, description="Use Redis cache (60s TTL)"),
    current_user: User = Depends(require_viewer)
):
    """
    Get detailed information about a specific monitor

    **Authentication Required:**
    - Minimum role: Viewer (all authenticated users can read monitors)

    **Path Parameters:**
    - `monitor_id`: Monitor ID (output channel number)

    **Query Parameters:**
    - `use_cache`: Use Redis cache (default: true, TTL: 60s)

    **Response:**
    - Monitor object with detailed information including current camera assignment

    **Errors:**
    - `404 Not Found`: Monitor with specified ID does not exist
    """
    monitor_service = MonitorService()

    logger.info("get_monitor_request",
               user_id=str(current_user.id),
               username=current_user.username,
               monitor_id=monitor_id,
               use_cache=use_cache)

    monitor = await monitor_service.get_monitor(monitor_id, use_cache=use_cache)

    if not monitor:
        logger.warning("monitor_not_found",
                      user_id=str(current_user.id),
                      monitor_id=monitor_id)
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Monitor with ID {monitor_id} not found"
        )

    logger.info("get_monitor_response",
               user_id=str(current_user.id),
               monitor_id=monitor_id,
               current_camera=monitor.get("current_camera_id"))

    return monitor


@router.post(
    "/refresh",
    response_model=MonitorListResponse,
    status_code=status.HTTP_200_OK,
    summary="Refresh monitor list",
    description="Force refresh monitor list from SDK Bridge (bypass cache)",
    dependencies=[Depends(require_viewer)]
)
async def refresh_monitors(
    current_user: User = Depends(require_viewer)
):
    """
    Force refresh monitor list from GeViScope SDK Bridge

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

    **Response:**
    - Fresh monitor list from SDK Bridge

    **Note:**
    - This endpoint bypasses Redis cache and fetches fresh data
    - Use this when you need real-time monitor status
    - Cache is automatically invalidated and updated with fresh data
    """
    monitor_service = MonitorService()

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

    result = await monitor_service.refresh_monitor_list()

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

    return result


@router.get(
    "/search/{query}",
    response_model=MonitorListResponse,
    status_code=status.HTTP_200_OK,
    summary="Search monitors",
    description="Search monitors by name or description",
    dependencies=[Depends(require_viewer)]
)
async def search_monitors(
    query: str,
    current_user: User = Depends(require_viewer)
):
    """
    Search monitors by name or description

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

    **Path Parameters:**
    - `query`: Search query string (case-insensitive)

    **Response:**
    - List of monitors matching the search query

    **Search:**
    - Searches monitor name and description fields
    - Case-insensitive partial match
    """
    monitor_service = MonitorService()

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

    monitors = await monitor_service.search_monitors(query)

    logger.info("search_monitors_response",
               user_id=str(current_user.id),
               query=query,
               matches=len(monitors))

    return {
        "monitors": monitors,
        "total": len(monitors)
    }


@router.get(
    "/filter/available",
    response_model=MonitorListResponse,
    status_code=status.HTTP_200_OK,
    summary="Get available monitors",
    description="Get list of available (idle/free) monitors",
    dependencies=[Depends(require_viewer)]
)
async def get_available_monitors(
    current_user: User = Depends(require_viewer)
):
    """
    Get list of available (idle/free) monitors

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

    **Response:**
    - List of monitors with no camera assigned (current_camera_id is None or 0)

    **Use Case:**
    - Use this endpoint to find monitors available for cross-switching
    """
    monitor_service = MonitorService()

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

    monitors = await monitor_service.get_available_monitors()

    logger.info("get_available_monitors_response",
               user_id=str(current_user.id),
               count=len(monitors))

    return {
        "monitors": monitors,
        "total": len(monitors)
    }


@router.get(
    "/filter/active",
    response_model=MonitorListResponse,
    status_code=status.HTTP_200_OK,
    summary="Get active monitors",
    description="Get list of active monitors (displaying a camera)",
    dependencies=[Depends(require_viewer)]
)
async def get_active_monitors(
    current_user: User = Depends(require_viewer)
):
    """
    Get list of active monitors (displaying a camera)

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

    **Response:**
    - List of monitors with a camera assigned (current_camera_id is not None)

    **Use Case:**
    - Use this endpoint to see which monitors are currently in use
    """
    monitor_service = MonitorService()

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

    monitors = await monitor_service.get_active_monitors()

    logger.info("get_active_monitors_response",
               user_id=str(current_user.id),
               count=len(monitors))

    return {
        "monitors": monitors,
        "total": len(monitors)
    }


@router.get(
    "/routing",
    status_code=status.HTTP_200_OK,
    summary="Get current routing state",
    description="Get current routing state (monitor -> camera mapping)",
    dependencies=[Depends(require_viewer)]
)
async def get_routing_state(
    current_user: User = Depends(require_viewer)
):
    """
    Get current routing state (monitor -> camera mapping)

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

    **Response:**
    - Dictionary mapping monitor IDs to current camera IDs
    - Format: `{monitor_id: camera_id, ...}`
    - If monitor has no camera, camera_id is null

    **Use Case:**
    - Use this endpoint to get a quick overview of current routing configuration
    """
    monitor_service = MonitorService()

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

    routing = await monitor_service.get_monitor_routing()

    logger.info("get_routing_state_response",
               user_id=str(current_user.id),
               monitors=len(routing))

    return {
        "routing": routing,
        "total_monitors": len(routing)
    }
