# SPDX-License-Identifier: MIT
"""
Generate a functional boilerplate EZGA Python script for quick starting.
"""
from pathlib import Path
import typer
from rich.console import Console
from rich.panel import Panel

console = Console()

BASIC_BOILERPLATE = '''# experiment.py
"""
Auto-generated EZGA Example Script using the QuickGA interface.
"""
from ezga import QuickGA

# 1. Define your system
composition = ["Ni", "O"]

if __name__ == "__main__":
    # 2. Configure and Run
    ga = QuickGA(
        composition=composition,
        calculator="lj",        # Fast LJ potential for testing
        max_generations=50,
    )
    
    print(f"Starting EZGA for system: {composition}")
    ga.run()
'''

ADVANCED_BOILERPLATE = '''# advanced_experiment.py
"""
Advanced EZGA Recipe.
Scaffolded via 'ezga init --advanced'.

This script demonstrates the explicit Core API usage, allowing granular 
control over every stage of the evolutionary search.
"""

import numpy as np
from ezga.factory import load_config, build_default_engine
from ezga.cli.run import _print_summary
from ezga.evaluator.features import feature_composition_vector
from ezga.evaluator.objective import objective_energy
from ezga.variation.presets import grand_canonical
from ezga.DoE.constraint import ConstraintFactory

# --- (1) System Definition --------------------------------------------------
composition = ["Ni", "O"]

# --- (2) Composition Constraints --------------------------------------------
# Limit the total number of atoms in the system
constraints = [
    ConstraintFactory.sum_in_range(composition, 2, 40)
]

# --- (3) Variation Operators (Mutations & Crossover) ------------------------
# grand_canonical provides a balanced bundle (Rattle, Swap, Add, Remove, etc.)
mutations = grand_canonical(
    species=composition,
    rattle_std=0.05,
    collision_tolerance=1.8
)

# --- (4) Evaluator (Features & Objectives) ----------------------------------
features   = feature_composition_vector(composition)
objectives = [ objective_energy() ]

# --- (5) Simulator (Calculator) ---------------------------------------------
# You can use shorthand strings ('lj', 'emt', 'mace') or pass a custom object.
calculator = "lj"

# --- (6) Configuration Dictionary (Standard Schema) -------------------------
cfg_dict = {
    "output_path": "runs/advanced_run",
    "max_generations": 100,
    
    "population": {
        "dataset_path": "config.xyz",
        "filter_duplicates": True,
        "constraints": constraints,
    },
    
    "multiobjective": {
        "size": 20,
    },
    
    "evaluator": {
        "features_funcs": features,
        "objectives_funcs": objectives
    },
    
    "mutation_funcs": mutations,
    
    "simulator": {
        "mode": "sampling",
        "calculator": calculator
    },
    
    "agentic": {
        "strategy": "balanced"
    }
}

if __name__ == "__main__":
    # 1. Load and Validate Configuration
    config = load_config(cfg_dict)
    
    # 2. Print Summary for the User
    _print_summary(config)
    
    # 3. Build and Run the Engine
    print(f"\\nBuilding EZGA Engine for: {composition}")
    engine = build_default_engine(config)
    
    # Execute the GA Loop
    final_dataset = engine.run()
    print("\\nDone! Results saved to 'runs/advanced_run'.")
'''

def init_cli(
    output: Path = typer.Argument(Path("experiment.py"), help="Name of the generated python script"),
    advanced: bool = typer.Option(False, "--advanced", "-a", help="Generate an advanced boilerplate (explicit config)"),
    force: bool = typer.Option(False, "--force", "-f", help="Overwrite the file if it already exists")
) -> None:
    """
    Scaffold a ready-to-use EZGA experiment script.
    
    Creates a functional Python script. By default, it uses the QuickGA facade.
    Use --advanced to see the full configuration schema and core engine wiring.
    """
    if output.exists() and not force:
        console.print(f"[bold red]Error:[/] File '{output}' already exists. Use --force to overwrite.")
        raise typer.Exit(1)
        
    code = ADVANCED_BOILERPLATE if advanced else BASIC_BOILERPLATE
    output.write_text(code)
    
    type_str = "Advanced (Core API)" if advanced else "Basic (QuickGA)"
    msg = f"""[bold green]Success![/] Scaffolded [bold]{type_str}[/] experiment at [bold]{output}[/].
    
[bold cyan]Next Steps:[/bold cyan]
1. Open [bold]{output}[/] to inspect/edit the parameters.
2. Run it with: [bold]python {output}[/]"""
    console.print(Panel(msg, border_style="green"))
