#!/usr/bin/env python3
import os
import sys
import glob
import argparse
import time
from dotenv import dotenv_values

# Add project root to path
sys.path.append(os.getcwd())

# Configuration
CONFIG_PATTERN = ".gemini.*.env"
CURRENT_LINK = ".gemini.current.env"
PROJECT_ROOT = os.getcwd()

def get_available_configs():
    """Return a list of available config files, excluding the current link."""
    files = glob.glob(CONFIG_PATTERN)
    # Remove the link itself from the list
    if CURRENT_LINK in files:
        files.remove(CURRENT_LINK)
    return sorted(files)

def get_current_target():
    """Return the file currently linked to by .gemini.current.env."""
    if os.path.islink(CURRENT_LINK):
        return os.readlink(CURRENT_LINK)
    return None

def switch_config(target_name):
    """Switch the symlink to the target configuration."""
    available = get_available_configs()
    
    # Fuzzy matching logic
    choice = None
    if target_name in available:
        choice = target_name
    else:
        matches = [f for f in available if target_name in f]
        if len(matches) == 1:
            choice = matches[0]
        elif len(matches) > 1:
            print(f"❌ Ambiguous name '{target_name}'. Matches: {', '.join(matches)}")
            return False
            
    if not choice:
        print(f"❌ Configuration '{target_name}' not found.")
        print("Available:", ", ".join(available))
        return False
        
    try:
        if os.path.exists(CURRENT_LINK) or os.path.islink(CURRENT_LINK):
            os.remove(CURRENT_LINK)
            
        os.symlink(choice, CURRENT_LINK)
        print(f"✅ Switched to: {choice}")
        print("ℹ️  Don't forget to restart your bots: python3 scripts/bot_manager.py restart all")
        return True
    except OSError as e:
        print(f"❌ Error switching symlink: {e}")
        return False

def check_single_config(config_file, verbose=False):
    """Check health of a single configuration."""
    # 1. Load config values (without polluting os.environ yet)
    env_vars = dotenv_values(config_file)
    
    # 2. Prepare environment for GeminiLLM
    # We must patch os.environ because GeminiLLM reads from it
    old_env = os.environ.copy()
    os.environ.update(env_vars)
    
    try:
        # Import here to avoid early init issues
        from slack_bot.llm.gemini import GeminiLLM
        
        # Suppress logs unless verbose
        import logging
        if not verbose:
            logging.getLogger("slack_bot.llm.gemini").setLevel(logging.ERROR)
            logging.getLogger("httpx").setLevel(logging.ERROR)
        else:
            logging.getLogger("slack_bot.llm.gemini").setLevel(logging.INFO)
            # Reconfigure stdout logger
            logger = logging.getLogger("slack_bot.llm.gemini")
            handler = logging.StreamHandler(sys.stdout)
            logger.addHandler(handler)
        
        start_time = time.time()
        llm = GeminiLLM()
        model_name = os.environ.get("GEMINI_MODEL", "Unknown")
        
        # Minimal inference
        response, _ = llm.generate_response("ping", [], tools=None)
        
        duration = (time.time() - start_time) * 1000
        
        if verbose:
            print(f"\n[{config_file}] RAW RESPONSE:\n{response}\n" + "-"*30)

        # Loose error detection (covers [Gemini Error], [Error], [Gemini API Error] etc)
        if "Error]" in response or "Error:" in response:
             return False, f"Error: {response[:50]}...", 0, model_name
        
        return True, f"OK ({duration:.0f}ms)", duration, model_name
        
    except Exception as e:
        if verbose:
            print(f"\n[{config_file}] EXCEPTION:\n{e}\n" + "-"*30)
        return False, f"Exception: {str(e)[:50]}...", 0, env_vars.get("GEMINI_MODEL", "Unknown")
    finally:
        # Restore environment
        os.environ.clear()
        os.environ.update(old_env)


def check_health(verbose=False):
    """Iterate and check all configs."""
    configs = get_available_configs()
    current = get_current_target()

    print(f"{'CONFIG':<25} | {'MODEL':<30} | {'STATUS':<10} | {'MESSAGE'}")
    print("-" * 90)

    for cfg in configs:
        is_current = " (current)" if cfg == current else ""
        name_display = cfg + is_current

        # Determine status
        print(f"{name_display:<25} | {'CHECKING..':<30}", end="\r")

        success, msg, _, model = check_single_config(cfg, verbose=verbose)

        status_str = "✅ PASS" if success else "❌ FAIL"
        print(f"{name_display:<25} | {model:<30} | {status_str:<10} | {msg}")


def check_health_detailed():
    """Run comprehensive health check with function calling tests."""
    print("\n🔍 Running comprehensive health check...\n")

    # Import here to avoid circular dependencies
    from slack_bot.llm.gemini import get_system_instruction
    from slack_bot.tools.groups import get_tool_preset
    from openai import OpenAI

    configs = get_available_configs()
    current = get_current_target()

    # Test configuration
    TESTS = [
        {
            "name": "简单对话（无工具）",
            "system": "You are a helpful assistant.",
            "user": "Hello",
            "tools": None,
            "expected": "text"
        },
        {
            "name": "健康查询（无工具）",
            "system": get_system_instruction(),
            "user": "今天睡得怎么样？",
            "tools": None,
            "expected": "text"
        },
        {
            "name": "Function Calling (6工具)",
            "system": get_system_instruction(),
            "user": "今天睡得怎么样？",
            "tools": get_tool_preset("light")[0],
            "expected": "tool_call"
        }
    ]

    for cfg in configs:
        is_current = " ⭐ CURRENT" if cfg == current else ""

        print("=" * 80)
        print(f"📋 Testing: {cfg}{is_current}")
        print("=" * 80)

        # Load config
        env_vars = dotenv_values(cfg)
        base_url = env_vars.get("GEMINI_BASE_URL", "https://generativelanguage.googleapis.com")
        api_key = env_vars.get("GEMINI_API_KEY", "")
        model = env_vars.get("GEMINI_MODEL", "gemini-2.0-flash-exp")

        # Setup client
        headers = {}
        if "openrouter" in base_url:
            headers = {
                "HTTP-Referer": "https://github.com/butler",
                "X-Title": "Butler Health Check"
            }

        client = OpenAI(
            api_key=api_key,
            base_url=f"{base_url}/v1",
            default_headers=headers
        )

        print(f"Model: {model}")
        print(f"Base URL: {base_url}")
        print()

        results = []
        total_time = 0

        for test in TESTS:
            test_name = test["name"]
            print(f"  Running: {test_name}...", end=" ", flush=True)

            try:
                start = time.time()

                kwargs = {
                    "model": model,
                    "messages": [
                        {"role": "system", "content": test["system"]},
                        {"role": "user", "content": test["user"]}
                    ]
                }

                if test["tools"]:
                    kwargs["tools"] = test["tools"]

                response = client.chat.completions.create(**kwargs)
                elapsed = time.time() - start
                total_time += elapsed

                msg = response.choices[0].message
                has_content = bool(msg.content and msg.content.strip())
                has_tools = bool(msg.tool_calls)

                # Evaluate
                if test["expected"] == "tool_call":
                    success = has_tools
                    detail = f"({len(msg.tool_calls)} tools)" if has_tools else "(no tool calls)"
                else:
                    success = has_content
                    detail = f"({len(msg.content)} chars)" if has_content else "(empty)"

                status = "✅" if success else "❌"
                print(f"{status} {detail} [{elapsed:.2f}s]")

                results.append(success)

            except Exception as e:
                print(f"❌ ERROR: {str(e)[:60]}")
                results.append(False)

        # Calculate grade
        success_rate = (sum(results) / len(results)) * 100 if results else 0
        avg_time = total_time / len(results) if results else 0

        if success_rate >= 66:
            grade = "A"
            emoji = "🟢"
        elif success_rate >= 33:
            grade = "C"
            emoji = "🟡"
        else:
            grade = "F"
            emoji = "🔴"

        print()
        print(f"Overall Grade: {emoji} {grade} ({success_rate:.0f}% success, avg {avg_time:.2f}s)")
        print()

    print("=" * 80)
    print("✅ Health check complete!")
    print("=" * 80)

def main():
    parser = argparse.ArgumentParser(description="Switch Gemini Configuration")
    parser.add_argument("config", nargs="?", help="Name of config, 'check' for quick health test, or 'check-detailed' for comprehensive test")
    parser.add_argument("--verbose", "-v", action="store_true", help="Show full debug output for checks")
    args = parser.parse_args()

    if args.config == "check":
        check_health(verbose=args.verbose)
    elif args.config == "check-detailed":
        check_health_detailed()
    elif not args.config:
        # List status
        current = get_current_target()
        available = get_available_configs()
        print(f"Current Configuration: {current if current else 'None'}")
        print("\nAvailable Configurations:")
        for cfg in available:
            prefix = "👉 " if cfg == current else "   "
            simple_name = cfg.replace(".gemini.", "").replace(".env", "")
            print(f"{prefix}{simple_name:<10} ({cfg})")

        print("\nUsage: python3 scripts/select_gemini.py <name> | check [--verbose] | check-detailed")
    else:
        switch_config(args.config)

if __name__ == "__main__":
    main()
