#!/usr/bin/env bash
set -euo pipefail

usage() {
  cat <<'EOF'
Usage:
  migrate-legacy-conf.sh --in <windows-legacy-agent.conf> --out <cloud.conf> [options]

Options:
  --in <path>              Input legacy config file (Windows style).
  --out <path>             Output cloud profile file.
  --lc0-bin <path>         lc0 executable path. Default: /usr/local/bin/lc0
  --stockfish-bin <path>   Stockfish executable path. Default: /usr/local/bin/stockfish
  --engine-root <path>     Root for unknown engines. Default: /data/engines
  --weights <path>         Default lc0 weights path. Default: /data/weights.pb
  --lc0-backend <value>    Default lc0 backend. Default: cuda-fp16
  --help                   Show this help.

Notes:
  - Comment/blank lines are preserved.
  - lc0 args are normalized to Linux/cloud defaults.
  - stockfish entries strip lc0-only flags like --backend/--weights.
EOF
}

INPUT=""
OUTPUT=""
LC0_BIN="/usr/local/bin/lc0"
SF_BIN="/usr/local/bin/stockfish"
ENGINE_ROOT="/data/engines"
WEIGHTS_PATH="/data/weights.pb"
LC0_BACKEND="cuda-fp16"

while [[ $# -gt 0 ]]; do
  case "$1" in
    --in)
      INPUT="${2:-}"
      shift 2
      ;;
    --out)
      OUTPUT="${2:-}"
      shift 2
      ;;
    --lc0-bin)
      LC0_BIN="${2:-}"
      shift 2
      ;;
    --stockfish-bin)
      SF_BIN="${2:-}"
      shift 2
      ;;
    --engine-root)
      ENGINE_ROOT="${2:-}"
      shift 2
      ;;
    --weights)
      WEIGHTS_PATH="${2:-}"
      shift 2
      ;;
    --lc0-backend)
      LC0_BACKEND="${2:-}"
      shift 2
      ;;
    --help|-h)
      usage
      exit 0
      ;;
    *)
      echo "ERROR: unknown argument: $1" >&2
      usage
      exit 1
      ;;
  esac
done

if [[ -z "${INPUT}" || -z "${OUTPUT}" ]]; then
  echo "ERROR: --in and --out are required." >&2
  usage
  exit 1
fi

if [[ ! -f "${INPUT}" ]]; then
  echo "ERROR: input file not found: ${INPUT}" >&2
  exit 1
fi

mkdir -p "$(dirname "${OUTPUT}")"

normalize_args() {
  local engine_type="$1"
  local raw="$2"

  # Legacy lc0 config often uses ":" between flags.
  local expanded="${raw//:/ }"
  # shellcheck disable=SC2206
  local tokens=( ${expanded} )
  local out=()
  local found_backend=0
  local found_weights=0

  for tok in "${tokens[@]}"; do
    case "${engine_type}" in
      lc0)
        if [[ "${tok}" == --backend=* ]]; then
          found_backend=1
          if [[ "${tok}" == "--backend=cuda-auto" ]]; then
            out+=("--backend=${LC0_BACKEND}")
          else
            out+=("${tok}")
          fi
          continue
        fi
        if [[ "${tok}" == --weights=* ]]; then
          found_weights=1
          case "${tok}" in
            --weights=weights.pb|--weights=weights.pb.gz|--weights=./weights.pb|--weights=./weights.pb.gz)
              out+=("--weights=${WEIGHTS_PATH}")
              ;;
            *)
              out+=("${tok}")
              ;;
          esac
          continue
        fi
        out+=("${tok}")
        ;;
      stockfish)
        if [[ "${tok}" == --backend=* || "${tok}" == --weights=* ]]; then
          continue
        fi
        out+=("${tok}")
        ;;
      *)
        out+=("${tok}")
        ;;
    esac
  done

  if [[ "${engine_type}" == "lc0" ]]; then
    if [[ ${found_backend} -eq 0 ]]; then
      out+=("--backend=${LC0_BACKEND}")
    fi
    if [[ ${found_weights} -eq 0 ]]; then
      out+=("--weights=${WEIGHTS_PATH}")
    fi
  fi

  if [[ ${#out[@]} -eq 0 ]]; then
    printf '%s' ""
    return
  fi
  printf '%s' "${out[*]}"
}

detect_engine_type() {
  local name_lc="$1"
  local exe_lc="$2"
  if [[ "${exe_lc}" == *lc0* || "${name_lc}" == lc0-* || "${name_lc}" == lc0* ]]; then
    printf '%s' "lc0"
    return
  fi
  if [[ "${exe_lc}" == *stockfish* || "${name_lc}" == sf-* || "${name_lc}" == sf* ]]; then
    printf '%s' "stockfish"
    return
  fi
  printf '%s' "generic"
}

resolve_exec_path() {
  local engine_type="$1"
  local eng_name="$2"
  local exe="$3"
  local exe_base="${exe##*/}"
  exe_base="${exe_base##*\\}"
  exe_base="${exe_base%.exe}"

  case "${engine_type}" in
    lc0)
      printf '%s' "${LC0_BIN}"
      ;;
    stockfish)
      printf '%s' "${SF_BIN}"
      ;;
    *)
      printf '%s' "${ENGINE_ROOT}/${eng_name}/${exe_base}"
      ;;
  esac
}

tmp_out="$(mktemp)"
trap 'rm -f "${tmp_out}"' EXIT

while IFS= read -r line || [[ -n "${line}" ]]; do
  trimmed="$(echo "${line}" | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//')"
  if [[ -z "${trimmed}" || "${trimmed}" == \#* ]]; then
    echo "${line}" >> "${tmp_out}"
    continue
  fi

  name="$(echo "${trimmed}" | awk '{print $1}')"
  port="$(echo "${trimmed}" | awk '{print $2}')"
  exe="$(echo "${trimmed}" | awk '{print $3}')"
  args="$(echo "${trimmed}" | awk '{$1=$2=$3=""; sub(/^[ \t]+/, ""); print}')"

  if [[ -z "${name}" || -z "${port}" || -z "${exe}" ]]; then
    echo "WARN: skipping unparsable line: ${line}" >&2
    continue
  fi

  name_lc="$(echo "${name}" | tr '[:upper:]' '[:lower:]')"
  exe_lc="$(echo "${exe}" | tr '[:upper:]' '[:lower:]')"
  engine_type="$(detect_engine_type "${name_lc}" "${exe_lc}")"
  exec_out="$(resolve_exec_path "${engine_type}" "${name}" "${exe}")"
  args_out="$(normalize_args "${engine_type}" "${args}")"

  if [[ -n "${args_out}" ]]; then
    printf '%s\t%s\t%s\t%s\n' "${name}" "${port}" "${exec_out}" "${args_out}" >> "${tmp_out}"
  else
    printf '%s\t%s\t%s\n' "${name}" "${port}" "${exec_out}" >> "${tmp_out}"
  fi
done < "${INPUT}"

cp "${tmp_out}" "${OUTPUT}"
echo "Wrote cloud profile: ${OUTPUT}"
