from rich.console import Console
import os
import subprocess
import time
import shutil
from pathlib import Path

console = Console()


def safe_run(cmd, **kwargs):
    """Executa um comando e mostra logs legíveis no TUI."""
    console.print(f"[dim]{cmd}[/dim]")
    result = subprocess.run(cmd, shell=True, text=True)
    if result.returncode != 0:
        console.print(f"[red]❌ Erro ao executar:[/red] {cmd}")
        return False
    return True


def run():
    base_dir = Path(__file__).resolve().parents[1]
    nfdos_dir = base_dir / "_nfdos"
    kernel_path = nfdos_dir / "kernel" / "linux" / "arch" / "x86" / "boot" / "bzImage"
    initramfs_path = nfdos_dir / "initramfs.cpio.gz"
    iso_root = nfdos_dir / "iso"
    iso_dir = iso_root / "boot" / "grub"
    iso_output = nfdos_dir / "build" / "nfdos.iso"
    data_disk = nfdos_dir / "nfdos_data.img"

    while True:
        console.clear()
        console.rule("[bold yellow]Gerar Imagem ISO do NFDOS[/bold yellow]")
        console.print("1. Criar ISO bootável (GRUB2 + Kernel + BusyBox)")
        console.print("2. Iniciar NFDOS no QEMU (modo direto - kernel/initramfs)")
        console.print("3. Iniciar NFDOS no QEMU (via ISO real -cdrom)")
        console.print("0. Voltar")

        choice = console.input("\n[cyan]nfdos> [/cyan]")

        # =====================================================
        # 1️⃣ CRIAR ISO
        # =====================================================
        if choice == "1":
            console.print("[cyan]Montando estrutura ISO...[/cyan]")

            if iso_output.exists():
                iso_output.unlink()
            shutil.rmtree(iso_root, ignore_errors=True)
            os.makedirs(iso_dir, exist_ok=True)
            os.makedirs(iso_dir.parent, exist_ok=True)

            # Copiar kernel e initramfs
            safe_run(f"cp {kernel_path} {iso_dir.parent}/bzImage")
            safe_run(f"cp {initramfs_path} {iso_dir.parent}/initramfs.cpio.gz")

            # Criar grub.cfg com kernelopts
            grub_cfg = iso_dir / "grub.cfg"
            grub_cfg.write_text(
                "# NFDOS GRUB2 configuration\n"
                "set timeout=3\n"
                "set default=0\n\n"
                "# Parâmetros padrão do kernel (ajustáveis)\n"
                "set kernelopts=\"console=ttyS0 earlyprintk=serial,ttyS0,115200 keep_bootcon loglevel=8\"\n\n"
                "menuentry 'NFDOS Linux (Serial Console)' {\n"
                "    linux /boot/bzImage root=/dev/ram0 ${kernelopts}\n"
                "    initrd /boot/initramfs.cpio.gz\n"
                "}\n\n"
                "menuentry 'NFDOS Linux (Serial Console + Force Format)' {\n"
                "    linux /boot/bzImage root=/dev/ram0 ${kernelopts} nfdos_force_format=1\n"
                "    initrd /boot/initramfs.cpio.gz\n"
                "}\n\n"
                "menuentry 'NFDOS Linux (Standard VGA)' {\n"
                "    linux /boot/bzImage root=/dev/ram0 quiet ${kernelopts}\n"
                "    initrd /boot/initramfs.cpio.gz\n"
                "}\n"
            )

            # Gerar ISO
            console.print("[yellow]Gerando ISO bootável...[/yellow]")
            safe_run(f"grub-mkrescue -o {iso_output} {iso_root} --compress=xz -V NFDOS")
            console.print(f"[green]✔ ISO criada com sucesso: {iso_output}[/green]")

        # =====================================================
        # 2️⃣ QEMU MODO DIRETO (KERNEL + INITRAMFS)
        # =====================================================
        elif choice == "2":
            console.print("[cyan]Iniciando NFDOS no QEMU (modo direto)...[/cyan]")

            if not kernel_path.exists() or not initramfs_path.exists():
                console.print("[red]❌ Kernel ou initramfs não encontrados. Gere-os primeiro.[/red]")
                time.sleep(2)
                continue

            # Criar disco se não existir
            if not data_disk.exists():
                console.print("[yellow]⚠ Disco de dados não encontrado, criando novo...[/yellow]")
                safe_run(f"qemu-img create -f raw {data_disk} 512M")

            allow_format = console.input("\n[magenta]Permitir formatação automática (y/N)? [/magenta]").lower() == "y"

            kernel_params = (
                "console=ttyS0 earlyprintk=serial,ttyS0,115200 keep_bootcon loglevel=8"
            )
            if allow_format:
                kernel_params += " nfdos_force_format=1"
                console.print("[green]✔ Formatação automática permitida neste boot.[/green]")
            else:
                console.print("[cyan]ℹ Formatação automática desativada (modo seguro).[/cyan]")

            qemu_cmd = (
                f"qemu-system-x86_64 "
                f"-machine q35,accel=kvm "
                f"-cpu host "
                f"-m 1024 "
                f"-kernel {kernel_path} "
                f"-initrd {initramfs_path} "
                f"-append '{kernel_params}' "
                f"-drive file={data_disk},if=virtio,format=raw "
                f"-serial mon:stdio "
                f"-nographic "
                f"-no-reboot"
            )

            console.print(f"[dim]{qemu_cmd}[/dim]")
            safe_run(qemu_cmd)

        # =====================================================
        # 3️⃣ QEMU VIA ISO REAL (-cdrom)
        # =====================================================
        elif choice == "3":
            console.print("[cyan]Iniciando NFDOS no QEMU (via ISO real)...[/cyan]")

            if not iso_output.exists():
                console.print("[red]❌ Nenhuma ISO encontrada. Gere a ISO primeiro (opção 1).[/red]")
                time.sleep(2)
                continue

            if not data_disk.exists():
                console.print("[yellow]⚠ Disco de dados não encontrado, criando novo...[/yellow]")
                safe_run(f"qemu-img create -f raw {data_disk} 512M")

            console.print("[cyan]ℹ Opção de formatação definida pelo menu GRUB interno.[/cyan]")

            qemu_cmd = (
                f"qemu-system-x86_64 "
                f"-machine q35,accel=kvm "
                f"-cpu host "
                f"-m 1024 "
                f"-cdrom {iso_output} "
                f"-drive file={data_disk},if=virtio,format=raw "
                f"-serial mon:stdio "
                f"-nographic "
                f"-no-reboot"
            )

            console.print(f"[dim]{qemu_cmd}[/dim]")
            safe_run(qemu_cmd)

        # =====================================================
        # 0️⃣ SAIR
        # =====================================================
        elif choice == "0":
            break

        else:
            console.print("[red]Opção inválida![/red]")

        time.sleep(1)
