#!/usr/bin/python3
import subprocess
import os
from datetime import datetime
import shutil
import sys

SWAPFILE = "/swapfile"


def run(cmd, check=True):
    """Helper para ejecutar comandos de sistema."""
    return subprocess.run(cmd, check=check)


def print_header(msg: str):
    now = datetime.now().strftime("%a %b %d %I:%M:%S %p %Z %Y")
    print(f"[{now}] {msg}")


def show_memory_state(label: str):
    print(f"\n📊 Estado {label} de la limpieza:")
    run(["free", "-m"], check=False)


def cleanup_caches():
    print("\n🧠 Limpiando caché de página, dentries e inodes...")
    # Equivalente a: sync; echo 3 > /proc/sys/vm/drop_caches
    run(["sync"], check=False)

    try:
        with open("/proc/sys/vm/drop_caches", "w") as f:
            f.write("3\n")
    except PermissionError:
        print("⚠️ No se pudo escribir en /proc/sys/vm/drop_caches (requiere root).")
    except Exception as e:
        print(f"⚠️ Error al limpiar cachés: {e}")


def cleanup_swap(swap_path: str = SWAPFILE):
    if not os.path.exists(swap_path):
        print(f"\n⚠️ {swap_path} no encontrado. No se limpiará swap.")
        return

    # Verificar que el comando swapoff/swapon existe
    if shutil.which("swapoff") is None or shutil.which("swapon") is None:
        print("\n⚠️ No se encontraron los comandos swapoff/swapon en el sistema.")
        return

    # Verificar si el swap está activo
    try:
        result = subprocess.run(
            ["swapon", "--show"],
            capture_output=True,
            text=True,
            check=False
        )
        if swap_path not in result.stdout:
            print(f"\n⚠️ {swap_path} no está activo como swap. No se limpiará swap.")
            return
    except Exception as e:
        print(f"\n⚠️ No se pudo comprobar el estado del swap: {e}")
        return

    print("\n♻️  Limpiando swap...")
    try:
        run(["swapoff", swap_path])
        run(["swapon", swap_path])
    except PermissionError:
        print("⚠️ No se pudo ejecutar swapoff/swapon (requiere root).")
    except subprocess.CalledProcessError as e:
        print(f"⚠️ Error al limpiar swap ({swap_path}): {e}")


def main():
    print_header("🧹 Iniciando limpieza de memoria post-mercado...")

    show_memory_state("ANTES")

    cleanup_caches()
    cleanup_swap(SWAPFILE)

    show_memory_state("DESPUÉS")

    print_header("✅ Limpieza completada.")


if __name__ == "__main__":
    # Opcional: aviso si no se corre como root (para que no te olvides)
    if os.geteuid() != 0:
        print("⚠️ Aviso: lo ideal es ejecutar este script como root para limpiar cachés y swap.")
    main()
