"""Pipeline: arregla permisos de SQLite en el contenedor Metabase.

Compone: metabase_auth + metabase_list_databases (para verificar).

SQLite necesita escribir journal/WAL files en el mismo directorio que la BD.
El contenedor Metabase corre Java como UID 2000 (usuario metabase).
Si los directorios o archivos no son escribibles por ese UID, Metabase
devuelve SQLITE_READONLY_DIRECTORY.

Este pipeline:
1. Detecta el contenedor Metabase
2. Encuentra todos los directorios /data/ que contienen .db
3. Hace chmod 777 en directorios y chmod 666 en archivos .db
4. Verifica que Metabase puede leer cada database

Uso:
    python metabase_fix_permissions.py
    python metabase_fix_permissions.py --container fn_registry-metabase
"""

import argparse
import os
import subprocess
import sys

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

from metabase.client import metabase_auth
from metabase import metabase_list_databases

METABASE_URL = os.environ.get("METABASE_URL", "http://localhost:3000")
EMAIL = os.environ.get("METABASE_ADMIN_EMAIL", "admin@fnregistry.local")
PASSWORD = os.environ.get("METABASE_ADMIN_PASSWORD", "FnRegistry2024!")
DEFAULT_CONTAINER = "fn_registry-metabase"


def docker_exec(container: str, cmd: list[str], user: str = "root") -> str:
    """Ejecuta comando dentro del contenedor."""
    result = subprocess.run(
        ["docker", "exec", "-u", user, container] + cmd,
        capture_output=True, text=True,
    )
    return result.stdout.strip()


def fix_container_permissions(container: str) -> list[str]:
    """Arregla permisos de todos los .db en /data/ del contenedor.

    Returns:
        Lista de paths arreglados.
    """
    # Encontrar todos los .db bajo /data/
    find_output = docker_exec(container, ["find", "/data", "-name", "*.db", "-type", "f"])
    if not find_output:
        print("  No se encontraron archivos .db en /data/")
        return []

    db_files = [f.strip() for f in find_output.splitlines() if f.strip()]
    fixed = []

    for db_path in db_files:
        db_dir = os.path.dirname(db_path)

        # Fix directorio: 777 para que UID 2000 pueda crear journal
        docker_exec(container, ["chmod", "777", db_dir])

        # Fix archivo: 666 para que UID 2000 pueda leer/escribir
        docker_exec(container, ["chmod", "666", db_path])

        # Fix WAL/SHM si existen
        for suffix in ["-wal", "-shm", "-journal"]:
            wal_path = db_path + suffix
            docker_exec(container, ["chmod", "666", wal_path])

        fixed.append(db_path)
        print(f"  Fixed: {db_path} (dir: {db_dir})")

    return fixed


def verify_databases(client) -> bool:
    """Verifica que todas las databases SQLite responden."""
    import httpx

    dbs = metabase_list_databases(client)
    all_ok = True

    for db in dbs:
        if db.get("engine") != "sqlite":
            continue

        name = db["name"]
        db_id = db["id"]

        try:
            resp = client._http.request("POST", "/api/dataset", json={
                "database": db_id,
                "type": "native",
                "native": {"query": "SELECT 1"},
            }, extensions={"timeout": {"read": 60, "write": 10, "connect": 10, "pool": 10}})

            if resp.status_code in (200, 202):
                print(f"  OK: {name} (id={db_id})")
            else:
                error = resp.text[:150]
                print(f"  FAIL: {name} (id={db_id}) -> {error}")
                all_ok = False
        except httpx.ReadTimeout:
            print(f"  TIMEOUT: {name} (id={db_id}) -> Metabase aun sincronizando, reintentar en unos segundos")
            all_ok = False

    return all_ok


def main():
    parser = argparse.ArgumentParser(description="Arregla permisos SQLite en contenedor Metabase")
    parser.add_argument("--container", default=DEFAULT_CONTAINER, help="Nombre del contenedor Metabase")
    args = parser.parse_args()

    container = args.container

    # Verificar que el contenedor existe
    result = subprocess.run(
        ["docker", "inspect", container, "--format", "{{.State.Running}}"],
        capture_output=True, text=True,
    )
    if result.returncode != 0 or result.stdout.strip() != "true":
        print(f"ERROR: Contenedor '{container}' no esta corriendo.")
        sys.exit(1)

    print(f"Contenedor: {container}")
    print(f"\n1. Arreglando permisos en /data/...")
    fixed = fix_container_permissions(container)

    if not fixed:
        print("  Nada que arreglar.")
        return

    print(f"\n2. Verificando databases en Metabase...")
    client = metabase_auth(METABASE_URL, EMAIL, PASSWORD)
    ok = verify_databases(client)
    client.close()

    if ok:
        print(f"\nTodas las databases responden correctamente.")
    else:
        print(f"\nAlgunas databases siguen fallando. Revisar logs del contenedor:")
        print(f"  docker logs {container} --tail 50")


if __name__ == "__main__":
    main()
