import urllib.request
from logging import Logger
from typing import override

from pydantic import BaseModel

from test_automation_suite.checks.check import Check
from test_automation_suite.core.context import Context
from test_automation_suite.core.task import Step, StepResult
from test_automation_suite.utility.cmd import run_cmd_t
from test_automation_suite.utility.network import (
    check_internet_connection,
    deactivate_all_connections,
    remove_connection,
)


class WifiCredentials(BaseModel):
    ssid: str
    password: str


class CheckWifi(Check):
    @override
    def steps(self) -> list[Step]:
        return [*super().steps(), self.check_wifi]

    @staticmethod
    def fetch_wifi_credentials(url: str) -> WifiCredentials:
        with urllib.request.urlopen(url) as response:
            data: str = response.read().decode("UTF-8")
        return WifiCredentials.model_validate_json(data)

    def check_wifi(self, context: Context, logger: Logger) -> StepResult:
        try:
            credentials = self.fetch_wifi_credentials(context.config.wifi_credentials_url)
        except Exception as e:
            logger.error("Failed to load wifi credentials: %s", str(e))
            return StepResult(success=False)

        _ = deactivate_all_connections(logger)

        _, error = run_cmd_t("nmcli r wifi on")
        if error:
            logger.error("Failed to turn radio on: %s", error)
            return StepResult(success=False)
        logger.info("parse device name for wifi device")
        device_result, error = run_cmd_t("nmcli -t d | grep ':wifi:'")
        if error:
            logger.error("Failed to find wifi device: %s", error)
            return StepResult(success=False)
        ifacename = device_result.split(":")[0]
        logger.info("ifacename found: %s", ifacename)
        con_name = "wifitest"
        _ = remove_connection(con_name)
        logger.info("create new wifi connection %s", con_name)
        cmd = f"nmcli connection add type wifi ifname '{ifacename}' ssid '{credentials.ssid}' con-name '{con_name}' +802-11-wireless-security.key-mgmt WPA-PSK +802-11-wireless-security.psk '{credentials.password}'"  # noqa: E501
        _, error = run_cmd_t(cmd)
        if error:
            logger.error("Failed to add new wifi connection: %s", error)
            return StepResult(success=False)
        logger.info("connect to new wifi connection")
        _, error = run_cmd_t(f"nmcli -t c up '{con_name}'")
        if error:
            logger.error("Failed to activate wifi connection: %s", error)
            return StepResult(success=False)
        if not check_internet_connection(context.config.network_ping_address):
            logger.error("Internet connection not available")
        return StepResult(success=True)
