import backtrader as bt
import pandas as pd
import datetime

class TestStrategy(bt.Strategy):
    params = (('ema_fast', 9), ('ema_slow', 21), ('ema_long', 200), ('rsi_period', 14), ('rsi_buy', 35))

    def __init__(self):
        self.ema_fast = bt.indicators.EMA(period=self.p.ema_fast)
        self.ema_slow = bt.indicators.EMA(period=self.p.ema_slow)
        self.ema_long = bt.indicators.EMA(period=self.p.ema_long)
        self.rsi = bt.indicators.RSI(period=self.p.rsi_period)
        self.crossover = bt.indicators.CrossOver(self.ema_fast, self.ema_slow)

    def next(self):
        if not self.position:
            if self.crossover > 0 and self.rsi < self.p.rsi_buy and self.data.close[0] > self.ema_long[0]:
                self.buy()
        else:
            if self.crossover < 0:
                self.sell()

class Backtester:
    def __init__(self, config):
        self.config = config

    def run_backtest(self, symbol, df):
        cerebro = bt.Cerebro()
        
        data = bt.feeds.PandasData(dataname=df, datetime='timestamp', open='open', high='high', low='low', close='close', volume='volume', openinterest=-1)
        cerebro.adddata(data)
        
        params = self.config['strategy_params']
        cerebro.addstrategy(TestStrategy, 
                            ema_fast=params['ema_fast'], 
                            ema_slow=params['ema_slow'], 
                            ema_long=params['ema_long'], 
                            rsi_period=params['rsi_period'],
                            rsi_buy=params['rsi_buy_threshold'])
        
        cerebro.broker.setcash(10000.0)
        cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="trades")
        cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name="sharpe")
        cerebro.addanalyzer(bt.analyzers.DrawDown, _name="drawdown")
        
        results = cerebro.run()
        res = results[0]
        
        trades = res.analyzers.trades.get_analysis()
        sharpe = res.analyzers.sharpe.get_analysis()
        drawdown = res.analyzers.drawdown.get_analysis()

        metrics = {
            "total_trades": trades.total.total if 'total' in trades else 0,
            "win_rate": (trades.won.total / trades.total.total * 100) if trades.total.total > 0 else 0,
            "sharpe_ratio": sharpe['sharperatio'] if sharpe['sharperatio'] else 0,
            "max_drawdown": drawdown.max.drawdown if 'max' in drawdown else 0,
            "return_pct": (cerebro.broker.getvalue() - 10000.0) / 100.0
        }
        
        return metrics
