from __future__ import annotations

import argparse
import os
from collections.abc import Sequence

from devenv import bootstrap
from devenv import doctor
from devenv import fetch
from devenv import pin_gha
from devenv import sync
from devenv.constants import home
from devenv.constants import user
from devenv.constants import version
from devenv.lib.config import read_config
from devenv.lib.context import Context
from devenv.lib.fs import gitroot
from devenv.lib.modules import DevModuleInfo
from devenv.lib.modules import ExitCode
from devenv.lib.repository import Repository


def devenv(argv: Sequence[str], config_path: str) -> ExitCode:
    # determine current repo, if applicable
    fake_reporoot = os.getenv("CI_DEVENV_INTEGRATION_FAKE_REPOROOT")
    if fake_reporoot:
        current_root = fake_reporoot
    else:
        try:
            current_root = gitroot()
        except RuntimeError:
            current_root = None

    # This may or may not exist
    config = read_config(config_path)

    # Guessing temporary code root
    code_root = config.get("devenv", "coderoot", fallback=None) or (
        os.path.abspath(f"{current_root}/..")
        if current_root
        else os.path.expanduser("~/code")
    )

    modinfo_list: Sequence[DevModuleInfo] = [
        module.module_info
        for module in [bootstrap, fetch, doctor, pin_gha, sync]
        if hasattr(module, "module_info")
    ]

    # TODO: Search for modules in work repo

    parser = argparse.ArgumentParser()
    parser.add_argument("--version", action="version", version=version)
    subparser = parser.add_subparsers(
        title=argparse.SUPPRESS,
        metavar="command",
        dest="command",
        required=True,
    )

    for info in modinfo_list:
        # Argparse stuff
        subparser.add_parser(info.command, help=info.help)

    if len(argv) == 1:
        parser.print_help()
        return 0

    args, remainder = parser.parse_known_args(argv[1:])

    # context for subcommands
    context: Context = {
        "config_path": config_path,
        "code_root": code_root,
        "repo": Repository(current_root) if current_root else None,
    }

    command_actions = {info.command: info.action for info in modinfo_list}
    action = command_actions.get(args.command)
    assert action is not None
    return action(context, remainder)


def main() -> ExitCode:
    if user == "root":
        raise SystemExit("You shouldn't be running devenv as root.")

    import sys
    import sentry_sdk

    sentry_sdk.init(
        # https://sentry.sentry.io/settings/projects/sentry-dev-env/keys/
        dsn="https://9bdb053cb8274ea69231834d1edeec4c@o1.ingest.sentry.io/5723503",
        # enable performance monitoring
        enable_tracing=True,
    )

    return devenv(sys.argv, f"{home}/.config/sentry-devenv/config.ini")


if __name__ == "__main__":
    raise SystemExit(main())
