"""
Configuration router for GeViSoft configuration management
Streamlined for external app integration
"""
from fastapi import APIRouter, Depends, status, HTTPException
from fastapi.responses import JSONResponse
import structlog

from schemas.action_mapping_config import (
    ActionMappingResponse,
    ActionMappingListResponse,
    ActionMappingCreate,
    ActionMappingUpdate,
    ActionMappingOperationResponse
)
from services.configuration_service import ConfigurationService
from middleware.auth_middleware import require_administrator, require_viewer
from models.user import User

logger = structlog.get_logger()

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


# ============ CONFIGURATION TREE NAVIGATION ============

@router.get(
    "",
    status_code=status.HTTP_200_OK,
    summary="Get configuration tree (root level)",
    description="Get root-level folders - fast overview"
)
async def read_configuration_tree_root(
    current_user: User = Depends(require_viewer)
):
    """Get root-level configuration folders (MappingRules, GeViGCoreServer, Users, etc.)"""
    service = ConfigurationService()

    try:
        result = await service.read_configuration_as_tree(max_depth=1)
        return JSONResponse(content=result, status_code=status.HTTP_200_OK)
    except Exception as e:
        logger.error("read_configuration_tree_root_error", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to read configuration tree: {str(e)}"
        )


@router.get(
    "/path",
    status_code=status.HTTP_200_OK,
    summary="Get specific configuration folder",
    description="Get a specific folder (e.g., MappingRules, Users)"
)
async def read_configuration_path(
    path: str,
    current_user: User = Depends(require_viewer)
):
    """
    Get specific configuration folder

    Examples:
    - ?path=MappingRules - Get all action mappings
    - ?path=GeViGCoreServer - Get all G-core servers
    - ?path=Users - Get all users
    """
    service = ConfigurationService()

    try:
        result = await service.read_configuration_path(path)
        return JSONResponse(content=result, status_code=status.HTTP_200_OK)
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    except Exception as e:
        logger.error("read_configuration_path_error", path=path, error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to read configuration path: {str(e)}"
        )


# ============ ACTION MAPPINGS CRUD ============

@router.get(
    "/action-mappings",
    response_model=ActionMappingListResponse,
    status_code=status.HTTP_200_OK,
    summary="List all action mappings",
    description="Get all action mappings with input/output actions"
)
async def list_action_mappings(
    current_user: User = Depends(require_viewer)
):
    """List all action mappings"""
    service = ConfigurationService()

    try:
        result = await service.read_action_mappings()

        if not result["success"]:
            raise ValueError(result.get("error_message", "Failed to read mappings"))

        # Transform mappings to match schema
        transformed_mappings = []
        mappings_with_parameters = 0

        for idx, mapping in enumerate(result["mappings"], start=1):
            # Count mappings with parameters
            has_params = any(
                action.get("parameters") and len(action["parameters"]) > 0
                for action in mapping.get("output_actions", [])
            )
            if has_params:
                mappings_with_parameters += 1

            # Transform mapping to match ActionMappingResponse schema
            transformed_mappings.append({
                "id": idx,
                "offset": mapping.get("start_offset", 0),
                "name": mapping.get("name"),
                "input_actions": mapping.get("input_actions", []),
                "output_actions": mapping.get("output_actions", [])
            })

        return {
            "total_mappings": result["total_count"],
            "mappings_with_parameters": mappings_with_parameters,
            "mappings": transformed_mappings
        }
    except Exception as e:
        logger.error("list_action_mappings_error", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to list action mappings: {str(e)}"
        )


@router.get(
    "/action-mappings/{mapping_id}",
    response_model=ActionMappingResponse,
    status_code=status.HTTP_200_OK,
    summary="Get single action mapping",
    description="Get details of a specific action mapping by ID"
)
async def get_action_mapping(
    mapping_id: int,
    current_user: User = Depends(require_viewer)
):
    """Get single action mapping by ID (1-based)"""
    service = ConfigurationService()

    try:
        result = await service.read_action_mappings()

        if not result["success"]:
            raise ValueError(result.get("error_message"))

        mappings = result.get("mappings", [])

        if mapping_id < 1 or mapping_id > len(mappings):
            raise ValueError(f"Mapping ID {mapping_id} not found")

        mapping = mappings[mapping_id - 1]

        return {
            "id": mapping_id,
            "offset": mapping.get("start_offset", 0),
            "name": mapping.get("name"),
            "input_actions": mapping.get("input_actions", []),
            "output_actions": mapping.get("output_actions", [])
        }
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    except Exception as e:
        logger.error("get_action_mapping_error", mapping_id=mapping_id, error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to get action mapping: {str(e)}"
        )


@router.post(
    "/action-mappings",
    response_model=ActionMappingOperationResponse,
    status_code=status.HTTP_201_CREATED,
    summary="Create action mapping",
    description="Create a new action mapping"
)
async def create_action_mapping(
    mapping_data: ActionMappingCreate,
    current_user: User = Depends(require_administrator)
):
    """Create new action mapping"""
    service = ConfigurationService()

    try:
        result = await service.create_action_mapping({
            "name": mapping_data.name,
            "output_actions": [
                {"action": action.action, "parameters": {}}
                for action in mapping_data.output_actions
            ]
        })

        return result
    except Exception as e:
        logger.error("create_action_mapping_error", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to create action mapping: {str(e)}"
        )


@router.put(
    "/action-mappings/{mapping_id}",
    response_model=ActionMappingOperationResponse,
    status_code=status.HTTP_200_OK,
    summary="Update action mapping",
    description="Update an existing action mapping"
)
async def update_action_mapping(
    mapping_id: int,
    mapping_data: ActionMappingUpdate,
    current_user: User = Depends(require_administrator)
):
    """Update existing action mapping"""
    service = ConfigurationService()

    try:
        result = await service.update_action_mapping(mapping_id, {
            "name": mapping_data.name,
            "output_actions": [
                {"action": action.action, "parameters": {}}
                for action in mapping_data.output_actions
            ] if mapping_data.output_actions else None
        })

        return result
    except Exception as e:
        logger.error("update_action_mapping_error", mapping_id=mapping_id, error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to update action mapping: {str(e)}"
        )


@router.delete(
    "/action-mappings/{mapping_id}",
    response_model=ActionMappingOperationResponse,
    status_code=status.HTTP_200_OK,
    summary="Delete action mapping",
    description="Delete an action mapping"
)
async def delete_action_mapping(
    mapping_id: int,
    current_user: User = Depends(require_administrator)
):
    """Delete action mapping"""
    service = ConfigurationService()

    try:
        result = await service.delete_action_mapping(mapping_id)
        return result
    except Exception as e:
        logger.error("delete_action_mapping_error", mapping_id=mapping_id, error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to delete action mapping: {str(e)}"
        )


# ============ SERVER CONFIGURATION (G-CORE & GSC) ============

@router.get(
    "/servers",
    status_code=status.HTTP_200_OK,
    summary="List all servers",
    description="Get all G-core servers from GeViGCoreServer folder"
)
async def list_servers(
    current_user: User = Depends(require_viewer)
):
    """List all G-core servers"""
    service = ConfigurationService()

    try:
        # Get GeViGCoreServer folder
        gcore_folder = await service.read_configuration_path("GeViGCoreServer")

        servers = []
        if gcore_folder.get("type") == "folder" and "children" in gcore_folder:
            for child in gcore_folder["children"]:
                if child.get("type") != "folder":
                    continue

                # Extract server details
                server_id = child.get("name")
                children_dict = {c.get("name"): c for c in child.get("children", [])}

                server = {
                    "id": server_id,
                    "alias": children_dict.get("Alias", {}).get("value", ""),
                    "host": children_dict.get("Host", {}).get("value", ""),
                    "user": children_dict.get("User", {}).get("value", ""),
                    "password": children_dict.get("Password", {}).get("value", ""),
                    "enabled": bool(children_dict.get("Enabled", {}).get("value", 0)),
                    "deactivateEcho": bool(children_dict.get("DeactivateEcho", {}).get("value", 0)),
                    "deactivateLiveCheck": bool(children_dict.get("DeactivateLiveCheck", {}).get("value", 0))
                }
                servers.append(server)

        return {"total_count": len(servers), "servers": servers}
    except Exception as e:
        logger.error("list_servers_error", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to list servers: {str(e)}"
        )


@router.get(
    "/servers/{server_id}",
    status_code=status.HTTP_200_OK,
    summary="Get single server",
    description="Get details of a specific G-core server by ID"
)
async def get_server(
    server_id: str,
    current_user: User = Depends(require_viewer)
):
    """Get single G-core server by ID"""
    service = ConfigurationService()

    try:
        gcore_folder = await service.read_configuration_path("GeViGCoreServer")

        if gcore_folder.get("type") != "folder" or "children" not in gcore_folder:
            raise ValueError("GeViGCoreServer folder not found")

        # Find server with matching ID
        for child in gcore_folder["children"]:
            if child.get("type") == "folder" and child.get("name") == server_id:
                children_dict = {c.get("name"): c for c in child.get("children", [])}

                server = {
                    "id": server_id,
                    "alias": children_dict.get("Alias", {}).get("value", ""),
                    "host": children_dict.get("Host", {}).get("value", ""),
                    "user": children_dict.get("User", {}).get("value", ""),
                    "password": children_dict.get("Password", {}).get("value", ""),
                    "enabled": bool(children_dict.get("Enabled", {}).get("value", 0)),
                    "deactivateEcho": bool(children_dict.get("DeactivateEcho", {}).get("value", 0)),
                    "deactivateLiveCheck": bool(children_dict.get("DeactivateLiveCheck", {}).get("value", 0))
                }
                return server

        raise ValueError(f"Server '{server_id}' not found")
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    except Exception as e:
        logger.error("get_server_error", server_id=server_id, error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to get server: {str(e)}"
        )


@router.post(
    "/servers",
    status_code=status.HTTP_201_CREATED,
    summary="Create server",
    description="Create a new G-core server"
)
async def create_server(
    server_data: dict
    # current_user: User = Depends(require_administrator)  # Temporarily disabled for testing
):
    """
    Create new G-core server

    Request body:
    {
        "id": "server-name",
        "alias": "My Server",
        "host": "192.168.1.100",
        "user": "admin",
        "password": "password",
        "enabled": true,
        "deactivateEcho": false,
        "deactivateLiveCheck": false
    }
    """
    service = ConfigurationService()

    try:
        result = await service.create_server(server_data)
        return result
    except Exception as e:
        logger.error("create_server_error", error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to create server: {str(e)}"
        )


@router.put(
    "/servers/{server_id}",
    status_code=status.HTTP_200_OK,
    summary="Update server",
    description="Update an existing G-core server"
)
async def update_server(
    server_id: str,
    server_data: dict,
    current_user: User = Depends(require_administrator)
):
    """Update existing G-core server"""
    service = ConfigurationService()

    try:
        result = await service.update_server(server_id, server_data)
        return result
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    except Exception as e:
        logger.error("update_server_error", server_id=server_id, error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to update server: {str(e)}"
        )


@router.delete(
    "/servers/{server_id}",
    status_code=status.HTTP_200_OK,
    summary="Delete server",
    description="Delete a G-core server"
)
async def delete_server(
    server_id: str,
    current_user: User = Depends(require_administrator)
):
    """Delete G-core server"""
    service = ConfigurationService()

    try:
        result = await service.delete_server(server_id)
        return result
    except ValueError as e:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
    except Exception as e:
        logger.error("delete_server_error", server_id=server_id, error=str(e))
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Failed to delete server: {str(e)}"
        )
