"""
Predix Prompt Loader

Loads prompts from:
1. prompts/local/*.yaml (your improved prompts - not in Git)
2. prompts/standard_prompts.yaml (default prompts - in Git)

Usage:
    from rdagent.components.prompt_loader import load_prompt
    
    # Load factor discovery prompt
    prompt = load_prompt("factor_discovery")
    
    # Load with custom local prompt
    prompt = load_prompt("factor_discovery", local_only=True)
"""

import os
import yaml
from pathlib import Path
from typing import Optional, Dict, Any


# Base paths
BASE_DIR = Path(__file__).parent.parent.parent  # Predix/
PROMPTS_DIR = BASE_DIR / "prompts"
LOCAL_PROMPTS_DIR = PROMPTS_DIR / "local"
STANDARD_PROMPTS_FILE = PROMPTS_DIR / "standard_prompts.yaml"


def get_local_prompt_path(name: str) -> Optional[Path]:
    """Find local prompt file by name.
    
    Priority:
    1. {name}_v2.yaml (latest version)
    2. {name}_v1.yaml
    3. {name}.yaml
    """
    if not LOCAL_PROMPTS_DIR.exists():
        return None
    
    # Try versioned files first (v4, v3, v2, v1, etc.)
    for version in ["v4", "v3", "v2", "v1"]:
        for ext in ["yaml", "yml"]:
            path = LOCAL_PROMPTS_DIR / f"{name}_{version}.{ext}"
            if path.exists():
                print(f"  (found versioned: {name}_{version}.{ext})")
                return path
    
    # Try exact name
    for ext in ["yaml", "yml"]:
        path = LOCAL_PROMPTS_DIR / f"{name}.{ext}"
        if path.exists():
            return path
    
    # Try subdirectories
    for subdir in LOCAL_PROMPTS_DIR.iterdir():
        if subdir.is_dir():
            for ext in ["yaml", "yml"]:
                path = subdir / f"{name}.{ext}"
                if path.exists():
                    return path
    
    return None


def load_yaml_file(path: Path) -> Dict[str, Any]:
    """Load YAML file."""
    with open(path, 'r', encoding='utf-8') as f:
        return yaml.safe_load(f)


def load_prompt(
    name: str,
    section: Optional[str] = None,
    local_only: bool = False,
    fallback_to_standard: bool = True
) -> str:
    """
    Load a prompt by name.
    
    Priority:
    1. prompts/local/{name}.yaml (if exists)
    2. prompts/standard_prompts.yaml (if fallback_to_standard=True)
    
    Args:
        name: Prompt name (e.g., "factor_discovery")
        section: Specific section in YAML (e.g., "system" or "user")
        local_only: Only load from local/, raise error if not found
        fallback_to_standard: If True, fall back to standard prompts
    
    Returns:
        Prompt text
    
    Raises:
        FileNotFoundError: If prompt not found
    """
    # Try local prompts first
    local_path = get_local_prompt_path(name)
    
    if local_path:
        print(f"✓ Loading prompt '{name}' from local: {local_path}")
        data = load_yaml_file(local_path)

        if section:
            return data.get(section, "")

        # If data is dict, unwrap single-key dicts (e.g., {'strategy_generation': {'system': ...}})
        if isinstance(data, dict):
            # If only one key and it matches the name, unwrap it
            if len(data) == 1 and name in data:
                return data[name]
            return data
        return str(data)
    
    # Local not found
    if local_only:
        raise FileNotFoundError(f"Local prompt '{name}' not found in {LOCAL_PROMPTS_DIR}")
    
    # Try standard prompts
    if not fallback_to_standard:
        raise FileNotFoundError(f"Prompt '{name}' not found")
    
    if not STANDARD_PROMPTS_FILE.exists():
        raise FileNotFoundError(f"Standard prompts file not found: {STANDARD_PROMPTS_FILE}")
    
    print(f"✓ Loading prompt '{name}' from standard prompts")
    data = load_yaml_file(STANDARD_PROMPTS_FILE)
    
    # Get section from standard prompts
    if name in data:
        prompt_data = data[name]
        
        if section and isinstance(prompt_data, dict):
            return prompt_data.get(section, "")
        
        return prompt_data
    
    raise FileNotFoundError(f"Prompt '{name}' not found in standard prompts")


def load_all_prompts() -> Dict[str, Any]:
    """Load all available prompts."""
    result = {}
    
    # Load standard prompts
    if STANDARD_PROMPTS_FILE.exists():
        result["standard"] = load_yaml_file(STANDARD_PROMPTS_FILE)
    
    # Load local prompts
    if LOCAL_PROMPTS_DIR.exists():
        result["local"] = {}
        for path in LOCAL_PROMPTS_DIR.glob("*.yaml"):
            result["local"][path.stem] = load_yaml_file(path)
    
    return result


def list_available_prompts() -> Dict[str, list]:
    """List all available prompts."""
    result = {"standard": [], "local": []}
    
    # Standard prompts
    if STANDARD_PROMPTS_FILE.exists():
        data = load_yaml_file(STANDARD_PROMPTS_FILE)
        result["standard"] = list(data.keys())
    
    # Local prompts
    if LOCAL_PROMPTS_DIR.exists():
        result["local"] = [p.stem for p in LOCAL_PROMPTS_DIR.glob("*.yaml")]
    
    return result


def get_strategy_discovery_prompt() -> Dict[str, str]:
    """Load strategy discovery prompts from local/strategy_discovery_v1.yaml."""
    return load_prompt("strategy_discovery")


def get_strategy_evaluation_prompt() -> Dict[str, str]:
    """Load strategy evaluation prompts."""
    return load_prompt("strategy_evaluation")


def get_strategy_improvement_prompt() -> Dict[str, str]:
    """Load strategy improvement prompts."""
    return load_prompt("strategy_improvement")


# Convenience functions for specific prompts
def get_factor_discovery_prompt() -> Dict[str, str]:
    """Get factor discovery prompt (system + user)."""
    return load_prompt("factor_discovery")


def get_factor_evolution_prompt() -> Dict[str, str]:
    """Get factor evolution prompt."""
    return load_prompt("factor_evolution")


def get_model_coder_prompt() -> Dict[str, str]:
    """Get model coder prompt."""
    return load_prompt("model_coder")


def get_trading_strategy_prompt() -> Dict[str, str]:
    """Get trading strategy prompt."""
    return load_prompt("strategy_discovery")


def get_strategy_evaluation_prompt() -> Dict[str, str]:
    """Get strategy evaluation prompt."""
    return load_prompt("strategy_discovery", section="strategy_evaluation")


def get_strategy_improvement_prompt() -> Dict[str, str]:
    """Get strategy improvement prompt."""
    return load_prompt("strategy_discovery", section="strategy_improvement")


# Test function
if __name__ == "__main__":
    print("=== Available Prompts ===")
    available = list_available_prompts()
    print(f"Standard: {available['standard']}")
    print(f"Local: {available['local']}")
    
    print("\n=== Testing Prompt Load ===")
    try:
        prompt = load_prompt("factor_discovery")
        print(f"✓ Loaded factor_discovery prompt")
        
        # Handle nested dict structure (local prompts)
        if isinstance(prompt, dict):
            if 'factor_discovery' in prompt:
                # Local prompt structure
                fd = prompt['factor_discovery']
                print(f"  System: {len(fd.get('system', ''))} chars")
                print(f"  User: {len(fd.get('user', ''))} chars")
            else:
                # Standard prompt structure
                print(f"  System: {len(prompt.get('system', ''))} chars")
                print(f"  User: {len(prompt.get('user', ''))} chars")
        else:
            print(f"  Content: {len(str(prompt))} chars")
    except FileNotFoundError as e:
        print(f"✗ Error: {e}")
