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

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
ENV_FILE="${REPO_ROOT}/credentials/.env"

PLUGIN_SLUG="${PLUGIN_SLUG:-feca_mailshots_plugin}"
SOURCE_DIR="${SOURCE_DIR:-${REPO_ROOT}/${PLUGIN_SLUG}}"
DRY_RUN=0

usage() {
  cat <<'USAGE'
Usage: scripts/deploy_remote.sh [--dry-run] [--source /path/to/plugin]

Deploys plugin files to DEPLOYMENT_DIRECTORY on the remote host using
REMOTE_SSH_* values from credentials/.env.
USAGE
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --dry-run)
      DRY_RUN=1
      shift
      ;;
    --source)
      SOURCE_DIR="${2:-}"
      shift 2
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "Unknown argument: $1" >&2
      usage >&2
      exit 1
      ;;
  esac
done

if [[ ! -f "${ENV_FILE}" ]]; then
  echo "Error: credentials file not found: ${ENV_FILE}" >&2
  exit 1
fi

if [[ ! -d "${SOURCE_DIR}" ]]; then
  echo "Error: source directory not found: ${SOURCE_DIR}" >&2
  exit 1
fi

PLUGIN_BASENAME="$(basename "${SOURCE_DIR}")"
PLUGIN_MAIN_FILE="${SOURCE_DIR}/${PLUGIN_BASENAME}.php"
if [[ ! -f "${PLUGIN_MAIN_FILE}" ]]; then
  echo "Error: plugin main file not found: ${PLUGIN_MAIN_FILE}" >&2
  exit 1
fi

COMPOSER_JSON="${REPO_ROOT}/composer.json"
COMPOSER_LOCK="${REPO_ROOT}/composer.lock"
LOCAL_VENDOR_DIR="${REPO_ROOT}/vendor"
if [[ ! -f "${COMPOSER_JSON}" || ! -f "${COMPOSER_LOCK}" ]]; then
  echo "Error: missing composer.json/composer.lock in ${REPO_ROOT}" >&2
  exit 1
fi

load_env_value() {
  local key="$1"
  local line
  line="$(grep -E "^${key}=" "${ENV_FILE}" | tail -n 1 || true)"
  line="${line#*=}"
  line="${line%\"}"
  line="${line#\"}"
  line="${line%\'}"
  line="${line#\'}"
  printf '%s' "${line}"
}

SSH_HOST="$(load_env_value REMOTE_SSH_HOST)"
SSH_PORT="$(load_env_value REMOTE_SSH_PORT)"
SSH_USER="$(load_env_value REMOTE_SSH_USER)"
SSH_KEY_RAW="$(load_env_value REMOTE_SSH_KEY)"
REMOTE_DIR_RAW="$(load_env_value DEPLOYMENT_DIRECTORY)"

if [[ -z "${SSH_HOST}" || -z "${SSH_USER}" || -z "${SSH_KEY_RAW}" ]]; then
  echo "Error: missing REMOTE_SSH_* values in ${ENV_FILE}" >&2
  exit 1
fi

if [[ -z "${REMOTE_DIR_RAW}" ]]; then
  echo "Error: missing DEPLOYMENT_DIRECTORY in ${ENV_FILE}" >&2
  exit 1
fi

if [[ -z "${SSH_PORT}" ]]; then
  SSH_PORT=22
fi

if [[ "${SSH_KEY_RAW}" = /* ]]; then
  SSH_KEY_PATH="${SSH_KEY_RAW}"
else
  SSH_KEY_PATH="${REPO_ROOT}/${SSH_KEY_RAW}"
fi

if [[ ! -f "${SSH_KEY_PATH}" ]]; then
  echo "Error: SSH key not found: ${SSH_KEY_PATH}" >&2
  exit 1
fi

SSH_TARGET="${SSH_USER}@${SSH_HOST}"

if [[ "${REMOTE_DIR_RAW}" = /* ]]; then
  REMOTE_DIR="${REMOTE_DIR_RAW}"
else
  REMOTE_DIR="/home/${SSH_USER}/${REMOTE_DIR_RAW}"
fi
REMOTE_PLUGIN_VENDOR_DIR="${REMOTE_DIR}/vendor"

CURRENT_VERSION="$(awk '
  /Version:/ {
    line = $0
    sub(/^.*Version:[[:space:]]*/, "", line)
    if (match(line, /^[0-9]+\.[0-9]+\.[0-9]+/)) {
      print substr(line, RSTART, RLENGTH)
      exit
    }
  }
' "${PLUGIN_MAIN_FILE}")"
if [[ -z "${CURRENT_VERSION}" ]]; then
  echo "Error: could not parse Version: x.y.z from ${PLUGIN_MAIN_FILE}" >&2
  exit 1
fi

IFS='.' read -r VER_MAJOR VER_MINOR VER_PATCH <<< "${CURRENT_VERSION}"
NEW_PATCH=$((VER_PATCH + 1))
NEW_VERSION="${VER_MAJOR}.${VER_MINOR}.${NEW_PATCH}"

if [[ "${DRY_RUN}" -eq 1 ]]; then
  echo "Version bump (dry-run): ${CURRENT_VERSION} -> ${NEW_VERSION}"
else
  TMP_FILE="${PLUGIN_MAIN_FILE}.tmp.$$"
  awk -v new_version="${NEW_VERSION}" '
    BEGIN { done = 0 }
    {
      if (!done && $0 ~ /^[[:space:]]*\*[[:space:]]*Version:[[:space:]]*[0-9]+\.[0-9]+\.[0-9]+[[:space:]]*$/) {
        sub(/[0-9]+\.[0-9]+\.[0-9]+/, new_version)
        done = 1
      }
      print
    }
    END {
      if (!done) {
        exit 2
      }
    }
  ' "${PLUGIN_MAIN_FILE}" > "${TMP_FILE}"
  mv "${TMP_FILE}" "${PLUGIN_MAIN_FILE}"
  echo "Version bumped: ${CURRENT_VERSION} -> ${NEW_VERSION}"
fi

echo "Remote host: ${SSH_TARGET}:${SSH_PORT}"
echo "Source dir: ${SOURCE_DIR}"
echo "Deploy target: ${REMOTE_DIR}"
echo "Vendor target: ${REMOTE_PLUGIN_VENDOR_DIR}"

if [[ "${DRY_RUN}" -eq 1 ]]; then
  if [[ ! -f "${LOCAL_VENDOR_DIR}/autoload.php" ]]; then
    echo "Warning: ${LOCAL_VENDOR_DIR}/autoload.php not found. Run scripts/install_dependencies.sh before real deploy."
  fi
else
  "${REPO_ROOT}/scripts/install_dependencies.sh" --skip-node
  if [[ ! -f "${LOCAL_VENDOR_DIR}/autoload.php" ]]; then
    echo "Error: ${LOCAL_VENDOR_DIR}/autoload.php is missing. Install dependencies first (scripts/install_dependencies.sh)." >&2
    exit 1
  fi
  php "${REPO_ROOT}/scripts/validate_composer_vendor.php" "${LOCAL_VENDOR_DIR}"
fi

ssh -p "${SSH_PORT}" \
  -i "${SSH_KEY_PATH}" \
  -o BatchMode=yes \
  -o StrictHostKeyChecking=accept-new \
  "${SSH_TARGET}" \
  "mkdir -p '${REMOTE_DIR}' '${REMOTE_PLUGIN_VENDOR_DIR}'"

RSYNC_SSH="ssh -p ${SSH_PORT} -i ${SSH_KEY_PATH} -o BatchMode=yes -o StrictHostKeyChecking=accept-new"
RSYNC_ARGS=(
  -avz
  --delete
  --exclude '.git/'
  --exclude '.codex/'
  --exclude '.DS_Store'
)

if [[ "${DRY_RUN}" -eq 1 ]]; then
  RSYNC_ARGS+=(-n)
fi

rsync "${RSYNC_ARGS[@]}" \
  -e "${RSYNC_SSH}" \
  "${SOURCE_DIR}/" \
  "${SSH_TARGET}:${REMOTE_DIR}/"

VENDOR_RSYNC_ARGS=(
  -avz
  --delete
)
if [[ "${DRY_RUN}" -eq 1 ]]; then
  VENDOR_RSYNC_ARGS+=(-n)
fi

rsync "${VENDOR_RSYNC_ARGS[@]}" \
  -e "${RSYNC_SSH}" \
  "${LOCAL_VENDOR_DIR}/" \
  "${SSH_TARGET}:${REMOTE_PLUGIN_VENDOR_DIR}/"

if [[ "${DRY_RUN}" -eq 1 ]]; then
  echo "Dry-run complete. No remote files were changed."
else
  ssh -p "${SSH_PORT}" \
    -i "${SSH_KEY_PATH}" \
    -o BatchMode=yes \
    -o StrictHostKeyChecking=accept-new \
    "${SSH_TARGET}" \
    "test -f '${REMOTE_DIR}/vendor/autoload.php' && test -f '${REMOTE_DIR}/vendor/thecodingmachine/safe/lib/special_cases.php'"
  echo "Deploy complete."
fi
