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...")
    # Only show backend & celery logs
    cmd = ["docker-compose"] + compose_files_args + ["logs", "-f", "--tail=10", "backend", "celery_worker"]
    
    try:
        # Explicitly piping stdout/stderr to the current process's streams
        subprocess.run(
            cmd, 
            check=False, 
            shell=(sys.platform == "win32"),
            stdout=sys.stdout,
            stderr=sys.stderr
        )
    except Exception as e:
        print(f"[WARN] Log stream interrupted: {e}")

def main():
    parser = argparse.ArgumentParser(description="Developer Runner for Docker setup")
    parser.add_argument("--edge", action="store_true", help="Set environment to edge")
    env_group = parser.add_mutually_exclusive_group()
    env_group.add_argument("--env", action="store_true", help="Generate local .env file")
    env_group.add_argument("--env-all", action="store_true", help="Generate local .env and sync GitHub secrets")
    parser.add_argument("--vite", action="store_true", help="Use Hot-Reloading Mode (Vite on Host)")
    parser.add_argument("--refresh", action="store_true", help="Force refresh of Python dependencies")

    args = parser.parse_args()

    # --- KONFIGURATION (FIX) ---
    # Wir nutzen das aktuelle Arbeitsverzeichnis (wo du den Befehl ausführst),
    # nicht den Speicherort des Skripts.
    BASE_DIR = Path.cwd()
    frontend_dir = BASE_DIR / "frontend"
    
    env_mode = "edge" if args.edge else "local"
    MODE = "VITE" if args.vite else "CLASSIC"
    FORCE_ENV = args.env or args.env_all

    if args.refresh:
        print("[INFO] 🐢 Dependency Refresh ACTIVE: Downloading latest packages...")
        os.environ["UV_FLAGS"] = "--refresh"
    else:
        os.environ["UV_FLAGS"] = ""

    print(f"==================================================")
    print(f"🚀 RUN-DEV | Mode: {MODE} | Env-Regen: {FORCE_ENV}")
    print(f"==================================================")
    # DEBUG OUTPUT: Damit wir sehen, wo er sucht
    print(f"[DEBUG] Searching for frontend in: {frontend_dir}")

    # --- SCHRITT 1: ENV GENERATION ---
    if FORCE_ENV:
        print(f"[INFO] Generating .env for {env_mode}...")
        sys.argv = ["generate-env", "--env", env_mode]
        generate_env.main()

        frontend_env_path = frontend_dir / ".env"
        if frontend_dir.exists():
            shutil.copy(".env", frontend_env_path)
        
        if args.env_all:
            print("[INFO] Syncing GitHub secrets...")
            sys.argv = ["sync-secrets", "--target", "github"]
            sync_secrets.main()
    else:
        print("[INFO] Skipping .env generation (use --env or --env-all to force)")


    # --- SCHRITT 2: DOCKER FILES ---
    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":
        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":
        # New default: prefer local compose even in CLASSIC mode.
        # This keeps local mount protections (templates/static) consistent.
        if Path("docker-compose.local.yml").exists():
            compose_files_args.extend(["-f", "docker-compose.local.yml"])
        elif Path("docker-compose.override.yml").exists():
            print("[WARN] docker-compose.local.yml not found, falling back to docker-compose.override.yml")
            compose_files_args.extend(["-f", "docker-compose.override.yml"])

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

    # --- SCHRITT 3: CLEANUP ---
    print("[INFO] Stopping containers...")
    run_command(["docker", "rm", "-f", "traefik"], ignore_errors=True)
    subprocess.run(
        ["docker", "rm", "-f", "traefik"], 
        stderr=subprocess.DEVNULL, 
        stdout=subprocess.DEVNULL, 
        shell=(sys.platform=="win32")
    )


    # --- SCHRITT 4: START ---
    # Always renew anonymous volumes to avoid stale frontend static/templates artifacts.
    up_flags = ["-d", "--remove-orphans", "--renew-anon-volumes"]
    
    if MODE == "CLASSIC":
        print("[INFO] Starting Classic Docker Build...")
        run_command(["docker-compose"] + compose_files_args + ["build"])
        
        print("[INFO] Starting Containers (Detached)...")
        # 1. Alles im Hintergrund starten (damit Java uns nicht vollquatscht)
        run_command(["docker-compose"] + compose_files_args + ["up"] + up_flags)
        
        print("[INFO] Streaming logs for backend & celery_worker (Ctrl+C to stop)...")
        try:
            # 2. Nur RELEVANTE Logs anzeigen (Main Thread blockiert hier)
            # Das ist der gleiche Filter wie im Vite-Modus
            cmd = ["docker-compose"] + compose_files_args + ["logs", "-f", "backend", "celery_worker"]
            subprocess.run(cmd, check=True, shell=(sys.platform=="win32"))
        except KeyboardInterrupt:
            print("\n[INFO] Stopping containers...")
            # 3. Aufräumen: Wenn du CTRL+C drückst, stoppen wir alles (wie beim normalen 'up')
            run_command(["docker-compose"] + compose_files_args + ["stop"])

    elif MODE == "VITE":
        # 1. Backend starten
        print("[INFO] Starting Backend Containers...")
        run_command(["docker-compose"] + compose_files_args + ["up", "--build"] + up_flags)
        
        # 2. Frontend
        if frontend_dir.exists():
            print("\n[INFO] Starting Vite...")
            
            log_thread = threading.Thread(target=stream_docker_logs, args=(compose_files_args,), daemon=True)
            log_thread.start()

            try:
                # Node Modules Check
                node_modules = frontend_dir / "node_modules"
                if not node_modules.exists():
                     print("[INFO] node_modules not found. Running pnpm install...")
                     subprocess.run("pnpm install", cwd=str(frontend_dir), shell=True, check=True)
                
                # Vite Start
                print(f"[INFO] Executing 'pnpm dev' in {frontend_dir}...")
                subprocess.run("pnpm dev", cwd=str(frontend_dir), shell=True, check=True)
                
            except KeyboardInterrupt:
                print("\n[INFO] Stopping...")
            except subprocess.CalledProcessError as e:
                print(f"[ERROR] Frontend process failed: {e}")
        else:
             print(f"[WARN] No frontend directory found at {frontend_dir}!")
             run_command(["docker-compose"] + compose_files_args + ["logs", "-f", "backend", "celery_worker"])

if __name__ == "__main__":
    main()
