#!/usr/bin/python3


from __future__ import annotations

import logging
import re
from typing import Optional

import requests
from packaging.version import InvalidVersion
from packaging.version import parse as parse_version

from slpkg.config import config_load
from slpkg.views.version import Version

logger = logging.getLogger(__name__)

PYPROJECT_URL = "https://gitlab.com/dslackw/slpkg/-/raw/master/pyproject.toml"


def get_installed_version() -> str:
    """Retrieves the locally installed version of the software."""
    return Version().version


def get_repo_latest_version(url: str) -> Optional[str]:  # pylint: disable=[R0911]
    """
    Fetches the latest version from the repository's pyproject file.

    Args:
        url (str): The URL to the pyproject.toml file.

    Returns:
Optional[        str]: The latest version string if found, otherwise None.
    """
    try:
        response = requests.get(url, timeout=10)
        response.raise_for_status()

        version_pattern = re.compile(r'version = "(\d+\.\d+\.\d+)"')

        for line in response.text.splitlines():
            match = version_pattern.search(line)
            if match:
                return match.group(1)

        logger.warning("No version found with the specified prefix.")
        return None

    except requests.exceptions.Timeout:
        logger.error("The request timed out after 10 seconds while trying to reach the URL: %s", url)
        return None
    except requests.exceptions.ConnectionError:
        logger.error("Could not connect to the URL: %s. Check your internet connection or the URL.", url)
        return None
    except requests.exceptions.HTTPError as e:
        status = e.response.status_code if e.response is not None else "N/A"
        reason = e.response.reason if e.response is not None else "N/A"
        logger.error("HTTP error occurred while accessing %s: %s - %s", url, status, reason)
        return None
    except requests.exceptions.RequestException as e:
        logger.error("An unexpected request error occurred while accessing %s: %s", url, e)
        return None


def check_self_update() -> None:
    """
    Checks for a newer version of the software and informs the user.
    """
    green: str = config_load.green
    cyan: str = config_load.cyan
    yellow: str = config_load.yellow
    endc: str = config_load.endc

    installed_version_str = get_installed_version()
    repo_version_str = get_repo_latest_version(PYPROJECT_URL)

    if not repo_version_str:
        logger.info("Could not determine the latest version from the repository. Update check aborted.")
        return

    try:
        parsed_installed = parse_version(installed_version_str)
        parsed_repo = parse_version(repo_version_str)
    except InvalidVersion as e:
        logger.error(
            "Failed to parse versions '%s' or '%s': %s. Please ensure valid version strings.",
            installed_version_str,
            repo_version_str,
            e,
        )
        return

    if parsed_repo > parsed_installed:
        print(
            f"Update available: Version {green}{parsed_repo}{endc} is newer than your current {yellow}{parsed_installed}{endc}."
        )
        print(f"Please visit the install page: '{cyan}https://dslackw.gitlab.io/slpkg/install{endc}'")
    else:
        print(f"Current version ({green}{parsed_installed}{endc}) is up to date. No new updates found.")
