#!/usr/bin/env python3
"""radical-orbit-makeflow — one-shot prep + makeflow.

Convenience wrapper around ``radical-orbit-makeflow-prep`` and the
``makeflow`` binary.  Preprocesses the input in a temporary directory,
then invokes ``makeflow`` with any passthrough flags.

Usage:
    radical-orbit-makeflow INPUT.makeflow [-- makeflow-args...]
    radical-orbit-makeflow --default-endpoint=e --default-pool=p INPUT.makeflow

Examples:
    radical-orbit-makeflow workflow.makeflow
    radical-orbit-makeflow workflow.makeflow -- -T local -j 4
"""

from __future__ import annotations

import argparse
import os
import shutil
import subprocess
import sys
import tempfile

from pathlib import Path


def _split_argv(argv: list[str]) -> tuple[list[str], list[str]]:
    '''Split at the first ``--`` separator.  Passthrough args default
    to empty if no ``--`` is given.
    '''
    try:
        sep = argv.index('--')
    except ValueError:
        return argv[1:], []
    return argv[1:sep], argv[sep + 1:]


def main(argv: list[str] | None = None) -> int:
    if argv is None:
        argv = sys.argv

    prep_args, makeflow_args = _split_argv(argv)

    ap = argparse.ArgumentParser(
        prog='radical-orbit-makeflow',
        description='Preprocess and run a .makeflow via the task dispatcher.')
    ap.add_argument('input', type=Path,
                    help='input .makeflow file')
    ap.add_argument('--default-endpoint',     dest='default_endpoint')
    ap.add_argument('--default-pool',     dest='default_pool')
    ap.add_argument('--default-priority', dest='default_priority',
                    type=int, default=0)
    ap.add_argument('--keep-prepped', action='store_true',
                    help='keep the preprocessed .makeflow (default: delete)')
    args = ap.parse_args(prep_args)

    if not args.input.is_file():
        print(f'radical-orbit-makeflow: input not found: {args.input}',
              file=sys.stderr)
        return 2

    makeflow_bin = shutil.which('makeflow')
    if makeflow_bin is None:
        print('radical-orbit-makeflow: makeflow binary not found in PATH',
              file=sys.stderr)
        return 2

    with tempfile.TemporaryDirectory(prefix='radical-orbit-makeflow-') as td:
        prepped = Path(td) / (args.input.name + '.prepped')

        prep_cmd = [_find_prep(), str(args.input), '-o', str(prepped)]
        if args.default_endpoint:
            prep_cmd += ['--default-endpoint', args.default_endpoint]
        if args.default_pool:
            prep_cmd += ['--default-pool', args.default_pool]
        if args.default_priority:
            prep_cmd += ['--default-priority', str(args.default_priority)]

        rc = subprocess.call(prep_cmd)
        if rc != 0:
            return rc

        if args.keep_prepped:
            keep = args.input.with_suffix(args.input.suffix + '.prepped')
            shutil.copy2(prepped, keep)
            print(f'kept prepped file at {keep}', file=sys.stderr)

        # Hand off to makeflow.  Our prepped file may live in a
        # temp dir; set cwd to the user's working dir so relative
        # inputs/outputs resolve where the user expects.
        return subprocess.call(
            [makeflow_bin, str(prepped)] + makeflow_args,
            cwd=os.getcwd())


def _find_prep() -> str:
    '''Locate ``radical-orbit-makeflow-prep``.

    Normally it lives next to us on ``PATH`` after install.  Fall back
    to the adjacent file for in-tree invocations.
    '''
    found = shutil.which('radical-orbit-makeflow-prep')
    if found:
        return found
    candidate = Path(__file__).resolve().with_name(
        'radical-orbit-makeflow-prep')
    if candidate.is_file():
        return str(candidate)
    raise FileNotFoundError(
        'radical-orbit-makeflow-prep not found; install the package or '
        'ensure it is on PATH')


if __name__ == '__main__':
    sys.exit(main())
