###############################################################################
# (c) Copyright 2020-2024 CERN for the benefit of the LHCb Collaboration      #
#                                                                             #
# This software is distributed under the terms of the GNU General Public      #
# Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING".   #
#                                                                             #
# In applying this licence, CERN does not waive the privileges and immunities #
# granted to it by virtue of its status as an Intergovernmental Organization  #
# or submit itself to any jurisdiction.                                       #
###############################################################################
"""
Interactive wizard utilities for the experimental CLI.

Provides guided, user-friendly prompts for complex operations.
"""

from pathlib import Path
from typing import List, Optional

from rich.console import Console
from rich.panel import Panel
from rich.prompt import Confirm, IntPrompt, Prompt
from rich.table import Table

console = Console()


def welcome_wizard():
    """Display a welcome message for wizard mode"""
    console.print(
        Panel(
            "[bold cyan]🧙 Welcome to the Interactive Wizard![/bold cyan]\n\n"
            "The wizard will guide you through the process step by step.\n"
            "You can press [bold]Ctrl+C[/bold] at any time to cancel.",
            title="Interactive Mode",
            border_style="cyan",
        )
    )


def select_from_list(
    items: List[str],
    title: str = "Select an option",
    show_indices: bool = True,
) -> Optional[str]:
    """
    Display a list of items and prompt user to select one.

    Args:
        items: List of items to choose from
        title: Title for the selection prompt
        show_indices: Whether to show numeric indices

    Returns:
        Selected item or None if cancelled
    """
    if not items:
        console.print("[yellow]No items available to select[/yellow]")
        return None

    # Display options
    table = Table(title=title, show_header=True, header_style="bold cyan")
    table.add_column("#", style="dim", width=4)
    table.add_column("Option", style="green")

    for idx, item in enumerate(items, 1):
        table.add_row(str(idx), item)

    console.print(table)

    # Prompt for selection
    while True:
        try:
            choice = IntPrompt.ask(
                f"\n[cyan]Enter number (1-{len(items)})[/cyan]",
                default=1,
            )
            if 1 <= choice <= len(items):
                return items[choice - 1]
            console.print(
                f"[red]Please enter a number between 1 and {len(items)}[/red]"
            )
        except KeyboardInterrupt:
            console.print("\n[yellow]Selection cancelled[/yellow]")
            return None


def clone_wizard() -> dict:
    """
    Interactive wizard for cloning AnalysisProductions.

    Returns:
        Dictionary with clone parameters or None if cancelled
    """
    welcome_wizard()

    console.print("\n[bold cyan]Step 1:[/bold cyan] Working Group")
    working_group = Prompt.ask(
        "Enter working group name",
        default="charm",
    )

    console.print("\n[bold cyan]Step 2:[/bold cyan] Production Name")
    production_name = Prompt.ask(
        "Enter production name",
    )

    console.print("\n[bold cyan]Step 3:[/bold cyan] Version")
    console.print("[dim]Tip: Use 'lb-ap-exp versions' to see available versions[/dim]")
    version = Prompt.ask(
        "Enter version tag",
        default="master",
    )

    console.print("\n[bold cyan]Step 4:[/bold cyan] Branch Name")
    branch_name = Prompt.ask(
        "Enter branch name for your work",
        default=f"{production_name}-work",
    )

    console.print("\n[bold cyan]Step 5:[/bold cyan] Clone Protocol")

    # Import auto-detection function
    from .main import get_default_clone_type

    # Auto-detect default
    default_clone_type = get_default_clone_type()

    clone_types = ["ssh", "https", "krb5"]
    default_idx = clone_types.index(default_clone_type.value) + 1

    console.print("\nAvailable protocols:")
    for idx, ct in enumerate(clone_types, 1):
        marker = " (auto-detected)" if idx == default_idx else ""
        console.print(f"  {idx}. {ct}{marker}")

    clone_type_idx = IntPrompt.ask(
        "Select protocol",
        default=default_idx,
        choices=[str(i) for i in range(1, len(clone_types) + 1)],
    )
    clone_type = clone_types[clone_type_idx - 1]

    # Confirmation
    console.print(
        Panel(
            f"[cyan]Working Group:[/cyan] {working_group}\n"
            f"[cyan]Production:[/cyan] {production_name}\n"
            f"[cyan]Version:[/cyan] {version}\n"
            f"[cyan]Branch:[/cyan] {branch_name}\n"
            f"[cyan]Protocol:[/cyan] {clone_type}",
            title="🔍 Review Configuration",
            border_style="yellow",
        )
    )

    if not Confirm.ask("\nProceed with these settings?", default=True):
        console.print("[yellow]Clone cancelled[/yellow]")
        return None

    return {
        "working_group": working_group,
        "production_name": production_name,
        "version": version,
        "branch_name": branch_name,
        "clone_type": clone_type,
    }


def checkout_wizard() -> dict:
    """
    Interactive wizard for checkout command.

    Returns:
        Dictionary with checkout parameters or None if cancelled
    """
    welcome_wizard()

    console.print("\n[bold cyan]Step 1:[/bold cyan] Working Group")
    working_group = Prompt.ask(
        "Enter working group name",
        default="charm",
    )

    console.print("\n[bold cyan]Step 2:[/bold cyan] Production Name")
    production_name = Prompt.ask(
        "Enter production name",
    )

    console.print("\n[bold cyan]Step 3:[/bold cyan] Version")
    version = Prompt.ask(
        "Enter version tag to checkout",
    )

    console.print("\n[bold cyan]Step 4:[/bold cyan] Branch Name")
    branch_name = Prompt.ask(
        "Enter new branch name",
        default=f"{production_name}-{version}",
    )

    console.print("\n[bold cyan]Step 5:[/bold cyan] Deletion Policy")
    allow_deletes = Confirm.ask(
        "Allow deletion of existing production directory?",
        default=False,
    )

    if allow_deletes:
        console.print(
            "[bold yellow]⚠ Warning:[/bold yellow] Existing production directory will be deleted!"
        )
        if not Confirm.ask("Are you sure?", default=False):
            allow_deletes = False

    # Confirmation
    console.print(
        Panel(
            f"[cyan]Working Group:[/cyan] {working_group}\n"
            f"[cyan]Production:[/cyan] {production_name}\n"
            f"[cyan]Version:[/cyan] {version}\n"
            f"[cyan]Branch:[/cyan] {branch_name}\n"
            f"[cyan]Allow Deletes:[/cyan] {allow_deletes}",
            title="🔍 Review Configuration",
            border_style="yellow",
        )
    )

    if not Confirm.ask("\nProceed with checkout?", default=True):
        console.print("[yellow]Checkout cancelled[/yellow]")
        return None

    return {
        "working_group": working_group,
        "production_name": production_name,
        "version": version,
        "branch_name": branch_name,
        "allow_deletes": allow_deletes,
    }


def test_wizard(productions: Optional[List[str]] = None) -> dict:
    """
    Interactive wizard for test command.

    Args:
        productions: Optional list of available productions

    Returns:
        Dictionary with test parameters or None if cancelled
    """
    from LbAPCommon import parse_yaml, render_yaml

    welcome_wizard()

    console.print("\n[bold cyan]Step 1:[/bold cyan] Production Selection")

    if productions and len(productions) > 0:
        production_name = select_from_list(
            productions,
            title="Available Productions",
        )
        if not production_name:
            return None
    else:
        production_name = Prompt.ask("Enter production name")

    console.print("\n[bold cyan]Step 2:[/bold cyan] Job Name")

    # Try to list available jobs from info.yaml
    try:
        info_yaml_path = Path(production_name) / "info.yaml"
        if info_yaml_path.exists():
            with open(info_yaml_path, "rt") as fp:
                raw_yaml = fp.read()
            job_data = parse_yaml(render_yaml(raw_yaml))
            jobs = list(job_data.keys())

            if jobs:
                job_name = select_from_list(
                    jobs,
                    title=f"Available Jobs in {production_name}",
                )
                if not job_name:
                    return None
            else:
                console.print("[yellow]No jobs found in info.yaml[/yellow]")
                job_name = Prompt.ask("Enter job name")
        else:
            console.print(
                "[dim]Tip: Use 'lb-ap-exp list <production>' to see available jobs[/dim]"
            )
            job_name = Prompt.ask("Enter job name")
    except Exception as e:
        console.print(f"[yellow]Could not read jobs from info.yaml: {e}[/yellow]")
        job_name = Prompt.ask("Enter job name")

    console.print("\n[bold cyan]Step 3:[/bold cyan] Test Configuration (Optional)")

    use_custom_input = Confirm.ask(
        "Use custom input file?",
        default=False,
    )

    dependent_input = None
    if use_custom_input:
        dependent_input = Prompt.ask(
            "Enter input file path or LFN",
        )

    # Confirmation
    console.print(
        Panel(
            f"[cyan]Production:[/cyan] {production_name}\n"
            f"[cyan]Job:[/cyan] {job_name}\n"
            f"[cyan]Custom Input:[/cyan] {dependent_input or 'default'}",
            title="🔍 Test Configuration",
            border_style="yellow",
        )
    )

    if not Confirm.ask("\nRun test with these settings?", default=True):
        console.print("[yellow]Test cancelled[/yellow]")
        return None

    return {
        "production_name": production_name,
        "job_name": job_name,
        "dependent_input": dependent_input,
    }


def cwl_generate_wizard(productions: Optional[List[str]] = None) -> dict:
    """
    Interactive wizard for CWL generation.

    Args:
        productions: Optional list of available productions

    Returns:
        Dictionary with generation parameters or None if cancelled
    """
    from LbAPCommon import parse_yaml, render_yaml

    welcome_wizard()

    console.print(
        Panel(
            "[bold yellow]⚠ CWL Generation is Experimental[/bold yellow]\n\n"
            "This wizard will help you convert an AnalysisProductions job\n"
            "into a CWL workflow definition.",
            title="Experimental Feature",
            border_style="yellow",
        )
    )

    console.print("\n[bold cyan]Step 1:[/bold cyan] Production Selection")

    if productions and len(productions) > 0:
        production_name = select_from_list(
            productions,
            title="Available Productions",
        )
        if not production_name:
            return None
    else:
        production_name = Prompt.ask("Enter production name")

    console.print("\n[bold cyan]Step 2:[/bold cyan] Job Name")

    # Try to list available jobs from info.yaml
    try:
        info_yaml_path = Path(production_name) / "info.yaml"
        if info_yaml_path.exists():
            with open(info_yaml_path, "rt") as fp:
                raw_yaml = fp.read()
            job_data = parse_yaml(render_yaml(raw_yaml))
            jobs = list(job_data.keys())

            if jobs:
                job_name = select_from_list(
                    jobs,
                    title=f"Available Jobs in {production_name}",
                )
                if not job_name:
                    return None
            else:
                console.print("[yellow]No jobs found in info.yaml[/yellow]")
                job_name = Prompt.ask("Enter job name to convert")
        else:
            job_name = Prompt.ask("Enter job name to convert")
    except Exception as e:
        console.print(f"[yellow]Could not read jobs from info.yaml: {e}[/yellow]")
        job_name = Prompt.ask("Enter job name to convert")

    console.print("\n[bold cyan]Step 3:[/bold cyan] Output Directory")
    default_output = f"./cwl_generated/{production_name}"
    output_dir = Prompt.ask(
        "Enter output directory",
        default=default_output,
    )

    # Confirmation
    console.print(
        Panel(
            f"[cyan]Production:[/cyan] {production_name}\n"
            f"[cyan]Job:[/cyan] {job_name}\n"
            f"[cyan]Output:[/cyan] {output_dir}",
            title="🔍 Generation Configuration",
            border_style="yellow",
        )
    )

    if not Confirm.ask("\nGenerate CWL with these settings?", default=True):
        console.print("[yellow]Generation cancelled[/yellow]")
        return None

    return {
        "production_name": production_name,
        "job_name": job_name,
        "output_dir": Path(output_dir),
    }
