#!/usr/bin/env bash

_jptrel_SRC="$0"
if [[ -n "${BASH_VERSION:-}" ]]; then
  _jptrel_SRC="${BASH_SOURCE[0]}"
elif [[ -n "${ZSH_VERSION:-}" ]]; then
  _jptrel_SRC="$(eval 'echo ${(%):-%x}')"
fi

_jptrel_DIR="$(cd "$(dirname "$_jptrel_SRC")" && pwd)"

_jptrel_usage() {
  cat <<'EOF'
Usage:
  jptrel <version> [-v|--verbose]

Examples:
  source ./jptrel
  jptrel 0.1.1
  jptrel 0.1.1 -v

Notes:
  jptrel publishes Jarvis-HEP-Portal to PyPI, refreshes the local editable install
  (pip install -e .), and verifies the installed package and built-in adapters.
EOF
}

_jptrel_install_editable() {
  python3 -m pip uninstall -y Jarvis-HEP-Portal jarvis-hep-portal Jarvis-Portal jarvis-portal jarvis_portal >/dev/null 2>&1 || true

  # Defensive cleanup for stale metadata from previous local installs.
  # Multiple leftover dist-info folders can make importlib.metadata report an
  # older version after a release reinstall.
  python3 - <<'PY'
from __future__ import annotations
import glob
import os
import shutil
import sysconfig

purelib = sysconfig.get_paths().get("purelib", "")
if purelib and os.path.isdir(purelib):
    patterns = [
        "jarvis_portal-*.dist-info",
        "Jarvis_Portal-*.dist-info",
        "jarvis_hep_portal-*.dist-info",
        "Jarvis_HEP_Portal-*.dist-info",
        "jarvis_portal*.egg-info",
        "Jarvis_Portal*.egg-info",
        "jarvis_hep_portal*.egg-info",
        "Jarvis_HEP_Portal*.egg-info",
        "jarvis_portal*.egg-link",
        "Jarvis_Portal*.egg-link",
        "jarvis_hep_portal*.egg-link",
        "Jarvis_HEP_Portal*.egg-link",
    ]
    for pat in patterns:
        for path in glob.glob(os.path.join(purelib, pat)):
            if os.path.isdir(path):
                shutil.rmtree(path, ignore_errors=True)
            else:
                try:
                    os.remove(path)
                except OSError:
                    pass

    installed_pkg = os.path.join(purelib, "jarvis_portal")
    if os.path.isdir(installed_pkg):
        shutil.rmtree(installed_pkg, ignore_errors=True)
PY

  python3 -m pip install --no-deps --force-reinstall -e .
}

_jptrel_prune_installed_metadata() {
  python3 - <<'PY'
from __future__ import annotations
import glob
import os
import re
import shutil
import sysconfig

purelib = sysconfig.get_paths().get("purelib", "")
if not purelib or not os.path.isdir(purelib):
    raise SystemExit(0)

dist_infos = []
for pat in (
    "jarvis_portal-*.dist-info",
    "Jarvis_Portal-*.dist-info",
    "jarvis_hep_portal-*.dist-info",
    "Jarvis_HEP_Portal-*.dist-info",
):
    for path in glob.glob(os.path.join(purelib, pat)):
        base = os.path.basename(path)
        m = re.search(r"-(\d+(?:\.\d+)*)\.dist-info$", base)
        if m:
            version_tuple = tuple(int(x) for x in m.group(1).split("."))
        else:
            version_tuple = (-1,)
        dist_infos.append((version_tuple, path))

dist_infos.sort(key=lambda item: item[0], reverse=True)
for _ver, stale_path in dist_infos[1:]:
    shutil.rmtree(stale_path, ignore_errors=True)

for pat in (
    "jarvis_portal*.egg-info",
    "Jarvis_Portal*.egg-info",
    "jarvis_hep_portal*.egg-info",
    "Jarvis_HEP_Portal*.egg-info",
    "jarvis_portal*.egg-link",
    "Jarvis_Portal*.egg-link",
    "jarvis_hep_portal*.egg-link",
    "Jarvis_HEP_Portal*.egg-link",
):
    for path in glob.glob(os.path.join(purelib, pat)):
        if os.path.isdir(path):
            shutil.rmtree(path, ignore_errors=True)
        else:
            try:
                os.remove(path)
            except OSError:
                pass
PY
}

_jptrel_clean_artifacts() {
  python3 - <<'PY'
from __future__ import annotations
import glob
import os
import shutil

for path in ("dist", "build"):
    if os.path.isdir(path):
        shutil.rmtree(path, ignore_errors=True)
for pattern in ("*.egg-info", "src/*.egg-info"):
    for matched in glob.glob(pattern):
        if os.path.isdir(matched):
            shutil.rmtree(matched, ignore_errors=True)
PY
}

_jptrel_clean_local_junk() {
  python3 - <<'PY'
from __future__ import annotations
from pathlib import Path

for path in Path(".").rglob(".DS_Store"):
    try:
        path.unlink()
        print(f"[jptrel] removed local junk file: {path}")
    except OSError as exc:
        print(f"[jptrel] WARNING: failed to remove {path}: {exc}")
PY
}

_jptrel_bump_version() {
  local version="$1"
  python3 - <<'PY' "$version"
from pathlib import Path
import re
import sys

version = sys.argv[1]

pyproject = Path("pyproject.toml")
text = pyproject.read_text(encoding="utf-8")
updated, n = re.subn(
    r'(?m)^version\s*=\s*"[^"]+"$',
    f'version = "{version}"',
    text,
    count=1,
)
if n != 1:
    raise SystemExit("[jptrel] Failed to locate version field in pyproject.toml")
pyproject.write_text(updated, encoding="utf-8")
print(f"[jptrel] pyproject.toml updated to {version}")

version_file = Path("src/jarvis_portal/_version.py")
text = version_file.read_text(encoding="utf-8")
updated, n = re.subn(
    r'(?m)^__version__\s*=\s*"[^"]+"$',
    f'__version__ = "{version}"',
    text,
    count=1,
)
if n != 1:
    raise SystemExit("[jptrel] Failed to locate __version__ in src/jarvis_portal/_version.py")
version_file.write_text(updated, encoding="utf-8")
print(f"[jptrel] src/jarvis_portal/_version.py updated to {version}")
PY
}

_jptrel_upload() {
  local verbose="${1:-0}"
  local version="${2:-}"

  if [[ "$verbose" -eq 1 ]]; then
    echo "[jptrel] Upload command: python3 -m twine upload -r pypi --verbose dist/*"
    python3 -m twine upload -r pypi --verbose dist/*
  else
    echo "[jptrel] Upload command: python3 -m twine upload -r pypi dist/*"
    python3 -m twine upload -r pypi dist/*
  fi

  local status=$?
  if [[ "$status" -ne 0 ]]; then
    if [[ "$verbose" -eq 1 ]]; then
      cat >&2 <<'EOF'
[jptrel] Upload failed.
[jptrel] The verbose twine output above contains PyPI's exact rejection reason.
[jptrel] Common 400 causes are a blocked/similar project name, an already-used
[jptrel] version/file, or server-side metadata policy. If PyPI says the project
[jptrel] name is too similar to an existing project, choose a less ambiguous
[jptrel] package name in pyproject.toml and rerun jptrel with a fresh version.
EOF
    else
      echo "[jptrel] Upload failed. Rerun with '-v' for PyPI's full rejection details:" >&2
      echo "[jptrel]   jptrel ${version:-<version>} -v" >&2
    fi
    return "$status"
  fi
}

_jptrel_verify_install() {
  python3 - <<'PY'
import importlib.metadata as m
from shutil import which

import jarvis_portal
from jarvis_portal import create_default_registry

print("[jptrel] installed version:", m.version("Jarvis-HEP-Portal"))
print("[jptrel] runtime version:", jarvis_portal.__version__)
print("[jptrel] jportal command:", which("jportal"))
print("[jptrel] input formats:", ", ".join(create_default_registry().available_formats("input")))
print("[jptrel] output formats:", ", ".join(create_default_registry().available_formats("output")))

# Show all discovered Portal distributions to catch metadata duplication.
matches = []
for d in m.distributions():
    name = (d.metadata.get("Name") or "").lower()
    if name in {"jarvis-hep-portal", "jarvis_hep_portal", "jarvis-portal", "jarvis_portal"}:
        matches.append((d.metadata.get("Name"), d.version, str(d.locate_file(""))))

if matches:
    print("[jptrel] discovered Portal distributions:")
    for name, version, loc in matches:
        print(f"  - {name} {version} @ {loc}")
PY

  # Refresh shell command hash tables after pip install (zsh/bash).
  hash -r 2>/dev/null || true
  rehash 2>/dev/null || true

  local cli_cmd
  cli_cmd="$(command -v jportal 2>/dev/null || true)"
  if [[ -z "$cli_cmd" ]]; then
    cli_cmd="$(python3 - <<'PY'
from shutil import which
print(which("jportal") or "")
PY
)"
  fi

  if [[ -z "$cli_cmd" ]]; then
    echo "[jptrel] WARNING: jportal CLI not found in PATH after reinstall; skip CLI --version check." >&2
    return 0
  fi

  "$cli_cmd" --version >/dev/null
  echo "[jptrel] CLI --version check passed: $cli_cmd"
}

jptrel() {
  (
    set -euo pipefail

    if [[ $# -eq 1 && ( "$1" == "-h" || "$1" == "--help" ) ]]; then
      _jptrel_usage
      exit 0
    fi

    if [[ $# -lt 1 ]]; then
      _jptrel_usage
      exit 2
    fi

    local version="$1"; shift || true
    local upload_verbose=0
    if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
      echo "[jptrel] Invalid version: $version (expected X.Y.Z)" >&2
      exit 2
    fi

    while [[ $# -gt 0 ]]; do
      case "$1" in
        -v|--verbose)
          upload_verbose=1
          ;;
        *)
          echo "[jptrel] Unknown argument: $1" >&2
          _jptrel_usage
          exit 2
          ;;
      esac
      shift
    done

    cd "$_jptrel_DIR"
    if [[ ! -f "pyproject.toml" ]]; then
      echo "[jptrel] pyproject.toml not found in $_jptrel_DIR" >&2
      exit 2
    fi

    echo "[jptrel] Release target version: $version"
    echo "[jptrel] Repository: pypi"
    if [[ "$upload_verbose" -eq 1 ]]; then
      echo "[jptrel] Upload verbosity: verbose"
    else
      echo "[jptrel] Upload verbosity: normal"
    fi
    echo "[jptrel] Working directory: $(pwd)"
    echo "[jptrel] Python: $(python3 -V 2>/dev/null || true)"

    echo "[jptrel] Step 1/5: bump version"
    _jptrel_bump_version "$version"

    echo "[jptrel] Step 2/5: clean build artifacts"
    _jptrel_clean_artifacts
    _jptrel_clean_local_junk
    _jptrel_prune_installed_metadata

    echo "[jptrel] Step 3/5: build package"
    python3 -m pip install --disable-pip-version-check -q -U build twine
    python3 -m build
    python3 -m twine check dist/*

    echo "[jptrel] Step 4/5: upload"
    _jptrel_upload "$upload_verbose" "$version"

    echo "[jptrel] Step 5/5: local editable install/verify"
    _jptrel_install_editable
    _jptrel_verify_install

    echo "[jptrel] Done."
  )
}

_jptrel_sourced=0
if [[ -n "${BASH_VERSION:-}" ]]; then
  [[ "${BASH_SOURCE[0]}" != "$0" ]] && _jptrel_sourced=1
elif [[ -n "${ZSH_VERSION:-}" ]]; then
  case "${ZSH_EVAL_CONTEXT:-}" in
    *:file) _jptrel_sourced=1 ;;
  esac
fi

if [[ "$_jptrel_sourced" -eq 0 ]]; then
  echo "This file defines the 'jptrel' bash function. Please source it first:" >&2
  echo "  source \"$0\"" >&2
  exit 1
fi
