"""bilge explain - Explain configuration decisions."""

import json
from pathlib import Path

from rich.console import Console

from bilgeai.analyzer.models import DatasetProfile
from bilgeai.core.constants import PROJECT_DIR
from bilgeai.optimizer.engine import GuardrailEngine
from bilgeai.optimizer.explainer import explain_config
from bilgeai.optimizer.models import TrainingConfig
from bilgeai.profiler.models import HardwareProfile

console = Console()


def explain_command() -> None:
    """Explain every configuration decision."""
    # Load hardware profile (needed for VRAM estimate in both paths)
    hw_path = Path.cwd() / PROJECT_DIR / "hardware_profile.json"
    if not hw_path.exists():
        console.print("[yellow]No hardware profile found. Running profiler...[/yellow]\n")
        from bilgeai.profiler import get_hardware_profile

        hw = get_hardware_profile()
    else:
        hw = HardwareProfile.model_validate(json.loads(hw_path.read_text(encoding="utf-8")))

    # Check for saved training config from 'bilge run'
    saved_config_path = Path.cwd() / PROJECT_DIR / "training_config.json"
    if saved_config_path.exists():
        training_config = TrainingConfig.model_validate(
            json.loads(saved_config_path.read_text(encoding="utf-8"))
        )
        explain_config(training_config, console)
    else:
        # Fallback: guardrail-only mode
        # Load dataset profile
        ds_path = Path.cwd() / PROJECT_DIR / "dataset_profile.json"
        if not ds_path.exists():
            console.print(
                "[yellow]No dataset profile found. "
                "Run 'bilge analyze' first for data-aware decisions.[/yellow]\n"
            )
            ds = DatasetProfile(path="unknown", format="unknown", num_rows=1000)
        else:
            ds = DatasetProfile.model_validate(json.loads(ds_path.read_text(encoding="utf-8")))

        # Load user overrides
        try:
            from bilgeai.core.config import BilgeConfig

            config = BilgeConfig.load()
            model_name = config.model.name
        except Exception:
            model_name = "meta-llama/Llama-3-8B"

        # Run guardrail engine to get hardware constraints and explanations
        engine = GuardrailEngine()
        constraints = engine.compute_constraints(hw, ds, model_name=model_name)

        # Build a TrainingConfig with guardrail explanations for display
        training_config = TrainingConfig(
            model_name=model_name,
            batch_size=constraints.max_batch_size,
            quantization=constraints.required_quantization,
            max_seq_length=constraints.max_seq_length_safe,
            distributed_strategy=constraints.distributed_strategy,
            num_gpus=constraints.num_gpus,
            use_gradient_checkpointing=constraints.gradient_checkpointing_required,
            explanations=constraints.explanations,
        )

        explain_config(training_config, console)
        console.print(
            "\n[dim]Note: Showing guardrail rules only. "
            "Run 'bilge run' for full LLM-optimized explanations.[/dim]"
        )

    # Show VRAM estimate if GPU available
    if hw.gpus:
        from bilgeai.validation.vram_estimator import estimate_vram

        vram = hw.gpus[0].vram_gb
        estimate = estimate_vram(training_config, vram)
        console.print("\n[bold]VRAM Estimate:[/bold]")
        console.print(f"  Model weights: {estimate.model_weights_gb:.1f} GB")
        console.print(f"  Activations:   {estimate.activations_gb:.1f} GB")
        console.print(f"  Optimizer:     {estimate.optimizer_states_gb:.1f} GB")
        console.print(f"  [bold]Total:       {estimate.total_gb:.1f} / {vram:.0f} GB[/bold]")
        if estimate.fits_in_vram:
            console.print("  [green]Fits in VRAM[/green]")
        else:
            console.print(
                "  [red]May exceed VRAM! Consider reducing batch_size or using 4bit.[/red]"
            )

    from bilgeai.cli.hints import show_next_hint

    show_next_hint("explain", console)
