import logging
from typing import List, Set

from defence360agent.subsys.panels.cpanel import cPanel as Base
from defence360agent.subsys.panels.cpanel.panel import (
    WWWACT_CONF,
)
from defence360agent.utils.kwconfig import KWConfig
from im360.subsys import webshield
from im360.subsys.panels.base import PanelInterface
from im360.utils import (
    change_system_password,
    generate_strong_password,
    is_apache2nginx_enabled,
)
from im360.subsys.panels.coraza_modsecurity import CorazaModSecurity
from im360.subsys.panels.cpanel.mod_security import cPanelModSecurity
from .pure_ftp import cPanelPureFTPConfig
from .remoteip import RemoteIP

logger = logging.getLogger(__name__)

CPANEL_CONFIG = "/var/cpanel/cpanel.config"


class cPanelConfig(KWConfig):
    SEARCH_PATTERN = r"^\s*{}\s*=\s*(.*?)\s*$"
    WRITE_PATTERN = "{}={}"
    DEFAULT_FILENAME = CPANEL_CONFIG


class cPanelBase:
    pure_ftp_conf_cls = cPanelPureFTPConfig

    async def _get_all_admin_emails(self) -> List[str]:
        emails = []  # type: List[str]
        with open(WWWACT_CONF) as f:
            contact_line = next(
                (
                    line
                    for line in f
                    if line.strip().startswith("CONTACTEMAIL")
                ),
                None,
            )
        if contact_line is not None:
            contacts = contact_line.strip().split()
            if len(contacts) > 1:
                return [
                    email.strip() for email in contacts[1].split(",") if email
                ]
        return emails

    def http_ports(self) -> Set[int]:
        return {2082, 2095, 2086}  # cPanel  # cPpanel Webmail  # WHM

    def https_ports(self) -> Set[int]:
        return {
            2083,  # cPanel SSL
            2096,  # cPpanel Webmail SSL
            2087,  # WHM SSL
        }

    def remoteip_supported(self) -> bool:
        return True

    def get_SMTP_conflict_status(self) -> bool:
        """
        Return True if SMTP restriction feature is enabled
        """
        return cPanelConfig("smtpmailgidonly").get() == "1"

    def get_webshield_protected_ports(self):
        return {
            port: webshield.port_redirect_map()[port] for port in (2082, 2083)
        }

    @staticmethod
    def force_reset_user_password(username, password=None):
        change_system_password(
            username, generate_strong_password() if not password else password
        )


class cPanelCoraza(
    Base, cPanelBase, PanelInterface, CorazaModSecurity, RemoteIP
):
    pass


class cPanel(Base, cPanelBase, PanelInterface, cPanelModSecurity, RemoteIP):
    def __new__(cls, force_cpanel=False, force_coraza=False, *args, **kwargs):
        if force_cpanel:
            return super().__new__(cls)

        if force_coraza:
            return cPanelCoraza()

        apache2nginx_status = is_apache2nginx_enabled()

        if apache2nginx_status:
            return cPanelCoraza()
        else:
            return super().__new__(cls)
