#!/usr/bin/env bash
# prepare_chrome_profile — clona un user-data-dir de Chrome/Chromium conservando solo
# las extensiones de una lista blanca. Sirve para perfiles de scraping limpios.

set -euo pipefail

# ── defaults ──────────────────────────────────────────────────────────────────
_SRC=""
_DST=""
_FORCE=0
# uBlock Origin Lite por defecto
_KEEP=()
_DEFAULT_EXT="ddkjiahejlhfcafbddmgiahcphecmpfh"

# ── parse args ────────────────────────────────────────────────────────────────
_usage() {
    cat >&2 <<'EOF'
Usage: prepare_chrome_profile --src <user-data-dir> --dst <user-data-dir> \
           [--keep <ext_id>]... [--force]

  --src   user-data-dir origen (ej. $HOME/.config/chromium)
  --dst   user-data-dir destino a crear
  --keep  ID de extensión a conservar (repetible). Default: uBlock Origin Lite
  --force si --dst existe, lo borra y recrea; sin flag aborta si existe

Exit codes:
  0  éxito
  1  error de argumento o validación
  2  --dst ya existe y no se pasó --force
  3  --src igual a --dst (mismo path real)
  4  error de copia/rsync
EOF
    exit 1
}

while [[ $# -gt 0 ]]; do
    case "$1" in
        --src)   _SRC="$2";  shift 2 ;;
        --dst)   _DST="$2";  shift 2 ;;
        --keep)  _KEEP+=("$2"); shift 2 ;;
        --force) _FORCE=1;   shift ;;
        -h|--help) _usage ;;
        *) echo "prepare_chrome_profile: argumento desconocido: $1" >&2; _usage ;;
    esac
done

# ── validaciones básicas ──────────────────────────────────────────────────────
if [[ -z "$_SRC" || -z "$_DST" ]]; then
    echo "prepare_chrome_profile: --src y --dst son obligatorios" >&2
    exit 1
fi

if [[ ! -d "$_SRC/Default" ]]; then
    echo "prepare_chrome_profile: $_SRC/Default no existe; ¿es un user-data-dir válido?" >&2
    exit 1
fi

# Resolver paths reales para comparar (evitar borrar src cuando src==dst)
_SRC_REAL="$(realpath "$_SRC")"
_DST_REAL="$(realpath -m "$_DST")"   # -m: no requiere que exista

if [[ "$_SRC_REAL" == "$_DST_REAL" ]]; then
    echo "prepare_chrome_profile: --src y --dst resuelven al mismo path: $_SRC_REAL" >&2
    exit 3
fi

# También rechazar si --dst es prefijo de --src (evitar borrar el origen)
if [[ "$_SRC_REAL" == "$_DST_REAL"/* ]]; then
    echo "prepare_chrome_profile: --src está dentro de --dst; operación peligrosa, abortando" >&2
    exit 3
fi

# ── lista blanca de extensiones ───────────────────────────────────────────────
if [[ ${#_KEEP[@]} -eq 0 ]]; then
    _KEEP=("$_DEFAULT_EXT")
fi

# ── gestionar destino ─────────────────────────────────────────────────────────
if [[ -d "$_DST" ]]; then
    if [[ $_FORCE -eq 1 ]]; then
        rm -rf "$_DST"
    else
        echo "prepare_chrome_profile: $_DST ya existe; usa --force para sobreescribir" >&2
        exit 2
    fi
fi

mkdir -p "$_DST/Default"

# ── copiar Local State (HMAC seed para Secure Preferences) ────────────────────
if [[ -f "$_SRC/Local State" ]]; then
    cp "$_SRC/Local State" "$_DST/Local State"
fi

# ── rsync del perfil Default excluyendo caché y locks ─────────────────────────
rsync -a \
    --exclude='Cache/' \
    --exclude='Code Cache/' \
    --exclude='GPUCache/' \
    --exclude='Dawn Cache/' \
    --exclude='DawnGraphiteCache/' \
    --exclude='DawnWebGPUCache/' \
    --exclude='Service Worker/CacheStorage/' \
    --exclude='Service Worker/ScriptCache/' \
    --exclude='Singleton*' \
    --exclude='*.lock' \
    --exclude='lockfile' \
    --exclude='Sessions/' \
    --exclude='Session Storage/' \
    --exclude='Current Session' \
    --exclude='Current Tabs' \
    --exclude='Last Session' \
    --exclude='Last Tabs' \
    "$_SRC/Default/" "$_DST/Default/" || {
        echo "prepare_chrome_profile: rsync falló (exit $?)" >&2
        exit 4
    }

# ── eliminar extensiones fuera de la lista blanca ────────────────────────────
_EXT_DIR="$_DST/Default/Extensions"
_removed=()
_kept=()

if [[ -d "$_EXT_DIR" ]]; then
    while IFS= read -r -d '' ext_path; do
        ext_id="$(basename "$ext_path")"
        # Conservar siempre la carpeta Temp (usada por Chrome durante installs)
        if [[ "$ext_id" == "Temp" ]]; then
            continue
        fi
        # Comprobar si está en la lista blanca
        _in_keep=0
        for keep_id in "${_KEEP[@]}"; do
            if [[ "$ext_id" == "$keep_id" ]]; then
                _in_keep=1
                break
            fi
        done
        if [[ $_in_keep -eq 1 ]]; then
            _kept+=("$ext_id")
        else
            rm -rf "$ext_path"
            _removed+=("$ext_id")
        fi
    done < <(find "$_EXT_DIR" -mindepth 1 -maxdepth 1 -type d -print0)
fi

# ── purgar referencias a extensiones eliminadas en Preferences ───────────────
# Chrome re-descarga del Web Store cualquier extensión que aparezca en
# extensions.settings aunque su carpeta haya sido borrada. Editamos el JSON
# con python3 para evitar ese comportamiento.
if [[ ${#_removed[@]} -gt 0 ]]; then
    # Construir lista Python de IDs eliminados
    _py_ids_list=""
    for _id in "${_removed[@]}"; do
        _py_ids_list+="\"${_id}\","
    done
    _py_ids_list="[${_py_ids_list%,}]"

    for _prefs_file in "$_DST/Default/Preferences" "$_DST/Default/Secure Preferences"; do
        if [[ -f "$_prefs_file" ]]; then
            python3 - "$_prefs_file" "$_py_ids_list" <<'PY' || \
                echo "prepare_chrome_profile: advertencia — no se pudieron purgar refs en $(basename "$_prefs_file")" >&2
import sys, json

prefs_path = sys.argv[1]
removed_ids = json.loads(sys.argv[2])

with open(prefs_path, "r", encoding="utf-8") as f:
    data = json.load(f)

# 1. extensions.settings.<id>
ext_settings = data.get("extensions", {}).get("settings", {})
for ext_id in removed_ids:
    ext_settings.pop(ext_id, None)

# 2. extensions.pinned_extensions (lista de IDs)
pinned = data.get("extensions", {}).get("pinned_extensions", None)
if isinstance(pinned, list):
    data["extensions"]["pinned_extensions"] = [
        pid for pid in pinned if pid not in removed_ids
    ]

# 3. protection.macs.extensions.settings.<id>  (Secure Preferences)
try:
    mac_ext = data["protection"]["macs"]["extensions"]["settings"]
    for ext_id in removed_ids:
        mac_ext.pop(ext_id, None)
except (KeyError, TypeError):
    pass

with open(prefs_path, "w", encoding="utf-8") as f:
    json.dump(data, f, separators=(",", ":"))
PY
        fi
    done
fi

# ── emitir resultado JSON ─────────────────────────────────────────────────────
_json_array() {
    # Convierte array bash en JSON array de strings
    local arr=("$@")
    local out="["
    local first=1
    for item in "${arr[@]}"; do
        if [[ $first -eq 1 ]]; then
            out+="\"$item\""
            first=0
        else
            out+=",\"$item\""
        fi
    done
    out+="]"
    echo "$out"
}

_kept_json="$(_json_array "${_kept[@]+"${_kept[@]}"}")"
_removed_json="$(_json_array "${_removed[@]+"${_removed[@]}"}")"

printf '{"dst":"%s","kept":%s,"removed":%s}\n' \
    "$_DST_REAL" \
    "$_kept_json" \
    "$_removed_json"
