import re
import sys
from datetime import datetime
from importlib import metadata
from os import environ

import httpx
from packaging import version

from ..api import configure_client
from ..exceptions import SatoriRequestError
from ..utils import load_config
from .commands.config import ConfigCommand
from .commands.playbooks import PlaybooksCommand
from .commands.root import RootCommand
from .commands.shards import ShardsCommand
from .utils import configure_console_width, console, error_console, log, logging

VERSION = metadata.version("satori-ci")


def check_for_update():
    """Verify the current version and the latest version"""

    try:
        response = httpx.get("https://pypi.org/pypi/satori-ci/json")
        response.raise_for_status()
    except Exception:
        log.warning("Unable to get latest version.")
        return

    latest = response.json()["info"]["version"]

    if version.parse(latest) > version.parse(VERSION):
        log.warning("Newer version available v%s, update with: satori update", latest)


def main():
    timestamp = (datetime.now()).strftime("%Y-%m-%d %H:%M:%S")
    error_console.print(
        f"[dim]Satori CI {VERSION} - Automated Testing - Started on [b bright_magenta]{timestamp}"
    )
    root = RootCommand()
    args = root.parse_args()

    # Set debug/verbose mode
    if args["debug"]:
        log.setLevel(logging.DEBUG)
    elif args["verbose"]:
        log.setLevel(logging.WARNING)

    if environ.get("SATORI_CLI_NO_UPDATE_CHECK") != "1":
        check_for_update()

    if len(sys.argv) > 1 and sys.argv[1] == "update":
        try:
            exit_code = root.run(args)
            sys.exit(exit_code)
        except Exception as e:
            error_console.print(f"Error during update: {e}")
            sys.exit(1)

    try:
        full_config = load_config(args.get("config"))
        config = full_config.get(args["profile"])

        # Configure console width if specified in profile config
        if config and "width" in config:
            configure_console_width(config["width"])
    except Exception as e:
        if not isinstance(args["func"], ConfigCommand) and not isinstance(
            args["func"], ShardsCommand
        ):
            error_console.print(
                f"[error]ERROR:[/] Your .satori_credentials.yml file is corrupted or not found."
            )
            sys.exit(1)
        else:
            config = None

    if config:
        try:
            # Filter out width before passing to configure_client
            client_config = {k: v for k, v in config.items() if k != "width"}
            configure_client(**client_config)
        except Exception as e:
            error_console.print(
                f"[error]ERROR:[/] Cannot find your profile in your .satori_credentials.yml file. Is it corrupted?"
            )
            sys.exit(1)
    elif (
        not isinstance(args["func"], ConfigCommand)
        and not (
            # allow playbooks --public
            args["public"] and isinstance(args["func"], PlaybooksCommand)
        )
        and not isinstance(args["func"], ShardsCommand)
    ):
        # Allow config cmd only if profile not found
        error_console.print(f"[error]ERROR:[/] Profile {args['profile']} not found.")

        if config := load_config(args.get("config")):
            error_console.print("These are the profiles available:")

            for key in config:
                error_console.print(key)
        else:
            error_console.print(
                "\nGet your token at https://satori.ci/user-settings and configure it with:\n[b]satori config token TOKEN[/b]"
            )
        sys.exit(1)

    if config:
        config["team"] = args["team"]
        try:
            # Filter out width before passing to configure_client
            client_config = {k: v for k, v in config.items() if k != "width"}
            configure_client(**client_config)
        except Exception as e:
            error_console.print(
                f"[error]ERROR:[/] Cannot find your profile in your .satori_credentials.yml file. Is it corrupted?"
            )
            sys.exit(1)

    try:
        exit_code = root.run(args)
        export = args["export"]
        if export:
            if export == "html":
                content = console.export_html()
            elif export == "svg":
                content = console.export_svg(title="satori-cli")
                # remove non xml utf-8 chars
                regex = (
                    r"[^\x09\x0A\x0D\x20-\xFF\x85\xA0-\uD7FF\uE000-\uFDCF\uFDE0-\uFFFD]"
                )
                content = re.sub(regex, "", content, flags=re.MULTILINE)
            else:
                content = console.export_text()
            with open(f"output.{export}", "w") as f:
                f.write(content)
        sys.exit(exit_code)
    except SatoriRequestError as e:
        error_console.print(f"ERROR: {e}")
        error_console.print(f"Status code: {e.status_code}")
        sys.exit(1)
    except Exception as e:
        if args["debug"]:
            log.exception(e)
        else:
            error_console.print(e)
        sys.exit(1)
