from opn_api.models import AliasType as OPNsenseAliasType
from opn_api.models import FirewallAlias as OPNsenseFirewallAlias
from pyfsense_client.v1.models import AliasType as pfSenseV1AliasType
from pyfsense_client.v1.models import FirewallAlias as pfSenseV1FirewallAlias
from pyfsense_client.v2.models import AliasType as pfSenseV2AliasType
from pyfsense_client.v2.models import FirewallAlias as pfSenseV2FirewallAlias
from pyfsense_client.v2.models import (
    FirewallAliasCreate as pfSenseV2FirewallAliasCreate,
)

from .types import Alias, AliasType


def alias_to_opnsense_firewall_alias(alias: Alias) -> OPNsenseFirewallAlias:
    # Map AliasType to OPNsenseAliasType
    opnsense_alias_type = OPNsenseAliasType(alias.alias_type.value)

    # Ensure content is a list
    content = [alias.content] if isinstance(alias.content, str) else alias.content

    return OPNsenseFirewallAlias(
        name=alias.name,
        type=opnsense_alias_type,
        description=alias.description,
        content=content,
        enabled=True,
        update_freq="",
        counters="",
    )


def opnsense_firewall_alias_to_alias(fw_alias: OPNsenseFirewallAlias) -> Alias:
    # Map OPNsenseAliasType to AliasType
    alias_type = AliasType(fw_alias.type.value)

    return Alias(
        name=fw_alias.name,
        alias_type=alias_type,
        description=fw_alias.description or "",
        content=fw_alias.content,
        detail=[],  # OPNsense does not provide 'detail', so set it to empty list
    )


def alias_to_pfsense_v1_firewall_alias(alias: Alias) -> pfSenseV1FirewallAlias:
    # Map AliasType to pfSenseV1AliasType
    if not isinstance(alias.alias_type, AliasType):
        raise ValueError(f"Invalid alias type: {alias.alias_type}")

    pfsense_alias_type = pfSenseV1AliasType(alias.alias_type.value)

    return pfSenseV1FirewallAlias(
        name=alias.name,
        type=pfsense_alias_type,
        address=alias.content,
        detail=alias.detail,
        descr=alias.description,
    )


def pfsense_firewall_v1_alias_to_alias(fw_alias: pfSenseV1FirewallAlias) -> Alias:
    # Map pfSenseV1AliasType to AliasType
    alias_type = AliasType(fw_alias.type.value)

    # Ensure address and detail are in the correct format
    address = fw_alias.address if isinstance(fw_alias.address, list) else [fw_alias.address]
    detail = fw_alias.detail if isinstance(fw_alias.detail, list) else [fw_alias.detail]

    return Alias(
        name=fw_alias.name,
        alias_type=alias_type,
        description=fw_alias.descr or "",
        content=address,
        detail=detail,
    )


def alias_to_pfsense_v2_firewall_alias(alias: Alias) -> pfSenseV2FirewallAliasCreate:
    """
    Convert a project Alias instance to a pfSense V2 FirewallAliasCreate object.
    Since our project Alias does not have an ID, we use the creation model.
    """
    # Map AliasType to pfSenseV2AliasType
    pfsense_v2_alias_type = pfSenseV2AliasType(alias.alias_type.value)

    return pfSenseV2FirewallAliasCreate(
        name=alias.name,
        type=pfsense_v2_alias_type,
        descr=alias.description,
        address=alias.content,
        detail=alias.detail,
    )


def pfsense_firewall_v2_alias_to_alias(fw_alias: pfSenseV2FirewallAlias) -> Alias:
    """
    Convert a pfSense V2 FirewallAlias (read model) to a project Alias instance.
    """
    # Map pfSenseV2AliasType to AliasType
    alias_type = AliasType(fw_alias.type.value)

    return Alias(
        name=fw_alias.name,
        alias_type=alias_type,
        description=fw_alias.descr or "",
        content=fw_alias.address,
        detail=fw_alias.detail,
    )
