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

APP_DIR=/opt/docking-riset
DATA_DIR="${DOCKING_RISET_DATA_DIR:-$HOME/.local/share/docking-riset}"
MINIFORGE="$DATA_DIR/miniforge3"
CONDA="$MINIFORGE/bin/conda"
ENV="$DATA_DIR/env-1.4.1"
MODE="${1:-all}"
LOG_DIR="$DATA_DIR/logs"
INSTALL_LOG="$LOG_DIR/dependency-install-1.4.1.log"
mkdir -p "$DATA_DIR" "$LOG_DIR"

if [ "${EUID:-$(id -u)}" -eq 0 ]; then
  echo "ERROR: jalankan docking-riset-install sebagai USER biasa, bukan sudo/root." >&2
  echo "Contoh: docking-riset-install all" >&2
  exit 2
fi

log() { printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" | tee -a "$INSTALL_LOG"; }

install_miniforge() {
  if [ -x "$CONDA" ]; then
    log "Miniforge sudah tersedia: $MINIFORGE"
    return 0
  fi
  log "Mengunduh Miniforge untuk environment ilmiah terisolasi..."
  local arch mf_arch installer url
  arch="$(uname -m)"
  case "$arch" in
    x86_64|amd64) mf_arch="x86_64" ;;
    aarch64|arm64) mf_arch="aarch64" ;;
    *) log "ERROR: arsitektur belum didukung installer otomatis: $arch"; exit 3 ;;
  esac
  installer="$DATA_DIR/Miniforge3-Linux-${mf_arch}.sh"
  url="https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-${mf_arch}.sh"
  curl -fL --retry 4 --retry-delay 3 "$url" -o "$installer"
  bash "$installer" -b -p "$MINIFORGE"
  rm -f "$installer"
  "$CONDA" config --set channel_priority strict >/dev/null 2>&1 || true
}

create_full_env() {
  install_miniforge
  if [ -x "$ENV/bin/python" ]; then
    log "Environment v1.4.1 sudah ada: $ENV"
  else
    log "Membuat environment FULL v1.4.1 (Python 3.11 + scientific stack)..."
    "$CONDA" create -y -p "$ENV" -c conda-forge \
      python=3.11 pip setuptools wheel \
      numpy pandas scipy requests h5py \
      rdkit openmm pdbfixer openbabel \
      xtb mopac gemmi tqdm lxml networkx pillow matplotlib prody
  fi
  export PATH="$ENV/bin:$PATH"
}

install_python_stack() {
  create_full_env
  log "Memperbarui pip/setuptools/wheel..."
  "$ENV/bin/python" -m pip install --upgrade pip setuptools wheel | tee -a "$INSTALL_LOG"

  log "Memasang Streamlit, AutoDock Vina, Meeko, py3Dmol..."
  "$ENV/bin/python" -m pip install --prefer-binary --upgrade \
      streamlit py3Dmol vina 'meeko>=0.7.1' | tee -a "$INSTALL_LOG"

  log "Memasang stack DFT/QM lengkap: PySCF, geomeTRIC, PyBerny..."
  "$ENV/bin/python" -m pip install --prefer-binary --upgrade \
      'pyscf>=2.5' 'geometric>=1.0' 'pyberny>=0.6' | tee -a "$INSTALL_LOG"

  log "Memasang PLIP..."
  if ! "$ENV/bin/python" -m pip install --prefer-binary --upgrade plip | tee -a "$INSTALL_LOG"; then
    log "Resolver PLIP gagal; mencoba --no-deps karena Open Babel/lxml/numpy/networkx sudah disediakan conda-forge."
    "$ENV/bin/python" -m pip install --no-deps --upgrade plip | tee -a "$INSTALL_LOG"
  fi
}

apply_guard() {
  log "Mengaktifkan proteksi browser translation untuk React/Streamlit..."
  if ! "$ENV/bin/python" "$APP_DIR/patch_streamlit_shell.py" >>"$INSTALL_LOG" 2>&1; then
    log "WARNING: proteksi browser translation tidak dapat diterapkan; aplikasi tetap dapat dijalankan."
  fi
}

find_meeko_cli() {
  local name="$1"
  for c in "$ENV/bin/$name.py" "$ENV/bin/$name"; do
    [ -x "$c" ] && { printf '%s' "$c"; return 0; }
  done
  return 1
}

verify_all() {
  create_full_env
  export PATH="$ENV/bin:$PATH"
  log "Verifikasi seluruh modul Python dan engine komputasi..."

  "$ENV/bin/python" - <<'PY' | tee -a "$INSTALL_LOG"
import importlib, sys
checks = [
    ("numpy","NumPy"), ("pandas","pandas"), ("scipy","SciPy"),
    ("requests","Requests"), ("streamlit","Streamlit"), ("rdkit","RDKit"),
    ("py3Dmol","py3Dmol"), ("vina","AutoDock Vina"), ("meeko","Meeko"),
    ("gemmi","Gemmi"), ("tqdm","tqdm"), ("openmm","OpenMM"),
    ("pdbfixer","PDBFixer"), ("openbabel","Open Babel Python"),
    ("pyscf","PySCF"), ("geometric","geomeTRIC"), ("berny","PyBerny"),
    ("h5py","h5py"), ("prody","ProDy"), ("lxml","lxml"), ("networkx","NetworkX"),
]
failed=[]
for mod,label in checks:
    try:
        m=importlib.import_module(mod)
        print(f"OK   {label:24s} {getattr(m,'__version__','')}")
    except Exception as exc:
        print(f"FAIL {label:24s} {exc}")
        failed.append(label)
if failed:
    print("\nKomponen Python gagal:", ", ".join(failed))
    raise SystemExit(2)
print("\nSEMUA MODUL PYTHON WAJIB: OK")
PY

  local failed=0
  check_cmd() {
    local c="$1" label="$2"
    if command -v "$c" >/dev/null 2>&1; then
      log "OK $label: $(command -v "$c")"
    else
      log "ERROR $label tidak ditemukan: $c"
      failed=1
    fi
  }
  check_cmd obabel "Open Babel CLI"
  check_cmd xtb "GFN2-xTB CLI"
  check_cmd mopac "MOPAC CLI (AM1/RM1/PM7)"

  local rec lig
  rec="$(find_meeko_cli mk_prepare_receptor || true)"
  lig="$(find_meeko_cli mk_prepare_ligand || true)"
  if [ -z "$rec" ]; then log "ERROR Meeko receptor CLI tidak ditemukan"; failed=1; else log "OK Meeko receptor CLI: $rec"; fi
  if [ -z "$lig" ]; then log "ERROR Meeko ligand CLI tidak ditemukan"; failed=1; else log "OK Meeko ligand CLI: $lig"; fi

  local plip_cli=""
  for c in "$ENV/bin/plip" "$ENV/bin/plipcmd.py"; do [ -x "$c" ] && plip_cli="$c" && break; done
  if [ -n "$plip_cli" ]; then log "OK PLIP CLI: $plip_cli"; else log "WARNING PLIP CLI tidak ditemukan; instalasi Python PLIP mungkin tetap tersedia."; fi

  if command -v orca >/dev/null 2>&1; then
    log "OK ORCA eksternal: $(command -v orca)"
  else
    log "INFO ORCA tidak dipasang otomatis (lisensi/distribusi terpisah). PySCF DFT tetap tersedia."
  fi

  if [ "$failed" -ne 0 ]; then
    log "ERROR: verifikasi FULL gagal. Jalankan: docking-riset-install repair"
    return 1
  fi
  log "VERIFIKASI FULL BERHASIL: docking + MMFF/UFF + AM1/RM1/PM7 + xTB + PySCF DFT siap."
}

full_install() {
  install_python_stack
  apply_guard
  verify_all
}

case "$MODE" in
  all|full|--all|--full|"")
    full_install
    ;;
  verify|--verify)
    verify_all
    ;;
  repair|--repair)
    log "Repair FULL: memastikan Miniforge, environment dan seluruh dependency kembali lengkap."
    full_install
    ;;
  reset|--reset)
    log "Menghapus environment komputasi v1.4.1 (data hasil runs tidak disentuh)..."
    rm -rf "$ENV"
    full_install
    ;;
  *)
    echo "Penggunaan: docking-riset-install [all|verify|repair|reset]" >&2
    exit 2
    ;;
esac

cat <<MSG

============================================================
Docking Riset 1.5.2-r3 — instalasi dependency selesai
============================================================
Environment : $ENV
Log         : $INSTALL_LOG

Jalankan aplikasi:
  docking-riset

Verifikasi ulang:
  docking-riset-install verify

Repair penuh:
  docking-riset-install repair

Catatan: ORCA adalah alternatif DFT berlisensi/distribusi terpisah dan tidak
        diperlukan untuk PySCF DFT yang sudah dipasang oleh installer FULL.
MSG
