#!/usr/bin/env bash
# encrypt_file
# ------------
# Cifra o descifra un archivo usando AES-256-CBC con PBKDF2 (310.000 iteraciones).
# La contraseña se lee de la variable de entorno ENCRYPT_PASSWORD o se solicita
# interactivamente por stdin.
#
# USO (directo):
#   encrypt_file encrypt <archivo>
#   encrypt_file decrypt <archivo.enc>
#   ENCRYPT_PASSWORD=secreto encrypt_file encrypt archivo.txt
#
# Depende de: openssl

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/../shell/bash_colors.sh"
source "$SCRIPT_DIR/../shell/bash_log.sh"
bash_colors
bash_log_init

# ─── Funciones puras ──────────────────────────────────────────────────────────

_enc_output_path_encrypt() {
    local input="$1"
    echo "${input}.enc"
}

_enc_output_path_decrypt() {
    local input="$1"
    if [[ "$input" == *.enc ]]; then
        echo "${input%.enc}"
    else
        echo "${input}.dec"
    fi
}

_enc_human_size() {
    local file="$1"
    du -sh "$file" 2>/dev/null | cut -f1
}

# ─── Funciones de efecto ──────────────────────────────────────────name──────────

_enc_ask_password() {
    local pass
    read -rsp "Contraseña: " pass
    echo ""  >&2
    echo "$pass"
}

_enc_ask_password_confirm() {
    local pass1 pass2
    read -rsp "Contraseña: " pass1
    echo "" >&2
    read -rsp "Confirmar contraseña: " pass2
    echo "" >&2

    if [[ "$pass1" != "$pass2" ]]; then
        error "Las contraseñas no coinciden" >&2
        return 1
    fi

    if [[ ${#pass1} -lt 8 ]]; then
        warning "La contraseña es muy corta (mínimo 8 caracteres recomendado)"
    fi

    echo "$pass1"
}

_enc_do_encrypt() {
    local input="$1"
    local output="$2"
    local password="$3"

    openssl enc -aes-256-cbc -pbkdf2 -iter 310000 \
        -in "$input" -out "$output" \
        -pass "pass:${password}" 2>/dev/null
}

_enc_do_decrypt() {
    local input="$1"
    local output="$2"
    local password="$3"

    openssl enc -d -aes-256-cbc -pbkdf2 -iter 310000 \
        -in "$input" -out "$output" \
        -pass "pass:${password}" 2>/dev/null
}

# ─── Punto de entrada ─────────────────────────────────────────────────────────

encrypt_file() {
    local mode="$1"
    local file="$2"

    if [[ -z "$mode" || -z "$file" ]]; then
        error "encrypt_file: uso: encrypt_file <encrypt|decrypt> <archivo>" >&2
        return 1
    fi

    if ! command -v openssl &>/dev/null; then
        error "encrypt_file: 'openssl' no está instalado (sudo apt install openssl)" >&2
        return 1
    fi

    if [[ ! -f "$file" ]]; then
        error "encrypt_file: archivo no encontrado: $file" >&2
        return 1
    fi

    local password
    if [[ -n "${ENCRYPT_PASSWORD:-}" ]]; then
        password="$ENCRYPT_PASSWORD"
    else
        case "$mode" in
            encrypt) password="$(_enc_ask_password_confirm)" || return 1 ;;
            decrypt) password="$(_enc_ask_password)" ;;
            *)
                error "encrypt_file: modo no válido '$mode'. Use: encrypt|decrypt" >&2
                return 1
                ;;
        esac
    fi

    case "$mode" in
        encrypt)
            local output
            output="$(_enc_output_path_encrypt "$file")"
            info "Archivo: ${file} ($(_enc_human_size "$file"))"
            info "Salida:  ${output}"
            info "Cifrando con AES-256-CBC + PBKDF2..."

            if _enc_do_encrypt "$file" "$output" "$password"; then
                success "Archivo cifrado: ${output} ($(_enc_human_size "$output"))"
            else
                error "encrypt_file: el cifrado falló" >&2
                rm -f "$output"
                return 1
            fi
            ;;
        decrypt)
            local output
            output="$(_enc_output_path_decrypt "$file")"
            info "Archivo: ${file} ($(_enc_human_size "$file"))"
            info "Salida:  ${output}"
            info "Descifrando..."

            if _enc_do_decrypt "$file" "$output" "$password"; then
                success "Archivo descifrado: ${output} ($(_enc_human_size "$output"))"
            else
                error "encrypt_file: el descifrado falló -- ¿contraseña incorrecta?" >&2
                rm -f "$output"
                return 1
            fi
            ;;
    esac

    # Limpiar contraseña de memoria
    password=""
}

# Ejecutar si se llama directamente
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    encrypt_file "$@"
fi
