# source: https://raw.githubusercontent.com/dasein108/freqtrade_dev_mcp/8d6eb05feb2e780f8c5c996ce1d346a57f0a57ff/src/commands/create_strategy_wireframe.py
"""Create strategy wireframe command implementation."""

import logging
from pathlib import Path
from typing import Any, Dict, Optional

try:
    from .base import BaseCommand, FREQTRADE_AVAILABLE
except ImportError:
    import sys
    from pathlib import Path
    sys.path.insert(0, str(Path(__file__).parent.parent))
    from commands.base import BaseCommand, FREQTRADE_AVAILABLE

logger = logging.getLogger(__name__)


class CreateStrategyWireframeCommand(BaseCommand):
    """Command to create minimal strategy wireframes for maximum LLM flexibility."""

    async def execute(
        self,
        strategy_name: str,
        strategy_path: Optional[str] = None,
        style: str = "minimal",  # minimal, guided, structured
        include_comments: bool = True,
        include_examples: bool = False,
        description: Optional[str] = None,
        **kwargs
    ) -> Dict[str, Any]:
        """Execute create strategy wireframe command.
        
        Args:
            strategy_name: Name of the strategy class and file
            strategy_path: Custom path for strategy file (optional)
            style: Wireframe style (minimal, guided, structured)
            include_comments: Include TODO comments and guidance
            include_examples: Include example code snippets
            description: Strategy description to include in docstring
            
        Returns:
            Command execution result with created wireframe details
        """
        try:
            await self.mcp_log("info", f"Creating strategy wireframe: Github_dasein108_freqtrade_dev_mcp__create_strategy_wireframe__20250820_034726")
            
            # Determine strategy file path
            if strategy_path:
                strategy_file_path = Path(strategy_path).resolve()
            else:
                # Default to strategies directory in current working directory
                strategies_dir = Path.cwd() / "strategies"
                strategies_dir.mkdir(exist_ok=True)
                strategy_file_path = strategies_dir / f"Github_dasein108_freqtrade_dev_mcp__create_strategy_wireframe__20250820_034726.py"
            
            # Check if file already exists
            if strategy_file_path.exists():
                return {
                    "command": "create_strategy_wireframe",
                    "success": False,
                    "error": f"Strategy file {strategy_file_path} already exists. Remove it first or use a different name.",
                    "strategy_path": str(strategy_file_path)
                }
            
            # Generate wireframe code
            wireframe_code = self._generate_wireframe_code(
                strategy_name=strategy_name,
                style=style,
                include_comments=include_comments,
                include_examples=include_examples,
                description=description
            )
            
            # Create directory if it doesn't exist
            strategy_file_path.parent.mkdir(parents=True, exist_ok=True)
            
            # Write wireframe to file
            strategy_file_path.write_text(wireframe_code)
            
            await self.mcp_log("info", f"Strategy wireframe created successfully at {strategy_file_path}")
            
            return {
                "command": "create_strategy_wireframe",
                "success": True,
                "strategy_name": strategy_name,
                "strategy_path": str(strategy_file_path),
                "style": style,
                "wireframe_info": {
                    "lines_of_code": len(wireframe_code.split('\n')),
                    "includes_comments": include_comments,
                    "includes_examples": include_examples,
                    "ready_for_customization": True
                },
                "next_steps": [
                    "Customize populate_indicators() with your technical indicators",
                    "Define entry logic in populate_entry_trend()",
                    "Define exit logic in populate_exit_trend()",
                    "Adjust strategy parameters (ROI, stoploss, timeframe)",
                    "Test with backtesting and optimize with hyperopt"
                ]
            }
            
        except Exception as e:
            await self.mcp_log("error", f"Create strategy wireframe command failed: {e}")
            return {
                "command": "create_strategy_wireframe",
                "success": False,
                "error": str(e),
                "strategy_name": strategy_name
            }

    def _generate_wireframe_code(
        self,
        strategy_name: str,
        style: str,
        include_comments: bool,
        include_examples: bool,
        description: Optional[str]
    ) -> str:
        """Generate wireframe code based on style and options."""
        
        if style == "minimal":
            return self._generate_minimal_wireframe(strategy_name, description, include_comments)
        elif style == "guided":
            return self._generate_guided_wireframe(strategy_name, description, include_comments, include_examples)
        elif style == "structured":
            return self._generate_structured_wireframe(strategy_name, description, include_comments, include_examples)
        else:
            return self._generate_minimal_wireframe(strategy_name, description, include_comments)

    def _generate_minimal_wireframe(self, strategy_name: str, description: Optional[str], include_comments: bool) -> str:
        """Generate minimal wireframe - maximum flexibility for LLMs."""
        
        desc = description or f"TODO: Describe your Github_dasein108_freqtrade_dev_mcp__create_strategy_wireframe__20250820_034726 strategy"
        
        comments = {
            "class_comment": f'''
    \"\"\"
    {desc}
    
    TODO: Implement your trading strategy logic
    \"\"\"''' if include_comments else '',
            
            "indicators_comment": '''
        """
        TODO: Add your technical indicators here
        Examples: RSI, MACD, Bollinger Bands, Moving Averages, etc.
        """''' if include_comments else '',
            
            "entry_comment": '''
        """
        TODO: Define your entry conditions
        Combine indicators and market conditions to create entry signals
        """''' if include_comments else '',
            
            "exit_comment": '''
        """
        TODO: Define your exit conditions  
        Set conditions for taking profits or cutting losses
        """''' if include_comments else ''
        }
        
        return f'''\
"""Github_dasein108_freqtrade_dev_mcp__create_strategy_wireframe__20250820_034726 Strategy

{desc}

Generated wireframe - customize as needed.
"""

from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
import talib.abstract as ta


class Github_dasein108_freqtrade_dev_mcp__create_strategy_wireframe__20250820_034726(IStrategy):{comments["class_comment"]}
    
    # Strategy interface version
    INTERFACE_VERSION: int = 3
    
    # TODO: Set your preferred timeframe
    timeframe = '5m'
    
    # TODO: Enable if strategy can short
    can_short: bool = False
    
    # TODO: Define your ROI table
    minimal_roi = {{
        "60": 0.01,
        "30": 0.02,
        "0": 0.04
    }}
    
    # TODO: Set your stop loss
    stoploss = -0.10
    
    # TODO: Configure trailing stop if needed
    trailing_stop = False
    
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:{comments["indicators_comment"]}
        # TODO: Add your indicators here
        
        return dataframe
    
    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:{comments["entry_comment"]}
        # TODO: Define entry conditions
        # Example structure:
        # dataframe.loc[
        #     (
        #         # Your conditions here
        #         (dataframe['volume'] > 0)  # Always include volume check
        #     ),
        #     'enter_long'] = 1
        
        return dataframe
    
    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:{comments["exit_comment"]}
        # TODO: Define exit conditions
        # Example structure:
        # dataframe.loc[
        #     (
        #         # Your exit conditions here
        #         (dataframe['volume'] > 0)  # Always include volume check
        #     ),
        #     'exit_long'] = 1
        
        return dataframe
'''

    def _generate_guided_wireframe(self, strategy_name: str, description: Optional[str], include_comments: bool, include_examples: bool) -> str:
        """Generate guided wireframe with more hints and examples."""
        
        desc = description or f"Guided wireframe for Github_dasein108_freqtrade_dev_mcp__create_strategy_wireframe__20250820_034726 strategy"
        
        examples = '''
        # Example indicators - uncomment and modify as needed:
        # dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
        # dataframe['macd'] = ta.MACD(dataframe)['macd']
        # dataframe['bb_lower'] = ta.BBANDS(dataframe)['lowerband']
        # dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
        # dataframe['ema12'] = ta.EMA(dataframe, timeperiod=12)
        ''' if include_examples else ''
        
        entry_examples = '''
        # Example entry conditions - uncomment and modify:
        # dataframe.loc[
        #     (
        #         (dataframe['rsi'] < 30) &          # Oversold
        #         (dataframe['close'] > dataframe['sma20']) &  # Above trend
        #         (dataframe['volume'] > dataframe['volume'].rolling(20).mean()) &  # High volume
        #         (dataframe['volume'] > 0)           # Volume check
        #     ),
        #     'enter_long'] = 1
        ''' if include_examples else ''
        
        exit_examples = '''
        # Example exit conditions - uncomment and modify:
        # dataframe.loc[
        #     (
        #         (dataframe['rsi'] > 70) |          # Overbought
        #         (dataframe['close'] < dataframe['sma20']) |  # Below trend
        #         (dataframe['volume'] > 0)           # Volume check
        #     ),
        #     'exit_long'] = 1
        ''' if include_examples else ''
        
        return f'''\
"""Github_dasein108_freqtrade_dev_mcp__create_strategy_wireframe__20250820_034726 Strategy

{desc}

This guided wireframe provides structure and examples to help you build your strategy.
Follow the TODO comments and uncomment/modify example code as needed.
"""

from freqtrade.strategy.interface import IStrategy
from pandas import DataFrame
import talib.abstract as ta
import numpy as np


class Github_dasein108_freqtrade_dev_mcp__create_strategy_wireframe__20250820_034726(IStrategy):
    """
    Guided strategy wireframe with examples and hints.
    
    Step 1: Choose your indicators in populate_indicators()
    Step 2: Define entry logic in populate_entry_trend() 
    Step 3: Define exit logic in populate_exit_trend()
    Step 4: Tune parameters (ROI, stoploss, etc.)
    Step 5: Backtest and optimize
    """
    
    # Strategy interface version - always use 3
    INTERFACE_VERSION: int = 3
    
    # TODO: Choose optimal timeframe for your strategy
    # Common: '1m', '5m', '15m', '1h', '4h', '1d'
    timeframe = '5m'
    
    # TODO: Set to True if strategy can go short
    can_short: bool = False
    
    # TODO: Define ROI table - profits at which to exit
    # Format: "minutes": profit_ratio
    minimal_roi = {{
        "60": 0.01,    # 1% after 60 minutes
        "30": 0.02,    # 2% after 30 minutes  
        "0": 0.04      # 4% immediately
    }}
    
    # TODO: Set stop loss (negative value, e.g., -0.10 = 10% loss)
    stoploss = -0.10
    
    # TODO: Enable trailing stop to lock in profits
    trailing_stop = False
    # trailing_stop_positive = 0.01
    # trailing_stop_positive_offset = 0.02
    
    # TODO: Add strategy-specific parameters for optimization
    # buy_rsi = IntParameter(20, 40, default=30, space="buy")
    # sell_rsi = IntParameter(60, 80, default=70, space="sell")
    
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Add technical indicators to the dataframe.
        
        This is where you calculate all the indicators you'll use in your entry/exit logic.
        Common indicators: RSI, MACD, Bollinger Bands, Moving Averages, Volume indicators
        """
        
        # TODO: Add your indicators here{examples}
        
        return dataframe
    
    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Define entry signals for your strategy.
        
        Set 'enter_long' = 1 where you want to enter long positions.
        Set 'enter_short' = 1 where you want to enter short positions (if can_short=True).
        
        Combine multiple indicators for better signals.
        Always include volume > 0 check.
        """
        
        # TODO: Define your entry conditions{entry_examples}
        
        return dataframe
    
    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Define exit signals for your strategy.
        
        Set 'exit_long' = 1 where you want to exit long positions.
        Set 'exit_short' = 1 where you want to exit short positions.
        
        Note: ROI and stoploss will also trigger exits automatically.
        """
        
        # TODO: Define your exit conditions{exit_examples}
        
        return dataframe
    
    # TODO: Uncomment and implement custom methods if needed
    # def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
    #                     current_rate: float, current_profit: float, **kwargs) -> float:
    #     """Custom stoploss logic"""
    #     return self.stoploss
    
    # def confirm_trade_entry(self, pair: str, order_type: str, amount: float,
    #                         rate: float, time_in_force: str, current_time: datetime,
    #                         entry_tag: Optional[str], side: str, **kwargs) -> bool:
    #     """Confirm trade entry"""
    #     return True
'''

    def _generate_structured_wireframe(self, strategy_name: str, description: Optional[str], include_comments: bool, include_examples: bool) -> str:
        """Generate structured wireframe with organized sections and advanced features."""
        
        desc = description or f"Structured wireframe for Github_dasein108_freqtrade_dev_mcp__create_strategy_wireframe__20250820_034726 strategy with advanced features"
        
        return f'''\
"""Github_dasein108_freqtrade_dev_mcp__create_strategy_wireframe__20250820_034726 Strategy

{desc}

This structured wireframe provides a comprehensive template with organized sections
for building sophisticated trading strategies.
"""

from freqtrade.strategy.interface import IStrategy
from freqtrade.strategy import merge_informative_pair, DecimalParameter, IntParameter, BooleanParameter
from pandas import DataFrame
import talib.abstract as ta
import numpy as np
from typing import Optional
from datetime import datetime


class Github_dasein108_freqtrade_dev_mcp__create_strategy_wireframe__20250820_034726(IStrategy):
    """
    Structured strategy template with advanced features.
    
    Features included:
    - Hyperopt parameter optimization
    - Informative timeframes
    - Custom stoploss and ROI
    - Entry/exit confirmation
    - Risk management
    """
    
    # Strategy interface version
    INTERFACE_VERSION: int = 3
    
    # === BASIC CONFIGURATION ===
    timeframe = '5m'
    can_short: bool = False
    
    # Startup candle count for indicators
    startup_candle_count: int = 30
    
    # === ROI & STOPLOSS ===
    minimal_roi = {{
        "60": 0.01,
        "30": 0.02,
        "0": 0.04
    }}
    
    stoploss = -0.10
    trailing_stop = False
    
    # === HYPEROPT PARAMETERS ===
    # TODO: Define parameters for optimization
    # buy_rsi_enabled = BooleanParameter(default=True, space="buy")
    # buy_rsi = IntParameter(20, 40, default=30, space="buy")
    # sell_rsi = IntParameter(60, 80, default=70, space="sell")
    # roi_p1 = DecimalParameter(0.01, 0.05, default=0.01, space="sell")
    # roi_p2 = DecimalParameter(0.01, 0.07, default=0.02, space="sell")
    # roi_p3 = DecimalParameter(0.01, 0.20, default=0.04, space="sell")
    
    # === INFORMATIVE TIMEFRAMES ===
    def informative_pairs(self):
        """
        Define additional pairs and timeframes for context.
        """
        pairs = self.dp.current_whitelist()
        informative_pairs = []
        
        # TODO: Add informative timeframes
        # for pair in pairs:
        #     informative_pairs.append((pair, '1h'))
        
        return informative_pairs
    
    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Add technical indicators organized by category.
        """
        
        # === TREND INDICATORS ===
        # TODO: Add trend indicators
        # dataframe['sma20'] = ta.SMA(dataframe, timeperiod=20)
        # dataframe['ema12'] = ta.EMA(dataframe, timeperiod=12)
        # dataframe['ema26'] = ta.EMA(dataframe, timeperiod=26)
        
        # === MOMENTUM INDICATORS ===
        # TODO: Add momentum indicators
        # dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14)
        # macd = ta.MACD(dataframe)
        # dataframe['macd'] = macd['macd']
        # dataframe['macdsignal'] = macd['macdsignal']
        
        # === VOLATILITY INDICATORS ===
        # TODO: Add volatility indicators
        # bollinger = ta.BBANDS(dataframe, timeperiod=20)
        # dataframe['bb_lower'] = bollinger['lowerband']
        # dataframe['bb_middle'] = bollinger['middleband'] 
        # dataframe['bb_upper'] = bollinger['upperband']
        # dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)
        
        # === VOLUME INDICATORS ===
        # TODO: Add volume indicators
        # dataframe['volume_sma'] = ta.SMA(dataframe['volume'], timeperiod=20)
        
        # === INFORMATIVE TIMEFRAME DATA ===
        # TODO: Merge informative timeframe data
        # if self.dp:
        #     inf_tf = '1h'
        #     informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=inf_tf)
        #     informative['rsi_1h'] = ta.RSI(informative, timeperiod=14)
        #     dataframe = merge_informative_pair(dataframe, informative, self.timeframe, inf_tf, ffill=True)
        
        return dataframe
    
    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Define entry conditions with organized logic.
        """
        
        conditions_long = []
        conditions_short = []
        
        # === LONG ENTRY CONDITIONS ===
        # TODO: Add long entry conditions
        # Trend conditions
        # conditions_long.append(dataframe['close'] > dataframe['sma20'])
        
        # Momentum conditions  
        # conditions_long.append(dataframe['rsi'] < self.buy_rsi.value)
        
        # Volume conditions
        # conditions_long.append(dataframe['volume'] > dataframe['volume_sma'])
        
        # Volatility conditions
        # conditions_long.append(dataframe['close'] < dataframe['bb_lower'])
        
        # Base conditions (always required)
        conditions_long.append(dataframe['volume'] > 0)
        
        # === SHORT ENTRY CONDITIONS ===
        if self.can_short:
            # TODO: Add short entry conditions
            # conditions_short.append(dataframe['close'] < dataframe['sma20'])
            # conditions_short.append(dataframe['rsi'] > 70)
            conditions_short.append(dataframe['volume'] > 0)
        
        # Apply conditions
        if conditions_long:
            dataframe.loc[
                reduce(lambda x, y: x & y, conditions_long),
                'enter_long'
            ] = 1
        
        if conditions_short:
            dataframe.loc[
                reduce(lambda x, y: x & y, conditions_short),
                'enter_short'
            ] = 1
        
        return dataframe
    
    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        """
        Define exit conditions with organized logic.
        """
        
        conditions_long_exit = []
        conditions_short_exit = []
        
        # === LONG EXIT CONDITIONS ===
        # TODO: Add long exit conditions
        # conditions_long_exit.append(dataframe['rsi'] > self.sell_rsi.value)
        # conditions_long_exit.append(dataframe['close'] > dataframe['bb_upper'])
        
        # Base conditions
        conditions_long_exit.append(dataframe['volume'] > 0)
        
        # === SHORT EXIT CONDITIONS ===
        if self.can_short:
            # TODO: Add short exit conditions
            # conditions_short_exit.append(dataframe['rsi'] < 30)
            conditions_short_exit.append(dataframe['volume'] > 0)
        
        # Apply conditions
        if conditions_long_exit:
            dataframe.loc[
                reduce(lambda x, y: x & y, conditions_long_exit),
                'exit_long'
            ] = 1
        
        if conditions_short_exit:
            dataframe.loc[
                reduce(lambda x, y: x & y, conditions_short_exit),
                'exit_short'
            ] = 1
        
        return dataframe
    
    # === CUSTOM METHODS ===
    
    def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime,
                       current_rate: float, current_profit: float, **kwargs) -> float:
        """
        Custom stoploss logic - TODO: Implement if needed
        """
        # TODO: Implement custom stoploss logic
        # Example: Trailing stoploss that becomes more aggressive over time
        return self.stoploss
    
    def confirm_trade_entry(self, pair: str, order_type: str, amount: float,
                           rate: float, time_in_force: str, current_time: datetime,
                           entry_tag: Optional[str], side: str, **kwargs) -> bool:
        """
        Entry confirmation - TODO: Implement if needed
        """
        # TODO: Add entry confirmation logic
        # Example: Check for sufficient volume, spread, etc.
        return True
    
    def confirm_trade_exit(self, pair: str, trade: 'Trade', order_type: str,
                          amount: float, rate: float, time_in_force: str,
                          exit_reason: str, current_time: datetime, **kwargs) -> bool:
        """
        Exit confirmation - TODO: Implement if needed
        """
        # TODO: Add exit confirmation logic
        return True
    
    # === HELPER METHODS ===
    
    def get_market_condition(self, dataframe: DataFrame) -> str:
        """
        Determine market condition - TODO: Implement if needed
        """
        # TODO: Implement market condition detection
        # Example: trending, ranging, volatile
        return "unknown"


# TODO: Import reduce function if using conditions
from functools import reduce
'''