#!/usr/bin/env bash
# clean_chrome_profile_extensions — purga in-place extensiones fuera de la whitelist
# de un perfil Chrome/Chromium existente. Borra las carpetas de disco y limpia las
# referencias en Preferences y Secure Preferences para que Chromium no las reinstale.

set -euo pipefail

clean_chrome_profile_extensions() {
    # ── defaults ──────────────────────────────────────────────────────────────
    local _user_data_dir="${HOME}/.config/chromium"
    local _profile_dir="Default"
    local _keep=()
    local _default_ext="ddkjiahejlhfcafbddmgiahcphecmpfh"
    local _dry_run=0

    # ── parse args ─────────────────────────────────────────────────────────────
    _usage() {
        cat >&2 <<'EOF'
Usage: clean_chrome_profile_extensions [--user-data-dir <dir>] [--profile-directory <name>]
           [--keep <ext_id>]... [--dry-run]

  --user-data-dir      Raíz del perfil. Default: ~/.config/chromium
  --profile-directory  Subperfil. Default: Default
  --keep <ext_id>      ID de extensión a conservar (repetible).
                       Default si no se pasa ninguno: ddkjiahejlhfcafbddmgiahcphecmpfh (uBlock Origin Lite)
  --dry-run            Lista qué se borraría sin tocar nada.

Exit codes:
  0  éxito (o dry-run completado)
  1  error de argumento o validación
  2  chromium está corriendo (solo en modo real)
  3  directorio de extensiones no encontrado
EOF
        return 1
    }

    while [[ $# -gt 0 ]]; do
        case "$1" in
            --user-data-dir)     _user_data_dir="$2"; shift 2 ;;
            --profile-directory) _profile_dir="$2";   shift 2 ;;
            --keep)              _keep+=("$2");        shift 2 ;;
            --dry-run)           _dry_run=1;           shift   ;;
            -h|--help)           _usage; return 0 ;;
            *) echo "clean_chrome_profile_extensions: argumento desconocido: $1" >&2; return 1 ;;
        esac
    done

    # ── whitelist por defecto ──────────────────────────────────────────────────
    if [[ ${#_keep[@]} -eq 0 ]]; then
        _keep=("$_default_ext")
    fi

    # ── construir paths base ───────────────────────────────────────────────────
    local _profile_path
    _profile_path="${_user_data_dir}/${_profile_dir}"
    local _ext_dir="${_profile_path}/Extensions"

    # ── validaciones ──────────────────────────────────────────────────────────
    if [[ ! -d "$_profile_path" ]]; then
        echo "clean_chrome_profile_extensions: perfil no encontrado: ${_profile_path}" >&2
        return 1
    fi

    if [[ ! -d "$_ext_dir" ]]; then
        echo "clean_chrome_profile_extensions: directorio de extensiones no encontrado: ${_ext_dir}" >&2
        return 3
    fi

    # ── guard: chromium NO debe estar corriendo (excepto en dry-run) ──────────
    if [[ $_dry_run -eq 0 ]]; then
        if pgrep -x chromium >/dev/null 2>&1; then
            echo "clean_chrome_profile_extensions: chromium está corriendo — ciérralo antes de limpiar:" >&2
            echo "  pkill -TERM chromium" >&2
            echo "(Chromium reescribe Preferences desde memoria al cerrar y desharía la purga)" >&2
            return 2
        fi
    fi

    # ── enumerar extensiones instaladas ───────────────────────────────────────
    local _to_remove=()
    local _to_keep=()

    while IFS= read -r -d '' _ext_path; do
        local _ext_id
        _ext_id="$(basename "$_ext_path")"

        # Siempre ignorar la carpeta Temp (usada durante installs en curso)
        if [[ "$_ext_id" == "Temp" ]]; then
            continue
        fi

        # Comprobar si está en la whitelist
        local _in_keep=0
        local _k
        for _k in "${_keep[@]}"; do
            if [[ "$_ext_id" == "$_k" ]]; then
                _in_keep=1
                break
            fi
        done

        if [[ $_in_keep -eq 1 ]]; then
            _to_keep+=("$_ext_id")
        else
            _to_remove+=("$_ext_id")
        fi
    done < <(find "$_ext_dir" -mindepth 1 -maxdepth 1 -type d -print0 | sort -z)

    # ── modo dry-run: solo informar ────────────────────────────────────────────
    if [[ $_dry_run -eq 1 ]]; then
        echo "=== clean_chrome_profile_extensions DRY-RUN ===" >&2
        echo "  Perfil : ${_profile_path}" >&2
        echo "  Conservar (${#_to_keep[@]}): ${_to_keep[*]+"${_to_keep[*]}"}" >&2
        echo "  Borrar  (${#_to_remove[@]}): ${_to_remove[*]+"${_to_remove[*]}"}" >&2
        _emit_json "$_profile_path" _to_keep _to_remove
        return 0
    fi

    # ── borrar extensiones fuera de la whitelist ───────────────────────────────
    if [[ ${#_to_remove[@]} -gt 0 ]]; then
        local _id
        for _id in "${_to_remove[@]}"; do
            rm -rf "${_ext_dir}/${_id}"
        done

        # ── purgar referencias en Preferences y Secure Preferences ────────────
        # Construir lista Python de IDs eliminados
        local _py_ids_list=""
        for _id in "${_to_remove[@]}"; do
            _py_ids_list+="\"${_id}\","
        done
        _py_ids_list="[${_py_ids_list%,}]"

        local _today
        _today="$(date +%Y%m%d)"

        local _prefs_file
        for _prefs_file in "${_profile_path}/Preferences" "${_profile_path}/Secure Preferences"; do
            if [[ ! -f "$_prefs_file" ]]; then
                continue
            fi

            # Backup (no sobreescribir backup del mismo día)
            local _backup="${_prefs_file}.bak.${_today}"
            if [[ ! -f "$_backup" ]]; then
                cp "$_prefs_file" "$_backup"
            fi

            # Editar con python3 si está disponible
            if command -v python3 >/dev/null 2>&1; then
                python3 - "$_prefs_file" "$_py_ids_list" <<'PY' || \
                    echo "clean_chrome_profile_extensions: advertencia — no se pudo purgar ${_prefs_file} con python3" >&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 HMAC table)
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

            # Fallback con jq si python3 no está disponible
            elif command -v jq >/dev/null 2>&1; then
                local _tmp_prefs
                _tmp_prefs="$(mktemp)"
                local _jq_del=""
                for _id in "${_to_remove[@]}"; do
                    _jq_del+=" | del(.extensions.settings[\"${_id}\"])"
                    _jq_del+=" | del(.protection.macs.extensions.settings[\"${_id}\"])"
                done
                # pinned_extensions como lista
                _jq_del+=" | if .extensions.pinned_extensions then .extensions.pinned_extensions -= [$(printf '"%s",' "${_to_remove[@]}" | sed 's/,$//')]  else . end"
                jq "${_jq_del:1}" "$_prefs_file" > "$_tmp_prefs" && mv "$_tmp_prefs" "$_prefs_file" || {
                    echo "clean_chrome_profile_extensions: advertencia — jq falló procesando ${_prefs_file}" >&2
                    rm -f "$_tmp_prefs"
                }
            else
                echo "clean_chrome_profile_extensions: advertencia — ni python3 ni jq disponibles; se borraron las carpetas pero no las referencias en $(basename "$_prefs_file")" >&2
            fi
        done
    fi

    # ── emitir resultado JSON ──────────────────────────────────────────────────
    _emit_json "$_profile_path" _to_keep _to_remove
}

# ── helpers ────────────────────────────────────────────────────────────────────

# _json_array_from_nameref <nameref>
# Convierte un array bash (pasado por nombre de variable) en JSON array de strings.
_json_array_from_nameref() {
    local -n _arr_ref="$1"
    local _out="["
    local _first=1
    local _item
    for _item in "${_arr_ref[@]+"${_arr_ref[@]}"}"; do
        if [[ $_first -eq 1 ]]; then
            _out+="\"${_item}\""
            _first=0
        else
            _out+=",\"${_item}\""
        fi
    done
    _out+="]"
    echo "$_out"
}

# _emit_json <profile_path> <kept_nameref> <removed_nameref>
_emit_json() {
    local _p="$1"
    local _kept_json
    _kept_json="$(_json_array_from_nameref "$2")"
    local _removed_json
    _removed_json="$(_json_array_from_nameref "$3")"
    printf '{"profile":"%s","kept":%s,"removed":%s}\n' \
        "$_p" "$_kept_json" "$_removed_json"
}

# ── auto-ejecución ────────────────────────────────────────────────────────────
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    clean_chrome_profile_extensions "$@"
fi
