#!/usr/bin/env python
"""
Script para limpiar y reconstruir completamente las tablas Folder, Document y DocumentVersion
a partir de los archivos existentes en media/documents.

Útil después de una pérdida de BD o para sincronizar la BD con el sistema de archivos.

Opciones:
  --user-id ID  : ID del usuario que se asignará como creador (por defecto 1)
  --clean       : Borra todos los registros existentes ANTES de reconstruir
  --noinput     : No pedir confirmación para borrar (usar con --clean)

Ejemplo:
  python rebuild_documents.py --clean --user-id 1
"""

import os
import sys
import django
from pathlib import Path

# Configurar entorno Django
BASE_DIR = Path(__file__).resolve().parent
sys.path.insert(0, str(BASE_DIR))
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
django.setup()

# Importar modelos después de django.setup()
from django.conf import settings
from django.contrib.auth import get_user_model
from documents.models import Folder, Document, DocumentVersion   # Ajusta si tu app se llama distinto

User = get_user_model()

def clean_all():
    """Elimina físicamente todos los registros de Folder, Document y DocumentVersion."""
    print("\n🔥 INICIANDO LIMPIEZA TOTAL 🔥")
    # Borrar en orden para evitar problemas con claves foráneas (aunque CASCADE lo maneja)
    versions_count = DocumentVersion.all_objects.hard_delete()
    docs_count = Document.all_objects.hard_delete()
    folders_count = Folder.all_objects.hard_delete()

    # Los count pueden ser tuplas (total, {model: subtotal})
    def extract_count(c):
        return c[0] if isinstance(c, tuple) else c

    print(f"   - {extract_count(versions_count)} versiones eliminadas")
    print(f"   - {extract_count(docs_count)} documentos eliminados")
    print(f"   - {extract_count(folders_count)} carpetas eliminadas")
    print("✅ Limpieza completada.\n")

def rebuild_from_filesystem(user_id=1):
    """
    Escanea media/documents y crea las instancias de Folder y Document
    que faltan, asignando como creador al usuario con ID dado.
    """
    base_dir = os.path.join(settings.MEDIA_ROOT, 'documents')
    if not os.path.exists(base_dir):
        print(f"❌ El directorio {base_dir} no existe.")
        return

    try:
        user = User.objects.get(pk=user_id)
    except User.DoesNotExist:
        print(f"❌ No se encontró un usuario con ID {user_id}.")
        return

    print(f"🔍 Escaneando {base_dir} ...")
    folder_map = {}  # ruta relativa (con /) → instancia de Folder

    for root, dirs, files in os.walk(base_dir):
        # Ruta relativa desde base_dir (usa siempre /)
        rel_path = os.path.relpath(root, base_dir).replace('\\', '/')
        if rel_path == '.':
            # Directorio raíz 'documents' – no se crea carpeta
            current_folder = None
        else:
            # Crear u obtener la carpeta actual y sus ancestros
            parts = rel_path.split('/')
            parent = None
            cumulative = ''
            for part in parts:
                cumulative = f"{cumulative}/{part}" if cumulative else part
                if cumulative in folder_map:
                    parent = folder_map[cumulative]
                    continue

                # Verificar si ya existe (considerando que no debería, tras limpieza)
                folder, created = Folder.objects.get_or_create(
                    name=part,
                    parent=parent,
                    defaults={
                        'created_by': user,
                        'updated_by': user,
                    }
                )
                if created:
                    print(f"✅ Carpeta creada: {cumulative}")
                else:
                    print(f"⏩ Carpeta ya existía: {cumulative}")

                folder_map[cumulative] = folder
                parent = folder

            current_folder = folder_map[rel_path]

        # Procesar archivos
        for file_name in files:
            file_full_path = os.path.join(root, file_name)
            # Ruta relativa desde MEDIA_ROOT (con /)
            rel_file_path = os.path.relpath(file_full_path, settings.MEDIA_ROOT).replace('\\', '/')

            # Verificar si ya existe
            if Document.objects.filter(file=rel_file_path).exists():
                print(f"⏩ Documento ya existe: {rel_file_path}")
                continue

            # Crear nuevo documento
            doc = Document(
                name=file_name,
                folder=current_folder,
                file=rel_file_path,
                created_by=user,
                updated_by=user,
            )
            doc.save()  # save() calcula file_size y file_type
            print(f"✅ Documento creado: {rel_file_path}")

    print("\n🎉 Reconstrucción completada.")

def main():
    import argparse

    parser = argparse.ArgumentParser(description='Reconstruir carpetas y documentos desde el sistema de archivos.')
    parser.add_argument('--user-id', type=int, default=1, help='ID del usuario creador (por defecto 1)')
    parser.add_argument('--clean', action='store_true', help='Eliminar todos los registros existentes antes de reconstruir')
    parser.add_argument('--noinput', action='store_true', help='No pedir confirmación (usar con --clean)')
    args = parser.parse_args()

    print("=" * 60)
    print("🔄 RECONSTRUCCIÓN DE DOCUMENTOS DESDE SISTEMA DE ARCHIVOS")
    print("=" * 60)

    if args.clean:
        if not args.noinput:
            print("⚠️  Se eliminarán TODOS los registros de carpetas, documentos y versiones.")
            respuesta = input("¿Estás seguro? (escribe 'BORRAR' para confirmar): ")
            if respuesta != 'BORRAR':
                print("Cancelado.")
                return
        clean_all()
    else:
        print("ℹ️  Modo reconstrucción sin limpieza previa. Se crearán solo los elementos faltantes.")

    rebuild_from_filesystem(args.user_id)

    print("=" * 60)

if __name__ == '__main__':
    main()