#!/usr/bin/env bash
# Cambia rapidamente la base de datos activa del proyecto (parameters.yml)
# usando perfiles por cliente en app/config/db_profiles/*.env
#
# Uso:
#   ./scripts/switch-db-profile.sh list
#   ./scripts/switch-db-profile.sh current
#   ./scripts/switch-db-profile.sh apply pruebas_unitarias
#   ./scripts/switch-db-profile.sh save cliente_nuevo
#   ./scripts/switch-db-profile.sh validate cliente_nuevo
#   ./scripts/switch-db-profile.sh rename cliente_viejo cliente_nuevo
#   ./scripts/switch-db-profile.sh delete cliente_nuevo

set -euo pipefail

ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
PROFILE_DIR="$ROOT_DIR/app/config/db_profiles"
PARAM_FILE="$ROOT_DIR/app/config/parameters.yml"
PARAM_DIST="$ROOT_DIR/app/config/parameters.yml.dist"
PROTECTED_PROFILES=("demosally" "pruebas_unitarias")

usage() {
  echo "Uso:"
  echo "  ./scripts/switch-db-profile.sh list"
  echo "  ./scripts/switch-db-profile.sh current"
  echo "  ./scripts/switch-db-profile.sh apply <perfil>"
  echo "  ./scripts/switch-db-profile.sh save <perfil>"
  echo "  ./scripts/switch-db-profile.sh validate <perfil>"
  echo "  ./scripts/switch-db-profile.sh rename <perfil_actual> <perfil_nuevo>"
  echo "  ./scripts/switch-db-profile.sh delete <perfil> [--force]"
}

is_protected_profile() {
  local profile="$1"
  local p
  for p in "${PROTECTED_PROFILES[@]}"; do
    if [[ "$p" == "$profile" ]]; then
      return 0
    fi
  done

  return 1
}

extract_yaml_value() {
  local key="$1"
  local line
  line="$(grep -E "^[[:space:]]*$key:" "$PARAM_FILE" | head -1 || true)"
  if [[ -z "$line" ]]; then
    echo ""
    return 0
  fi

  line="${line#*:}"
  line="$(echo "$line" | sed -E 's/^[[:space:]]+|[[:space:]]+$//g')"
  line="${line%\"}"
  line="${line#\"}"
  line="${line%\'}"
  line="${line#\'}"
  echo "$line"
}

yaml_quote() {
  local value="$1"
  value=${value//\\/\\\\}
  value=${value//\"/\\\"}
  printf '"%s"' "$value"
}

ensure_param_file() {
  if [[ ! -f "$PARAM_FILE" ]]; then
    if [[ -f "$PARAM_DIST" ]]; then
      cp "$PARAM_DIST" "$PARAM_FILE"
    else
      echo "parameters:" > "$PARAM_FILE"
    fi
  fi
}

update_yaml_key() {
  local key="$1"
  local value="$2"
  local tmp
  tmp="$(mktemp)"

  awk -v key="$key" -v value="$value" '
    BEGIN {
      found = 0;
      pattern = "^[[:space:]]*" key ":[[:space:]]*";
    }
    $0 ~ pattern {
      print "  " key ": " value;
      found = 1;
      next;
    }
    { print }
    END {
      if (!found) {
        print "  " key ": " value;
      }
    }
  ' "$PARAM_FILE" > "$tmp"

  mv "$tmp" "$PARAM_FILE"
}

list_profiles() {
  if [[ ! -d "$PROFILE_DIR" ]]; then
    echo "No existe carpeta de perfiles: $PROFILE_DIR"
    return 1
  fi

  echo "Perfiles disponibles:"
  shopt -s nullglob
  local files=("$PROFILE_DIR"/*.env)
  shopt -u nullglob

  if [[ ${#files[@]} -eq 0 ]]; then
    echo "  (sin perfiles)"
    return 0
  fi

  for f in "${files[@]}"; do
    local base
    base="$(basename "$f")"
    echo "  - ${base%.env}"
  done
}

show_current() {
  if [[ ! -f "$PARAM_FILE" ]]; then
    echo "No existe $PARAM_FILE"
    return 1
  fi

  echo "Configuracion actual en parameters.yml:"
  grep -E "^[[:space:]]*database_(host|port|name|user|password):" "$PARAM_FILE" || true
}

load_profile() {
  local profile="$1"
  local file="$PROFILE_DIR/$profile.env"

  if [[ ! -f "$file" ]]; then
    echo "Perfil no encontrado: $profile"
    echo "Esperado: $file"
    return 1
  fi

  set -a
  # shellcheck disable=SC1090
  source "$file"
  set +a

  if [[ -z "${DB_HOST:-}" || -z "${DB_PORT:-}" || -z "${DB_NAME:-}" || -z "${DB_USER:-}" ]]; then
    echo "Perfil incompleto. Se requieren DB_HOST, DB_PORT, DB_NAME, DB_USER"
    return 1
  fi
}

apply_profile() {
  local profile="$1"
  load_profile "$profile"

  ensure_param_file
  cp "$PARAM_FILE" "$PARAM_FILE.bak"

  update_yaml_key "database_host" "$(yaml_quote "$DB_HOST")"
  update_yaml_key "database_port" "$(yaml_quote "$DB_PORT")"
  update_yaml_key "database_name" "$(yaml_quote "$DB_NAME")"
  update_yaml_key "database_user" "$(yaml_quote "$DB_USER")"
  update_yaml_key "database_password" "$(yaml_quote "${DB_PASS:-}")"

  echo "Perfil aplicado: $profile"
  show_current
  echo "Backup previo: $PARAM_FILE.bak"
}

save_profile() {
  local profile="$1"
  local file="$PROFILE_DIR/$profile.env"

  ensure_param_file
  mkdir -p "$PROFILE_DIR"

  local host
  local port
  local name
  local user
  local pass
  local pass_shell
  host="$(extract_yaml_value database_host)"
  port="$(extract_yaml_value database_port)"
  name="$(extract_yaml_value database_name)"
  user="$(extract_yaml_value database_user)"
  pass="$(extract_yaml_value database_password)"
  printf -v pass_shell '%q' "$pass"

  if [[ -z "$host" || -z "$port" || -z "$name" || -z "$user" ]]; then
    echo "No se pudo guardar el perfil: faltan valores en parameters.yml"
    echo "Se requieren database_host, database_port, database_name, database_user"
    return 1
  fi

  cat > "$file" <<EOF
DB_HOST=$host
DB_PORT=$port
DB_NAME=$name
DB_USER=$user
DB_PASS=$pass_shell
EOF

  echo "Perfil guardado: $profile"
  echo "Archivo: $file"
}

validate_profile() {
  local profile="$1"
  load_profile "$profile"

  DB_HOST="$DB_HOST" \
  DB_PORT="$DB_PORT" \
  DB_NAME="$DB_NAME" \
  DB_USER="$DB_USER" \
  DB_PASS="${DB_PASS:-}" \
  php -r '
    $host = getenv("DB_HOST");
    $port = getenv("DB_PORT");
    $name = getenv("DB_NAME");
    $user = getenv("DB_USER");
    $pass = getenv("DB_PASS");

    try {
      $dsn = "mysql:host={$host};port={$port};dbname={$name};charset=utf8";
      $pdo = new PDO($dsn, $user, $pass, array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
      $pdo->query("SELECT 1");
      echo "Conexion OK: {$name}@{$host}:{$port}" . PHP_EOL;
    } catch (Throwable $e) {
      fwrite(STDERR, "Conexion FALLIDA: " . $e->getMessage() . PHP_EOL);
      exit(1);
    }
  '
}

rename_profile() {
  local old_name="$1"
  local new_name="$2"
  local old_file="$PROFILE_DIR/$old_name.env"
  local new_file="$PROFILE_DIR/$new_name.env"

  if [[ ! -f "$old_file" ]]; then
    echo "Perfil no encontrado: $old_name"
    return 1
  fi
  if [[ -f "$new_file" ]]; then
    echo "Ya existe un perfil con ese nombre: $new_name"
    return 1
  fi

  mv "$old_file" "$new_file"
  echo "Perfil renombrado: $old_name -> $new_name"
}

delete_profile() {
  local profile="$1"
  local force_delete="${2:-false}"
  local file="$PROFILE_DIR/$profile.env"

  if [[ ! -f "$file" ]]; then
    echo "Perfil no encontrado: $profile"
    return 1
  fi

  if is_protected_profile "$profile" && [[ "$force_delete" != "true" ]]; then
    echo "Perfil protegido: $profile"
    echo "Usa --force si realmente deseas eliminarlo"
    return 1
  fi

  rm -f "$file"
  echo "Perfil eliminado: $profile"
}

cmd="${1:-}";
case "$cmd" in
  list)
    list_profiles
    ;;
  current)
    show_current
    ;;
  apply)
    if [[ -z "${2:-}" ]]; then
      usage
      exit 1
    fi
    apply_profile "$2"
    ;;
  save)
    if [[ -z "${2:-}" ]]; then
      usage
      exit 1
    fi
    save_profile "$2"
    ;;
  validate)
    if [[ -z "${2:-}" ]]; then
      usage
      exit 1
    fi
    validate_profile "$2"
    ;;
  rename)
    if [[ -z "${2:-}" || -z "${3:-}" ]]; then
      usage
      exit 1
    fi
    rename_profile "$2" "$3"
    ;;
  delete)
    if [[ -z "${2:-}" ]]; then
      usage
      exit 1
    fi
    if [[ "${3:-}" == "--force" ]]; then
      delete_profile "$2" "true"
    else
      delete_profile "$2" "false"
    fi
    ;;
  *)
    usage
    exit 1
    ;;
esac
