import os
import sys

from mixersystem import __version__
from mixersystem.data.repository import parse_args, run_cli
from mixersystem.sync import sync
from mixersystem.push import push
from mixersystem.workflows.work.create_work import run as run_create_work
from mixersystem.workflows.plan.create_plan import run as run_create_plan
from mixersystem.workflows.task.create_task import run as run_create_task
from mixersystem.workflows.update.create_update import run as run_create_update
from mixersystem.workflows.upgrade.create_upgrade import run as run_create_upgrade
from mixersystem.workflows.report.create_report import run as run_create_report
from mixersystem.workflows.shared.create_questions import run as run_create_questions
from mixersystem.workflows.shared.create_answer import run as run_create_answer
from mixersystem.workflows.shared.create_context import run as run_create_context

_WORKFLOWS = {
    "task": run_create_task,
    "plan": run_create_plan,
    "work": run_create_work,
    "update": run_create_update,
    "upgrade": run_create_upgrade,
    "report": run_create_report,
    "questions": run_create_questions,
    "answer": run_create_answer,
    "context": run_create_context,
}


def _print_usage() -> None:
    print(
        "Usage:\n"
        "  python3 -m mixersystem --help\n"
        "  python3 -m mixersystem --version\n"
        "  python3 -m mixersystem init [--project_root=<path>]\n"
        "  python3 -m mixersystem sync [--project_root=<path>]\n"
        "  python3 -m mixersystem push [--project_root=<path>]\n"
        "  python3 -m mixersystem run <workflow> --session_folder=<path> [--key=value...]\n"
        "  python3 -m mixersystem <workflow> --session_folder=<path> [--key=value...]\n"
        "  Workflows: task, plan, work, update, upgrade, report, questions, answer\n"
        "  Questions/answer workflows require --stage=<stage> (e.g. --stage=plan)\n"
        "  python3 -m mixersystem studio [--host=127.0.0.1] [--port=8420] [--project_root=<path>]\n"
        "\n"
        "Compatibility aliases:\n"
        "  python3 -m mixersystem create-task --session_folder=<path> [--key=value...]\n"
        "  python3 -m mixersystem create-plan --session_folder=<path> [--key=value...]\n"
        "  python3 -m mixersystem create-work --session_folder=<path> [--key=value...]\n"
        "  python3 -m mixersystem create-update --session_folder=<path> [--key=value...]\n"
        "  python3 -m mixersystem create-upgrade --session_folder=<path> [--key=value...]\n"
        "  python3 -m mixersystem create-report --session_folder=<path> [--key=value...]\n"
    )


def _run_workflow(run_fn, args: list[str]) -> int:
    original_argv = sys.argv
    try:
        sys.argv = [original_argv[0], *args]
        run_cli(run_fn)
    finally:
        sys.argv = original_argv
    return 0


def _parse_root_only_args(args: list[str], command_name: str) -> tuple[str | None, int]:
    parsed = parse_args(args)
    project_root = parsed.pop("project_root", None)
    if parsed:
        unknown = ", ".join(sorted(parsed.keys()))
        print(f"Unsupported {command_name} arguments: {unknown}")
        return None, 1
    return project_root, 0


def _run_sync(args: list[str]) -> int:
    project_root, err = _parse_root_only_args(args, "sync")
    if err:
        return err
    sync(project_root=project_root)
    return 0


def _run_push(args: list[str]) -> int:
    project_root, err = _parse_root_only_args(args, "push")
    if err:
        return err
    return push(project_root=project_root)


def _run_init(args: list[str]) -> int:
    project_root, err = _parse_root_only_args(args, "init")
    if err:
        return err
    sync(project_root=project_root)
    target = project_root or "."
    print(f"Initialized MixerSystem runtime in {target}")
    return 0


def _run_studio(args: list[str]) -> int:
    parsed = parse_args(args)
    host = parsed.pop("host", "127.0.0.1")
    port = int(parsed.pop("port", 8420))
    project_root = parsed.pop("project_root", None)
    if parsed:
        unknown = ", ".join(sorted(parsed.keys()))
        print(f"Unsupported studio arguments: {unknown}")
        return 1

    try:
        import uvicorn
        from mixersystem.studio import create_app
        from mixersystem.studio.config import StudioConfig
    except ImportError:
        print(
            "Studio requires extra dependencies.\n"
            "Install with: pip install mixer-system[studio]"
        )
        return 1

    from pathlib import Path
    import signal, subprocess
    # Kill any existing process on this port so restarts just work
    try:
        result = subprocess.run(
            ["lsof", "-ti", f":{port}"],
            capture_output=True, text=True, timeout=5,
        )
        for pid in result.stdout.strip().splitlines():
            if pid.strip().isdigit():
                os.kill(int(pid.strip()), signal.SIGTERM)
        if result.stdout.strip():
            import time; time.sleep(0.5)
    except Exception:
        pass

    root = Path(project_root).resolve() if project_root else Path.cwd().resolve()

    # Load .env file so secrets like LINEAR_API_KEY are available
    env_file = root / ".env"
    if env_file.is_file():
        for line in env_file.read_text().splitlines():
            line = line.strip()
            if not line or line.startswith("#") or "=" not in line:
                continue
            key, _, value = line.partition("=")
            key = key.strip()
            value = value.strip().strip("'\"")
            if key and key not in os.environ:
                os.environ[key] = value

    config = StudioConfig(host=host, port=port, project_root=root)
    app = create_app(config)

    url = f"http://{host}:{port}"
    print(f"Mixer Studio → {url}")

    import webbrowser, threading
    threading.Timer(0.8, lambda: webbrowser.open(url)).start()

    uvicorn.run(app, host=host, port=port, log_level="warning")
    return 0


def _run_named_workflow(workflow_name: str, args: list[str]) -> int:
    run_fn = _WORKFLOWS.get(workflow_name)
    if not run_fn:
        allowed = ", ".join(sorted(_WORKFLOWS.keys()))
        print(f"Unknown workflow: {workflow_name}. Supported workflows: {allowed}")
        return 1
    return _run_workflow(run_fn, args)


def main(argv: list[str] | None = None) -> int:
    args = list(sys.argv[1:] if argv is None else argv)
    if not args or args[0] in {"-h", "--help"}:
        _print_usage()
        return 0

    command = args[0]
    command_args = args[1:]

    if command in {"-V", "--version", "version"}:
        print(__version__)
        return 0

    if command == "init":
        return _run_init(command_args)
    if command == "sync":
        return _run_sync(command_args)
    if command == "push":
        return _run_push(command_args)
    if command == "studio":
        return _run_studio(command_args)

    if command == "run":
        if not command_args:
            print("Usage: python3 -m mixersystem run <task|plan|work|update|upgrade|report> --session_folder=<path> [--key=value...]")
            return 1
        workflow_name = command_args[0]
        workflow_args = command_args[1:]
        return _run_named_workflow(workflow_name, workflow_args)

    if command == "create-task":
        return _run_named_workflow("task", command_args)
    if command == "create-plan":
        return _run_named_workflow("plan", command_args)
    if command == "create-work":
        return _run_named_workflow("work", command_args)
    if command == "create-update":
        return _run_named_workflow("update", command_args)
    if command == "create-upgrade":
        return _run_named_workflow("upgrade", command_args)
    if command == "create-report":
        return _run_named_workflow("report", command_args)

    if command in _WORKFLOWS:
        return _run_named_workflow(command, command_args)

    print(f"Unknown command: {command}")
    _print_usage()
    return 1


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