import logging

from pyfsense_client.v1.client import APIResponse, PfSenseV1Client
from pyfsense_client.v1.models import (
    FirewallAlias,
    FirewallAliasCreate,
    FirewallAliasUpdate,
)

from ..type_conversions import (
    alias_to_pfsense_v1_firewall_alias,
    pfsense_firewall_v1_alias_to_alias,
)
from ..types import Alias
from .base import ClientAliasAdapter

logger = logging.getLogger(__name__)


class PFSenseV1AliasAdapter(ClientAliasAdapter):
    """
    Concrete alias adapter for pfSense V1 API. This class knows
    how to talk to a pfSense firewall running the V1 API.
    """

    def __init__(self, client: PfSenseV1Client):
        super().__init__(client)

    def create_alias(self, alias: Alias, apply: bool = True) -> APIResponse:
        firewall_alias = alias_to_pfsense_v1_firewall_alias(alias)
        new_alias = FirewallAliasCreate(**firewall_alias.model_dump())
        new_alias.apply = apply
        response = self.client.create_firewall_alias(new_alias)
        logger.debug(f"pfSense create_alias response: {response}")
        return response

    def update_alias(self, alias: Alias, apply: bool = True) -> APIResponse:
        firewall_alias = alias_to_pfsense_v1_firewall_alias(alias)
        updated_alias = FirewallAliasUpdate(id=alias.name, **firewall_alias.model_dump())
        updated_alias.apply = apply
        response = self.client.update_firewall_alias(updated_alias)
        logger.debug(f"pfSense update_alias response: {response}")
        return response

    def is_alias_in_use(self, alias_name: str) -> bool:
        # Checking alias usage in source or destination of firewall rules
        result = self.client.get_firewall_rules()
        for item in result.data:
            if alias_name in item["source"].values() or alias_name in item["destination"].values():
                return True
        return False

    def delete_alias(self, alias_name: str, apply: bool = True) -> dict | APIResponse:
        # Skip deletion if alias is in use
        if self.is_alias_in_use(alias_name):
            response = {"msg": f"Alias {alias_name} is in use. Skipping deletion."}
            logger.debug(response)
            return response

        response = self.client.delete_firewall_alias(alias_name)
        logger.debug(f"pfSense delete_alias response: {response}")
        return response

    def rename_alias(self, alias: Alias, new_name: str, apply: bool = True) -> APIResponse:
        firewall_alias = alias_to_pfsense_v1_firewall_alias(alias)
        updated_alias = FirewallAliasUpdate(id=alias.name, **firewall_alias.model_dump())
        updated_alias.name = new_name
        updated_alias.apply = apply
        response = self.client.update_firewall_alias(updated_alias)
        logger.debug(f"pfSense rename_alias response: {response}")
        return response

    def get_all_aliases(self) -> list[Alias]:
        aliases = []
        result = self.client.get_firewall_alias()
        for raw_alias in result.data:
            firewall_alias = FirewallAlias(**raw_alias)
            converted_alias = pfsense_firewall_v1_alias_to_alias(firewall_alias)
            aliases.append(converted_alias)
        return aliases

    def apply(self) -> APIResponse:
        """Apply pending firewall changes on pfSense V1."""
        return self.client.apply_firewall_changes()
