import importlib.resources
import json

from netbox.settings import django_apps


# region Endpoint Creation

# These functions are used in the migration file to prepare the endpoints
# Because of this we have to use historical models
# see https://docs.djangoproject.com/en/5.1/topics/migrations/#historical-models


def build_endpoints(data, apps: django_apps = None, db_alias: str = "default") -> None:
    apps = apps or django_apps
    IPFabricEndpoint = apps.get_model("ipfabric_netbox", "IPFabricEndpoint")
    for endpoint_data in data:
        IPFabricEndpoint.objects.using(db_alias).create(**endpoint_data)


def get_endpoint_data() -> dict:
    for data_file in importlib.resources.files("ipfabric_netbox.data").iterdir():
        if data_file.name != "endpoint.json":
            continue
        with open(data_file, "rb") as data_file:
            return json.load(data_file)
    raise FileNotFoundError("'endpoint.json' not found in installed package")


# endregion Endpoint Creation

# region Endpoint Updating


class EndpointRecord:
    """Record for endpoint creation/deletion in migrations."""

    def __init__(self, name: str, description: str, endpoint: str):
        self.name = name
        self.description = description
        self.endpoint = endpoint


def do_endpoint_change(
    apps, schema_editor, endpoints: tuple[EndpointRecord, ...], forward: bool = True
):
    """
    Apply endpoint changes, `forward` determines direction.

    Forward: Creates endpoints if they don't exist (idempotent using get_or_create).
    Reverse: Deletes endpoints by endpoint path.

    Args:
        apps: Django apps registry (historical models)
        schema_editor: Database schema editor
        endpoints: Tuple of EndpointRecord objects to process
        forward: True for forward migration (create), False for reverse (delete)
    """
    IPFabricEndpoint = apps.get_model("ipfabric_netbox", "IPFabricEndpoint")
    db_alias = schema_editor.connection.alias

    try:
        for endpoint_record in endpoints:
            if forward:
                # Forward: Create endpoint if it doesn't exist (idempotent)
                IPFabricEndpoint.objects.using(db_alias).get_or_create(
                    endpoint=endpoint_record.endpoint,
                    defaults={
                        "name": endpoint_record.name,
                        "description": endpoint_record.description,
                    },
                )
            else:
                # Reverse: Delete endpoint by endpoint path
                IPFabricEndpoint.objects.using(db_alias).filter(
                    endpoint=endpoint_record.endpoint
                ).delete()

    except Exception as e:
        print(f"Error applying endpoint changes: {e}")


# endregion
