# source: https://raw.githubusercontent.com/Aatif-qmr/cipher/f3735aaf3655923bb1c8ee70c054c6a1a0d8831d/strategies/archive/DailyTrendV1.py
# directory_url: https://github.com/Aatif-qmr/cipher/blob/main/strategies/archive/
# User: Aatif-qmr
# Repository: cipher
# --------------------import json
import logging
import sys
from datetime import datetime, timedelta
from pathlib import Path

from pandas import DataFrame

# Resolve project root from this file's location (works on any machine)
_BASE = Path(__file__).resolve().parent.parent.parent
if str(_BASE) not in sys.path:
    sys.path.insert(0, str(_BASE))

from freqtrade.persistence import Trade
from freqtrade.strategy import IStrategy

from indicators.macro_merge import merge_macro_data
from qnt.oracle.hmm_regime import detect_regime, get_regime_for_strategy
from qnt.oracle.oracle_calendar import is_safe_to_trade_today
from qnt.thesis.thesis_reader import read_thesis
from risk.risk_manager import run_all_checks
from sentiment.reader import get_current_sentiment

logger = logging.getLogger(__name__)


class Github_Aatif_qmr_cipher__DailyTrendV1__20260901_081406(IStrategy):
    """
    Daily trend following strategy.
    Entry: Price > 50-day EMA + RSI cross above 45 + Vol expansion
    Exit: RSI > 70 or Price < 50-day EMA
    """

    INTERFACE_VERSION = 3

    timeframe = "1d"

    stoploss = -0.08

    minimal_roi = {"0": 0.08, "7": 0.05, "3": 0.03}

    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        from qnt.polars_indicators import add_ema, add_rsi, add_sma
        from qnt.polars_ohlcv import ohlcv_to_pandas, pandas_to_polars

        df_pl = pandas_to_polars(dataframe)

        df_pl = add_ema(df_pl, period=50, alias="ema_50")
        df_pl = add_rsi(df_pl, period=14, alias="rsi")
        df_pl = add_sma(df_pl, period=10, column="volume", alias="volume_avg")

        dataframe = ohlcv_to_pandas(df_pl)
        dataframe = merge_macro_data(dataframe)
        return dataframe

    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        sentiment = get_current_sentiment()

        # HMM Regime Check
        regime = detect_regime(dataframe, metadata["pair"])
        regime_ok = get_regime_for_strategy("Github_Aatif_qmr_cipher__DailyTrendV1__20260901_081406", regime)

        dataframe.loc[
            (
                (dataframe["close"] > dataframe["ema_50"])
                & (dataframe["rsi"] > 45)
                & (dataframe["rsi"].shift(1) <= 45)
                & (dataframe["volume"] > dataframe["volume_avg"])
                & (sentiment["score"] >= -0.3)  # Not BEARISH
                & (is_safe_to_trade_today())  # Calendar Gate
                & (regime_ok)
            ),
            "enter_long",
        ] = 1

        return dataframe

    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        dataframe.loc[
            ((dataframe["rsi"] > 70) | (dataframe["close"] < dataframe["ema_50"])), "exit_long"
        ] = 1
        return dataframe

    def confirm_trade_entry(
        self,
        pair: str,
        order_type: str,
        amount: float,
        rate: float,
        time_in_force: str,
        current_time: datetime,
        entry_tag: str,
        side: str,
        **kwargs,
    ) -> bool:
        # --- LAYER 0: THESIS GATE ---
        thesis = read_thesis(pair)
        if thesis["bias"] == "SELL":
            logger.info(
                f"[THESIS BLOCK] {pair} bias=SELL confidence={thesis['confidence']:.2f} — {thesis['reasoning']}"
            )
            return False
        stake_modifier = thesis.get("stake_modifier", 1.0)

        # --- LAYER 1: RISK & SENTIMENT CHECKS ---
        try:
            total_balance = self.wallets.get_total("USDT")

            # Fetch recent trades for loss counting
            recent_trades = [
                {
                    "profit_ratio": float(
                        getattr(t, "close_profit", None) or getattr(t, "profit_ratio", None) or 0.0
                    ),
                    "close_date": getattr(t, "close_date", None),
                }
                for t in Trade.get_trades_proxy(is_open=False)
            ][:10]

            # Count trades in the last hour
            one_hour_ago = current_time - timedelta(hours=1)
            trades_last_hour = len(
                [
                    t
                    for t in Trade.get_trades_proxy(is_open=False)
                    if t.close_date and t.close_date >= one_hour_ago
                ]
            )

            # Load balance state for drawdown checks
            state_file = _BASE / "risk/balance_state.json"
            if state_file.exists():
                with open(state_file) as f:
                    state = json.load(f)
                start_of_day = state.get("start_of_day", total_balance)
                start_of_week = state.get("start_of_week", total_balance)
            else:
                start_of_day = total_balance
                start_of_week = total_balance

            # Github_Aatif_qmr_cipher__DailyTrendV1__20260901_081406 requires at least NEUTRAL sentiment
            risk_result = run_all_checks(
                current_balance=total_balance,
                start_of_day_balance=start_of_day,
                start_of_week_balance=start_of_week,
                trade_amount_usdt=amount * rate * stake_modifier,
                trades_last_hour=trades_last_hour,
                recent_trades=recent_trades,
                min_sentiment="NEUTRAL",
            )

            if not risk_result["safe_to_trade"]:
                logger.info(
                    f"[RISK/SENTIMENT BLOCK] DailyTrend blocked for {pair}. Reasons: {risk_result['blocking_reasons']}"
                )
                return False

            # Log sentiment for visibility
            sentiment = get_current_sentiment()
            logger.info(f"[Sentiment Check] {pair} | Score: {sentiment['score']:.3f}")

        except Exception as e:
            logger.error(f"[RISK WARNING] Risk check error: {e}")

        return True
