"""
4Alarm - Deployment Routes
Endpoint para automatizar despliegues con build y validación
"""
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel
import subprocess
import os
import json
from pathlib import Path
from typing import Optional

router = APIRouter()

# Configuración de rutas
FRONTEND_PATH = Path(__file__).parent.parent.parent / "frontend"
BUILD_OUTPUT_DIR = "build"  # React usa 'build' por defecto


class DeployRequest(BaseModel):
    """Modelo para solicitud de despliegue"""
    force_rebuild: Optional[bool] = False


def run_command(cmd: str, cwd: str = None) -> dict:
    """
    Ejecuta un comando shell y retorna el resultado
    
    Args:
        cmd: Comando a ejecutar
        cwd: Directorio de trabajo
        
    Returns:
        dict con stdout, stderr y código de retorno
    """
    try:
        result = subprocess.run(
            cmd,
            shell=True,
            cwd=cwd,
            capture_output=True,
            text=True,
            timeout=300  # 5 minutos máximo
        )
        return {
            "stdout": result.stdout,
            "stderr": result.stderr,
            "returncode": result.returncode,
            "success": result.returncode == 0
        }
    except subprocess.TimeoutExpired:
        raise HTTPException(
            status_code=500,
            detail="El proceso de compilación excedió el tiempo límite (5 minutos)"
        )
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail=f"Error ejecutando comando: {str(e)}"
        )


def check_build_exists() -> bool:
    """Verifica si existe la carpeta de build compilada"""
    build_path = FRONTEND_PATH / BUILD_OUTPUT_DIR
    return build_path.exists() and build_path.is_dir()


def validate_build_output() -> bool:
    """
    Valida que la carpeta de build contenga archivos válidos
    
    Returns:
        True si el build es válido, False en caso contrario
    """
    build_path = FRONTEND_PATH / BUILD_OUTPUT_DIR
    
    if not build_path.exists():
        return False
    
    # Verificar que exista index.html
    index_html = build_path / "index.html"
    if not index_html.exists():
        return False
    
    # Verificar que haya archivos estáticos
    static_dir = build_path / "static"
    if static_dir.exists() and static_dir.is_dir():
        # Debe haber al menos algunos archivos JS/CSS
        files = list(static_dir.rglob("*"))
        if len(files) == 0:
            return False
    
    return True


@router.post("/deploy")
async def deploy_frontend(request: DeployRequest = None):
    """
    Endpoint de despliegue automatizado
    
    Ejecuta el ciclo completo:
    1. Git pull (actualizar código)
    2. npm install (instalar/actualizar dependencias)
    3. npm run build (compilar frontend)
    4. Validar que el build sea exitoso
    
    Returns:
        Estado del despliegue con logs detallados
    """
    if request is None:
        request = DeployRequest()
    
    logs = []
    
    # Verificar que existe package.json
    package_json = FRONTEND_PATH / "package.json"
    if not package_json.exists():
        raise HTTPException(
            status_code=500,
            detail=f"No se encontró package.json en {FRONTEND_PATH}"
        )
    
    # Verificar que existe el script de build
    try:
        with open(package_json, 'r') as f:
            pkg_data = json.load(f)
            if "scripts" not in pkg_data or "build" not in pkg_data["scripts"]:
                raise HTTPException(
                    status_code=500,
                    detail="No se encontró el script 'build' en package.json"
                )
    except json.JSONDecodeError:
        raise HTTPException(
            status_code=500,
            detail="Error al leer package.json"
        )
    
    # PASO 1: Git Pull (actualizar repositorio)
    logs.append("=== PASO 1: Actualizando repositorio (git pull) ===")
    git_result = run_command("git pull origin main", cwd=str(FRONTEND_PATH.parent))
    logs.append(f"Git Pull Output:\n{git_result['stdout']}")
    if git_result['stderr']:
        logs.append(f"Git Pull Warnings:\n{git_result['stderr']}")
    
    # PASO 2: Instalar dependencias
    logs.append("\n=== PASO 2: Instalando dependencias (npm install) ===")
    install_result = run_command("npm install", cwd=str(FRONTEND_PATH))
    
    if not install_result['success']:
        logs.append(f"ERROR en npm install:\n{install_result['stderr']}")
        raise HTTPException(
            status_code=500,
            detail={
                "error": "Falló la instalación de dependencias",
                "logs": "\n".join(logs),
                "stderr": install_result['stderr']
            }
        )
    
    logs.append(f"npm install completado exitosamente")
    if install_result['stdout']:
        logs.append(f"Output:\n{install_result['stdout'][:500]}")  # Primeros 500 chars
    
    # PASO 3: Ejecutar build
    logs.append("\n=== PASO 3: Compilando frontend (npm run build) ===")
    build_result = run_command("npm run build", cwd=str(FRONTEND_PATH))
    
    if not build_result['success']:
        logs.append(f"ERROR en npm run build:\n{build_result['stderr']}")
        raise HTTPException(
            status_code=500,
            detail={
                "error": "Falló la compilación del frontend",
                "logs": "\n".join(logs),
                "stderr": build_result['stderr'],
                "stdout": build_result['stdout']
            }
        )
    
    logs.append(f"Build completado exitosamente")
    if build_result['stdout']:
        logs.append(f"Output:\n{build_result['stdout'][-1000:]}")  # Últimos 1000 chars
    
    # PASO 4: Validar que el build sea correcto
    logs.append("\n=== PASO 4: Validando build generado ===")
    if not validate_build_output():
        raise HTTPException(
            status_code=500,
            detail={
                "error": "El build se completó pero la carpeta de salida no es válida",
                "logs": "\n".join(logs),
                "hint": f"Verifica que exista {FRONTEND_PATH / BUILD_OUTPUT_DIR} con index.html"
            }
        )
    
    logs.append(f"✓ Build validado correctamente en {FRONTEND_PATH / BUILD_OUTPUT_DIR}")
    
    return {
        "success": True,
        "message": "Despliegue completado exitosamente",
        "build_path": str(FRONTEND_PATH / BUILD_OUTPUT_DIR),
        "logs": "\n".join(logs)
    }


@router.get("/deploy/status")
async def deployment_status():
    """
    Verifica el estado actual del despliegue
    
    Returns:
        Estado de la carpeta de build y si está lista para servir
    """
    build_exists = check_build_exists()
    build_valid = validate_build_output() if build_exists else False
    
    build_path = FRONTEND_PATH / BUILD_OUTPUT_DIR
    
    status = {
        "build_exists": build_exists,
        "build_valid": build_valid,
        "build_path": str(build_path),
        "ready_to_serve": build_valid
    }
    
    if build_exists:
        # Obtener información adicional
        try:
            index_html = build_path / "index.html"
            if index_html.exists():
                status["index_html_size"] = index_html.stat().st_size
                status["index_html_modified"] = index_html.stat().st_mtime
        except Exception:
            pass
    
    return status


def setup_deploy_routes():
    """Retorna el router configurado"""
    return router
