"""
Network API router for ClaudeTools.

This module defines all REST API endpoints for managing networks, including
CRUD operations with proper authentication, validation, and error handling.
"""

from uuid import UUID

from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session

from api.database import get_db
from api.middleware.auth import get_current_user
from api.schemas.network import (
    NetworkCreate,
    NetworkResponse,
    NetworkUpdate,
)
from api.services import network_service

# Create router with prefix and tags
router = APIRouter()


@router.get(
    "",
    response_model=dict,
    summary="List all networks",
    description="Retrieve a paginated list of all networks with optional filtering",
    status_code=status.HTTP_200_OK,
)
def list_networks(
    skip: int = Query(
        default=0,
        ge=0,
        description="Number of records to skip for pagination"
    ),
    limit: int = Query(
        default=100,
        ge=1,
        le=1000,
        description="Maximum number of records to return (max 1000)"
    ),
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """
    List all networks with pagination.

    - **skip**: Number of networks to skip (default: 0)
    - **limit**: Maximum number of networks to return (default: 100, max: 1000)

    Returns a list of networks with pagination metadata.

    **Example Request:**
    ```
    GET /api/networks?skip=0&limit=50
    Authorization: Bearer <token>
    ```

    **Example Response:**
    ```json
    {
        "total": 5,
        "skip": 0,
        "limit": 50,
        "networks": [
            {
                "id": "123e4567-e89b-12d3-a456-426614174000",
                "client_id": "abc12345-6789-0def-1234-56789abcdef0",
                "site_id": "def12345-6789-0def-1234-56789abcdef0",
                "network_name": "Main LAN",
                "network_type": "lan",
                "cidr": "192.168.1.0/24",
                "gateway_ip": "192.168.1.1",
                "vlan_id": null,
                "notes": "Primary office network",
                "created_at": "2024-01-15T10:30:00Z",
                "updated_at": "2024-01-15T10:30:00Z"
            }
        ]
    }
    ```
    """
    try:
        networks, total = network_service.get_networks(db, skip, limit)

        return {
            "total": total,
            "skip": skip,
            "limit": limit,
            "networks": [NetworkResponse.model_validate(network) for network in networks]
        }

    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to retrieve networks: {str(e)}"
        )


@router.get(
    "/by-site/{site_id}",
    response_model=dict,
    summary="Get networks by site",
    description="Retrieve all networks for a specific site with pagination",
    status_code=status.HTTP_200_OK,
    responses={
        200: {
            "description": "Networks found and returned",
            "content": {
                "application/json": {
                    "example": {
                        "total": 3,
                        "skip": 0,
                        "limit": 100,
                        "networks": [
                            {
                                "id": "123e4567-e89b-12d3-a456-426614174000",
                                "client_id": "abc12345-6789-0def-1234-56789abcdef0",
                                "site_id": "def12345-6789-0def-1234-56789abcdef0",
                                "network_name": "Main LAN",
                                "network_type": "lan",
                                "cidr": "192.168.1.0/24",
                                "gateway_ip": "192.168.1.1",
                                "vlan_id": None,
                                "notes": "Primary office network",
                                "created_at": "2024-01-15T10:30:00Z",
                                "updated_at": "2024-01-15T10:30:00Z"
                            }
                        ]
                    }
                }
            }
        },
        404: {
            "description": "Site not found",
            "content": {
                "application/json": {
                    "example": {"detail": "Site with ID def12345-6789-0def-1234-56789abcdef0 not found"}
                }
            },
        },
    },
)
def get_networks_by_site(
    site_id: UUID,
    skip: int = Query(
        default=0,
        ge=0,
        description="Number of records to skip for pagination"
    ),
    limit: int = Query(
        default=100,
        ge=1,
        le=1000,
        description="Maximum number of records to return (max 1000)"
    ),
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Get all networks for a specific site.

    - **site_id**: UUID of the site
    - **skip**: Number of networks to skip (default: 0)
    - **limit**: Maximum number of networks to return (default: 100, max: 1000)

    Returns a list of networks for the specified site with pagination metadata.

    **Example Request:**
    ```
    GET /api/networks/by-site/def12345-6789-0def-1234-56789abcdef0?skip=0&limit=50
    Authorization: Bearer <token>
    ```
    """
    networks, total = network_service.get_networks_by_site(db, site_id, skip, limit)

    return {
        "total": total,
        "skip": skip,
        "limit": limit,
        "networks": [NetworkResponse.model_validate(network) for network in networks]
    }


@router.get(
    "/{network_id}",
    response_model=NetworkResponse,
    summary="Get network by ID",
    description="Retrieve a single network by its unique identifier",
    status_code=status.HTTP_200_OK,
    responses={
        200: {
            "description": "Network found and returned",
            "model": NetworkResponse,
        },
        404: {
            "description": "Network not found",
            "content": {
                "application/json": {
                    "example": {"detail": "Network with ID 123e4567-e89b-12d3-a456-426614174000 not found"}
                }
            },
        },
    },
)
def get_network(
    network_id: UUID,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Get a specific network by ID.

    - **network_id**: UUID of the network to retrieve

    Returns the complete network details.

    **Example Request:**
    ```
    GET /api/networks/123e4567-e89b-12d3-a456-426614174000
    Authorization: Bearer <token>
    ```

    **Example Response:**
    ```json
    {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "client_id": "abc12345-6789-0def-1234-56789abcdef0",
        "site_id": "def12345-6789-0def-1234-56789abcdef0",
        "network_name": "Main LAN",
        "network_type": "lan",
        "cidr": "192.168.1.0/24",
        "gateway_ip": "192.168.1.1",
        "vlan_id": null,
        "notes": "Primary office network",
        "created_at": "2024-01-15T10:30:00Z",
        "updated_at": "2024-01-15T10:30:00Z"
    }
    ```
    """
    network = network_service.get_network_by_id(db, network_id)
    return NetworkResponse.model_validate(network)


@router.post(
    "",
    response_model=NetworkResponse,
    summary="Create new network",
    description="Create a new network with the provided details",
    status_code=status.HTTP_201_CREATED,
    responses={
        201: {
            "description": "Network created successfully",
            "model": NetworkResponse,
        },
        404: {
            "description": "Site not found",
            "content": {
                "application/json": {
                    "example": {"detail": "Site with ID def12345-6789-0def-1234-56789abcdef0 not found"}
                }
            },
        },
        422: {
            "description": "Validation error",
            "content": {
                "application/json": {
                    "example": {
                        "detail": [
                            {
                                "loc": ["body", "network_name"],
                                "msg": "field required",
                                "type": "value_error.missing"
                            }
                        ]
                    }
                }
            },
        },
    },
)
def create_network(
    network_data: NetworkCreate,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Create a new network.

    Requires a valid JWT token with appropriate permissions.
    The site_id must reference an existing site if provided.

    **Example Request:**
    ```json
    POST /api/networks
    Authorization: Bearer <token>
    Content-Type: application/json

    {
        "client_id": "abc12345-6789-0def-1234-56789abcdef0",
        "site_id": "def12345-6789-0def-1234-56789abcdef0",
        "network_name": "Main LAN",
        "network_type": "lan",
        "cidr": "192.168.1.0/24",
        "gateway_ip": "192.168.1.1",
        "vlan_id": null,
        "notes": "Primary office network"
    }
    ```

    **Example Response:**
    ```json
    {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "client_id": "abc12345-6789-0def-1234-56789abcdef0",
        "site_id": "def12345-6789-0def-1234-56789abcdef0",
        "network_name": "Main LAN",
        "network_type": "lan",
        "cidr": "192.168.1.0/24",
        "gateway_ip": "192.168.1.1",
        "vlan_id": null,
        "notes": "Primary office network",
        "created_at": "2024-01-15T10:30:00Z",
        "updated_at": "2024-01-15T10:30:00Z"
    }
    ```
    """
    network = network_service.create_network(db, network_data)
    return NetworkResponse.model_validate(network)


@router.put(
    "/{network_id}",
    response_model=NetworkResponse,
    summary="Update network",
    description="Update an existing network's details",
    status_code=status.HTTP_200_OK,
    responses={
        200: {
            "description": "Network updated successfully",
            "model": NetworkResponse,
        },
        404: {
            "description": "Network or site not found",
            "content": {
                "application/json": {
                    "example": {"detail": "Network with ID 123e4567-e89b-12d3-a456-426614174000 not found"}
                }
            },
        },
    },
)
def update_network(
    network_id: UUID,
    network_data: NetworkUpdate,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Update an existing network.

    - **network_id**: UUID of the network to update

    Only provided fields will be updated. All fields are optional.
    If updating site_id, the new site must exist.

    **Example Request:**
    ```json
    PUT /api/networks/123e4567-e89b-12d3-a456-426614174000
    Authorization: Bearer <token>
    Content-Type: application/json

    {
        "gateway_ip": "192.168.1.254",
        "notes": "Gateway IP updated for redundancy"
    }
    ```

    **Example Response:**
    ```json
    {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "client_id": "abc12345-6789-0def-1234-56789abcdef0",
        "site_id": "def12345-6789-0def-1234-56789abcdef0",
        "network_name": "Main LAN",
        "network_type": "lan",
        "cidr": "192.168.1.0/24",
        "gateway_ip": "192.168.1.254",
        "vlan_id": null,
        "notes": "Gateway IP updated for redundancy",
        "created_at": "2024-01-15T10:30:00Z",
        "updated_at": "2024-01-15T14:20:00Z"
    }
    ```
    """
    network = network_service.update_network(db, network_id, network_data)
    return NetworkResponse.model_validate(network)


@router.delete(
    "/{network_id}",
    response_model=dict,
    summary="Delete network",
    description="Delete a network by its ID",
    status_code=status.HTTP_200_OK,
    responses={
        200: {
            "description": "Network deleted successfully",
            "content": {
                "application/json": {
                    "example": {
                        "message": "Network deleted successfully",
                        "network_id": "123e4567-e89b-12d3-a456-426614174000"
                    }
                }
            },
        },
        404: {
            "description": "Network not found",
            "content": {
                "application/json": {
                    "example": {"detail": "Network with ID 123e4567-e89b-12d3-a456-426614174000 not found"}
                }
            },
        },
    },
)
def delete_network(
    network_id: UUID,
    db: Session = Depends(get_db),
    current_user: dict = Depends(get_current_user),
):
    """
    Delete a network.

    - **network_id**: UUID of the network to delete

    This is a permanent operation and cannot be undone.

    **Example Request:**
    ```
    DELETE /api/networks/123e4567-e89b-12d3-a456-426614174000
    Authorization: Bearer <token>
    ```

    **Example Response:**
    ```json
    {
        "message": "Network deleted successfully",
        "network_id": "123e4567-e89b-12d3-a456-426614174000"
    }
    ```
    """
    return network_service.delete_network(db, network_id)
