

from __future__ import annotations

import os
import sys
from enum import Enum


class Color(str, Enum):
    RESET = "\033[0m"
    BOLD = "\033[1m"
    GREEN = "\033[92m"
    YELLOW = "\033[93m"
    BLUE = "\033[94m"
    CYAN = "\033[96m"


def print_banner() -> None:
    banner = f"""{Color.CYAN}
╔═══════════════════════════════════════════╗
║   LLM Provider Selector                   ║
║   Provider-agnostic AI interactions       ║
╚═══════════════════════════════════════════╝{Color.RESET}"""
    print(banner)


def print_providers(providers: list[tuple[str, str]]) -> None:
    print(f"\n{Color.BOLD}Available Providers:{Color.RESET}\n")
    for i, (name, desc) in enumerate(providers, 1):
        print(f"  {Color.GREEN}{i}{Color.RESET}. {Color.BOLD}{name}{Color.RESET} - {desc}")


def select_provider(providers: list[tuple[str, str]]) -> str | None:
    if not providers:
        print("No providers available.")
        return None

    print_providers(providers)

    while True:
        try:
            choice = input(f"\n{Color.YELLOW}Select provider (1-{len(providers)}): {Color.RESET}").strip()
            if not choice:
                return None
            idx = int(choice) - 1
            if 0 <= idx < len(providers):
                return providers[idx][0]
            print(f"{Color.YELLOW}Invalid selection. Try again.{Color.RESET}")
        except ValueError:
            print(f"{Color.YELLOW}Please enter a number.{Color.RESET}")


def select_model(models: list[tuple[str, str]]) -> str | None:
    if not models:
        print("No models available.")
        return None

    print(f"\n{Color.BOLD}Available Models:{Color.RESET}\n")
    for i, (name, desc) in enumerate(models, 1):
        print(f"  {Color.GREEN}{i}{Color.RESET}. {Color.BOLD}{name}{Color.RESET} - {desc}")

    while True:
        try:
            choice = input(f"\n{Color.YELLOW}Select model (1-{len(models)}): {Color.RESET}").strip()
            if not choice:
                return None
            idx = int(choice) - 1
            if 0 <= idx < len(models):
                return models[idx][0]
            print(f"{Color.YELLOW}Invalid selection. Try again.{Color.RESET}")
        except ValueError:
            print(f"{Color.YELLOW}Please enter a number.{Color.RESET}")


def save_config(provider: str, model: str, persist: bool = False) -> None:
    config = f"LLM_PROVIDER={provider}\nLLM_MODEL={model}\n"
    env_file = ".llm.env"

    with open(env_file, "w") as f:
        f.write(config)

    print(f"\n{Color.GREEN}✓{Color.RESET} Config saved to {Color.CYAN}{env_file}{Color.RESET}")

    if persist:
        os.environ["LLM_PROVIDER"] = provider
        os.environ["LLM_MODEL"] = model
        print(f"{Color.GREEN}✓{Color.RESET} Config loaded to current session")


def interactive_select(
    providers: list[tuple[str, str]] | None = None,
    models_per_provider: dict[str, list[tuple[str, str]]] | None = None,
    persist: bool = False,
) -> tuple[str, str] | None:
    print_banner()

    if providers is None:
        providers = [
            ("claude", "Anthropic Claude ( Sonnet, Opus, Haiku)"),
            ("openai", "OpenAI GPT (4o, 4o-mini, 3.5-turbo)"),
            ("ollama", "Local Ollama models"),
        ]

    if models_per_provider is None:
        models_per_provider = {
            "claude": [
                ("claude-opus-4-5", "Claude Opus 4.5 - Most capable"),
                ("claude-sonnet-4-7", "Claude Sonnet 4.7 - Balanced"),
                ("claude-haiku-4-7", "Claude Haiku 4.7 - Fast"),
            ],
            "openai": [
                ("gpt-4o", "GPT-4o - Most capable"),
                ("gpt-4o-mini", "GPT-4o-mini - Fast & affordable"),
                ("gpt-4-turbo", "GPT-4 Turbo - Legacy powerful"),
                ("gpt-3.5-turbo", "GPT-3.5 - Legacy fast"),
            ],
            "ollama": [
                ("llama3.2", "Llama 3.2 - General purpose"),
                ("mistral", "Mistral - Fast & efficient"),
                ("codellama", "CodeLlama - Code specialized"),
            ],
        }

    provider = select_provider(providers)
    if not provider:
        return None

    models = models_per_provider.get(provider, [])
    model = select_model(models)
    if not model:
        return None

    print(f"\n{Color.GREEN}Selected: {Color.BOLD}{provider}{Color.RESET} / {Color.BOLD}{model}{Color.RESET}")

    save_config(provider, model, persist)

    return (provider, model)


def main() -> None:
    result = interactive_select(persist=True)

    if result:
        print(f"\n{Color.GREEN}Ready to use!{Color.RESET}")
        print(f"  export LLM_PROVIDER={result[0]}")
        print(f"  export LLM_MODEL={result[1]}")
    else:
        print("\nSelection cancelled.")
        sys.exit(0)


if __name__ == "__main__":
    main()
