"""
Helper functions for validation state mutation during import workflow.

These functions centralize the logic for updating validation dictionaries
when users select roles, clusters, or racks during the device import process.
"""

import logging

logger = logging.getLogger(__name__)


def fetch_model_by_id(model_class, pk):
    """
    Generic helper to fetch a model instance by primary key.

    Args:
        model_class: Django model class (e.g., DeviceRole, Cluster, Rack)
        pk: Primary key value (int, str, or None)

    Returns:
        Model instance if found and valid, None otherwise

    Example:
        >>> from dcim.models import DeviceRole
        >>> role = fetch_model_by_id(DeviceRole, "5")
        >>> role.name
        'Router'
    """
    if pk is None:
        return None

    try:
        return model_class.objects.get(pk=int(pk))
    except (model_class.DoesNotExist, ValueError, TypeError):
        return None


def extract_device_selections(request, device_id):
    """
    Extract cluster, role, and rack selections from request POST/GET data.

    Args:
        request: Django request object
        device_id: LibreNMS device ID

    Returns:
        dict with keys: cluster_id, role_id, rack_id (all may be None)

    Example:
        >>> selections = extract_device_selections(request, 1234)
        >>> selections
        {'cluster_id': None, 'role_id': '5', 'rack_id': '12'}
    """
    # Check both POST and GET data (different views use different methods)
    data_source = request.POST if request.method == "POST" else request.GET

    return {
        "cluster_id": data_source.get(f"cluster_{device_id}"),
        "role_id": data_source.get(f"role_{device_id}"),
        "rack_id": data_source.get(f"rack_{device_id}"),
    }


def apply_role_to_validation(validation: dict, role, is_vm: bool = False) -> None:
    """
    Update validation state after device/VM role selection.

    Args:
        validation: Validation dict from validate_device_for_import()
        role: DeviceRole instance selected by user
        is_vm: True if importing as VM, False for device

    Modifies validation dict in-place:
        - Sets device_role["found"] = True
        - Sets device_role["role"] = role
        - Removes "role" related issues
        - Recalculates can_import and is_ready flags
    """
    validation["device_role"]["found"] = True
    validation["device_role"]["role"] = role
    remove_validation_issue(validation, "role")
    recalculate_validation_status(validation, is_vm)


def apply_cluster_to_validation(validation: dict, cluster) -> None:
    """
    Update validation state after cluster selection (VM import only).

    Args:
        validation: Validation dict from validate_device_for_import()
        cluster: Cluster instance selected by user

    Modifies validation dict in-place:
        - Sets cluster["found"] = True
        - Sets cluster["cluster"] = cluster
        - Removes "cluster" related issues
        - Recalculates can_import and is_ready flags (as VM)
    """
    validation["cluster"]["found"] = True
    validation["cluster"]["cluster"] = cluster
    remove_validation_issue(validation, "cluster")
    recalculate_validation_status(validation, is_vm=True)


def apply_rack_to_validation(validation: dict, rack) -> None:
    """
    Update validation state after rack selection (device import only).

    Args:
        validation: Validation dict from validate_device_for_import()
        rack: Rack instance selected by user

    Modifies validation dict in-place:
        - Sets rack["found"] = True
        - Sets rack["rack"] = rack

    Note: Rack is optional, so this doesn't affect can_import/is_ready.
    """
    validation.setdefault("rack", {})
    validation["rack"]["found"] = True
    validation["rack"]["rack"] = rack


def remove_validation_issue(validation: dict, keyword: str) -> None:
    """
    Remove validation issues containing the specified keyword.

    Args:
        validation: Validation dict
        keyword: Keyword to search for in issue messages (case-insensitive)

    Example:
        >>> remove_validation_issue(validation, "role")
        # Removes "Device role must be manually selected before import"
    """
    validation["issues"] = [issue for issue in validation["issues"] if keyword.lower() not in issue.lower()]


def recalculate_validation_status(validation: dict, is_vm: bool = False) -> None:
    """
    Recalculate can_import and is_ready flags based on current validation state.

    Args:
        validation: Validation dict
        is_vm: True if importing as VM, False for device

    Updates:
        - can_import: True if no blocking issues remain
        - is_ready: True if can_import AND all required fields are found

    Required fields for devices:
        - site, device_type, device_role

    Required fields for VMs:
        - cluster
    """
    validation["can_import"] = len(validation["issues"]) == 0

    if is_vm:
        validation["is_ready"] = validation["can_import"] and validation["cluster"]["found"]
    else:
        validation["is_ready"] = (
            validation["can_import"]
            and validation["site"]["found"]
            and validation["device_type"]["found"]
            and validation["device_role"]["found"]
        )
