import argparse
import subprocess
import sys
import shutil
import os
import threading
from pathlib import Path

# Import existing scripts as modules
from django_core_micha.scripts import generate_env, sync_secrets

def run_command(command, cwd=None, ignore_errors=False, shell=False, capture_output=False):
    """Helper function to execute shell commands."""
    if not capture_output:
        print(f"[INFO] Running: {' '.join(command) if isinstance(command, list) else command}")
    
    try:
        is_windows = sys.platform == "win32"
        use_shell = shell or is_windows
        
        if capture_output:
            return subprocess.Popen(command, cwd=cwd, shell=use_shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        
        subprocess.run(command, check=True, cwd=cwd, shell=use_shell)
    except subprocess.CalledProcessError as e:
        if ignore_errors:
            print(f"[WARN] Command failed (ignored): {e}")
        else:
            print(f"[ERROR] Command failed: {e}")
            sys.exit(e.returncode)

def stream_docker_logs(compose_files_args):
    """
    Runs in a separate thread to stream docker logs while frontend is running.
    """
    print("[INFO] Starting Docker Log Stream (Backend & Workers)...")
    cmd = ["docker-compose"] + compose_files_args + ["logs", "-f", "--tail=100", "backend", "celery_worker", "java_backend"]
    
    try:
        subprocess.run(cmd, check=False, shell=(sys.platform == "win32"))
    except Exception as e:
        print(f"[WARN] Log stream interrupted: {e}")

def main():
    parser = argparse.ArgumentParser(description="Developer Runner for Docker setup")
    # Standard Flags
    parser.add_argument("--local", action="store_true", help="Set environment to local (default if not edge)")
    parser.add_argument("--edge", action="store_true", help="Set environment to edge")
    parser.add_argument("--all", action="store_true", help="Sync ALL secrets")
    
    # NEUE STEUERUNG
    parser.add_argument("--env", action="store_true", help="Force regenerate .env file")
    parser.add_argument("--vite", action="store_true", help="Use Hot-Reloading Mode (Vite on Host, Backend in Docker)")
    parser.add_argument("--docker", action="store_true", help="Use Classic Mode (Full Docker Build)")
    parser.add_argument("--refresh", action="store_true", help="Force refresh of Python dependencies (slow!)")

    args = parser.parse_args()

    # --- KONFIGURATION ---
    BASE_DIR = Path(__file__).resolve().parent
    frontend_dir = BASE_DIR / "frontend"
    env_mode = "edge" if args.edge else "local"

    # --- MODUS ENTSCHEIDUNG ---
    # Default ist "Classic Docker", es sei denn --vite ist gesetzt.
    # --docker ist eigentlich redundant, dient aber zur Klarheit.
    MODE = "VITE" if args.vite else "CLASSIC"
    
    # Env Generierung erzwingen?
    FORCE_ENV = args.env

    if args.refresh:
        print("[INFO] 🐢 Dependency Refresh ACTIVE: Downloading latest packages (Slow Build)...")
        os.environ["UV_FLAGS"] = "--refresh"
    else:
        # Sicherstellen, dass sie leer ist, falls sie im System gesetzt wäre
        os.environ["UV_FLAGS"] = ""

    print(f"==================================================")
    print(f"🚀 RUN-DEV | Mode: {MODE} | Env-Regen: {FORCE_ENV}")
    print(f"==================================================")

    # --- SCHRITT 1: ENV GENERATION (Nur wenn --env gesetzt) ---
    if FORCE_ENV:
        sync_local = args.local or args.all
        sync_github = args.all

        if sync_local:
            print("[INFO] Syncing local secrets (.env.local)...")
            sys.argv = ["sync-secrets", "--target", "local"]
            sync_secrets.main()

        if sync_github:
            print("[INFO] Syncing GitHub secrets...")
            sys.argv = ["sync-secrets", "--target", "github"]
            sync_secrets.main()

        print(f"[INFO] Generating .env for environment: {env_mode}...")
        sys.argv = ["generate-env", "--env", env_mode]
        generate_env.main()

        # .env ins Frontend kopieren (nur nötig, wenn sie neu ist)
        frontend_env_path = frontend_dir / ".env"
        if frontend_dir.exists():
            print("[INFO] Copying .env to frontend...")
            shutil.copy(".env", frontend_env_path)
    else:
        print("[INFO] Skipping .env generation (use --env to force)")


    # --- SCHRITT 2: DOCKER COMPOSE DATEIEN WÄHLEN ---
    compose_files_args = ["-f", "docker-compose.yml"]
    
    if args.edge:
        if Path("docker-compose.edge.yml").exists():
            compose_files_args.extend(["-f", "docker-compose.edge.yml"])
    
    elif MODE == "VITE":
        # Im Vite Modus BRAUCHEN wir die .local config für Port-Mapping und Mounts
        if Path("docker-compose.local.yml").exists():
            compose_files_args.extend(["-f", "docker-compose.local.yml"])
        else:
            print("[ERROR] --vite requires docker-compose.local.yml!")
            sys.exit(1)
            
    elif MODE == "CLASSIC":
        # Im Classic Modus nutzen wir override (falls vorhanden), aber NICHT local
        # (da local das Frontend auslagert, was wir im Classic Mode nicht wollen)
        if Path("docker-compose.override.yml").exists():
             compose_files_args.extend(["-f", "docker-compose.override.yml"])

    print(f"[INFO] Using compose files: {' '.join(compose_files_args)}")

    # --- SCHRITT 3: CLEANUP ---
    print("[INFO] Cleaning up conflicting containers...")
    run_command(["docker", "rm", "-f", "traefik"], ignore_errors=True)
    # Wir löschen Backend-Container, um Konflikte zwischen Modi zu vermeiden
    run_command(["docker-compose"] + compose_files_args + ["rm", "-s", "-f", "-v", "backend", "celery_worker"], ignore_errors=True)


    # --- SCHRITT 4: AUSFÜHRUNG JE NACH MODUS ---
    
    if MODE == "CLASSIC":
        # === KLASSISCHER DOCKER BUILD ===
        # Frontend wird IM Container gebaut (Multi-Stage)
        print("[INFO] Starting Classic Docker Build (Frontend inside Docker)...")
        
        run_command(["docker-compose"] + compose_files_args + ["build"])
        
        print("[INFO] Starting Containers (Attached)...")
        # Hier nutzen wir kein Detached (-d), damit wir Logs direkt sehen und mit CTRL+C stoppen können
        # Das entspricht dem "alten" Verhalten
        run_command(["docker-compose"] + compose_files_args + ["up", "--remove-orphans"])

    elif MODE == "VITE":
        # === VITE HOT RELOADING ===
        # 1. Backend Container starten (Detached)
        print("[INFO] Building & Starting Backend Containers...")
        run_command(["docker-compose"] + compose_files_args + ["build"])
        run_command(["docker-compose"] + compose_files_args + ["up", "-d", "--remove-orphans"])
        
        print(f"\n[SUCCESS] Backend is running in background.")
        
        # 2. Frontend & Logs Parallel
        if frontend_dir.exists():
            print("\n[INFO] Starting Vite Server + Backend Logs...")
            print("[INFO] Press CTRL+C to stop all.")
            
            # Thread für Backend Logs
            log_thread = threading.Thread(target=stream_docker_logs, args=(compose_files_args,), daemon=True)
            log_thread.start()

            # Main Process: Vite
            try:
                # Wir erzwingen hier die direkte Verbindung zum Terminal-Input/Output
                pnpm_cmd = "pnpm install && pnpm dev"
                print(f"[INFO] Executing in {frontend_dir}: {pnpm_cmd}")
                
                # Nutze shell=True und stelle sicher, dass wir im richtigen Verzeichnis sind
                subprocess.run(
                    pnpm_cmd, 
                    cwd=str(frontend_dir), 
                    shell=True, 
                    check=True,
                    capture_output=False # Wichtig: Nicht abfangen, direkt ausgeben!
                )
            except KeyboardInterrupt:
                print("\n[INFO] Stopping...")
                # Optional: Container beim Beenden stoppen
                # run_command(["docker-compose"] + compose_files_args + ["stop"])
            except subprocess.CalledProcessError as e:
                print(f"[ERROR] Frontend process failed: {e}")
        else:
             print("[WARN] No frontend directory found! Streaming logs only.")
             run_command(["docker-compose"] + compose_files_args + ["logs", "-f"])

if __name__ == "__main__":
    main()