import pandas as pd
from database_manager import DatabaseManager
from models import create_stock_model


def get_dataframe(code: str) -> pd.DataFrame:
    """
    指定された銘柄コードの株価データをデータベースから取得し、Pandas DataFrame 形式で返す。

    Args:
        code (str): 取得する株式の銘柄コード。

    Returns:
        pd.DataFrame: 取得した株価データの DataFrame。
                     - インデックス: `date` (datetime)
    """
    db_manager = DatabaseManager()
    session = db_manager.get_session()

    # 銘柄コードに基づくモデルクラスを作成
    StockModel = create_stock_model(f"stock_{code}", db_manager.Base)

    stock_datas = session.query(StockModel).all()
    dicts = [vars(stock_data) for stock_data in stock_datas]
    df = pd.DataFrame(dicts).drop("_sa_instance_state", axis=1)
    # dateカラムをインデックスに設定
    df.set_index("date", inplace=True)
    df.index = pd.to_datetime(df.index)
    return df


# 移動平均線のゴールデンクロスのチェック
def check_ma_golden_cross(df: pd.DataFrame) -> bool:
    """
    指定されたDataFrame内の移動平均線を用いて、直近3日間のゴールデンクロス発生を判定する。

    Args:
        df (pd.DataFrame): MA5とMA25を含む株価データのDataFrame。

    Returns:
        bool: ゴールデンクロスが発生していればTrue、それ以外はFalse。
    """
    if len(df) < 3:  # データが不足している場合
        return False

    # 直近3日分のma5とma25のリストを作成
    ma5_3_days = df["ma5"].tail(3).tolist()  # ma5: 短期移動平均線（5日）
    ma25_3_days = df["ma25"].tail(3).tolist()  # ma25: 長期移動平均線（25日）

    # 最新日（当日）にゴールデンクロスが発生（前日までma5がma25以下で、当日に上回る）
    if ma5_3_days[2] > ma25_3_days[2]:  # 当日のma5がma25を上回っている
        if ma5_3_days[1] < ma25_3_days[1]:  # 前日のma5がma25を下回っている
            return True

    # 前日にゴールデンクロスが発生（2日前はma5がma25を下回り、前日に上回る）
    if ma5_3_days[1] > ma25_3_days[1]:  # 前日のma5がma25を上回っている
        if ma5_3_days[0] < ma25_3_days[0]:  # 2日前のma5がma25を下回っている
            return True

    # 上記以外
    return False


# MACDのゴールデンクロスのチェック
def check_macd_golden_cross(df: pd.DataFrame) -> bool:
    """
    指定されたDataFrame内のMACDを用いて、直近3日間のゴールデンクロス発生を判定する。

    Args:
        df (pd.DataFrame): MACDとシグナルを含む株価データのDataFrame。

    Returns:
        bool: ゴールデンクロスが発生していれば True、それ以外はFalse。
    """
    if len(df) < 3:  # データが不足している場合
        return False

    # 直近3日分のMACDとシグナルのリストを作成（降順なので最新が最初）
    macd_3_days = df["macd"].tail(3).tolist()  # MACD
    signal_3_days = df["macd_signal"].tail(3).tolist()  # シグナル

    # 最新日（当日）にMACDのゴールデンクロスが発生
    if macd_3_days[2] > signal_3_days[2]:  # 当日のMACDがシグナルを上回っている
        if macd_3_days[1] < signal_3_days[1]:  # 前日のMACDがシグナルを下回っている
            return True

    # 前日にMACDのゴールデンクロスが発生
    if macd_3_days[1] > signal_3_days[1]:  # 前日のMACDがシグナルを上回っている
        if macd_3_days[0] < signal_3_days[0]:  # 2日前のMACDがシグナルを下回っている
            return True

    # 上記以外
    return False


# RCIのゴールデンクロスのチェック
def check_rci_golden_cross(df: pd.DataFrame) -> bool:
    """
    指定されたDataFrame内のRCIを用いて、直近3日間のゴールデンクロス発生を判定する。

    Args:
        df (pd.DataFrame): RCI9とRCI26を含む株価データのDataFrame。

    Returns:
        bool: ゴールデンクロスが発生していれば True、それ以外はFalse。
    """
    if len(df) < 3:  # データが不足している場合
        return False

    # 直近3日間のRCI9とRCI26のリストを作成
    rci9_3_days = df["rci9"].tail(3).tolist()  # RCI9
    rci26_3_days = df["rci26"].tail(3).tolist()  # RCI26

    # 最新日（当日）にRCIのゴールデンクロスが発生
    if rci9_3_days[2] > rci26_3_days[2]:  # 当日のRCI9がRCI26を上回っている
        if rci9_3_days[1] < rci26_3_days[1]:  # 前日のRCI9がRCI26を下回っている
            return True

    # 前日にRCIのゴールデンクロスが発生
    if rci9_3_days[1] > rci26_3_days[1]:  # 前日のRCI9がRCI26を上回っている
        if rci9_3_days[0] < rci26_3_days[0]:  # 2日前のRCI9がRCI26を下回っている
            return True

    # 上記以外
    return False


# ・MACDがシグナルより下でゴールデンクロス前
# ・MACDが日々上昇しつつある
# ・長期RCIが-50未満
def check_rising_condition(df: pd.DataFrame) -> bool:
    """
    株価データのMACD・RCIを解析し、上昇の兆候があるかを判定する。

    判定条件:
    1. MACD がシグナルより下にある（ゴールデンクロス前の状態）。
    2. MACD が日々上昇している（直近2日間でMACDが増加傾向）。
    3. 長期RCI（RCI26）が-50未満である（売られすぎの状態）。

    Args:
        df (pd.DataFrame): MACD／シグナル／RCI26のカラムを含む株価データのDataFrame。

    Returns:
        bool: 条件を満たしていれば True、そうでなければFalse。
    """
    if len(df) < 3:  # データが不足している場合
        return False

    df = df.tail(3)
    # MACDがシグナルより下（ゴールデンクロス前）
    if df.iloc[2]["macd"] < df.iloc[2]["macd_signal"]:
        # MACDが日々上昇
        if (
            df.iloc[0]["macd"] < df.iloc[1]["macd"]
            and df.iloc[0]["macd"] < df.iloc[1]["macd"]
        ):
            # 長期RCIが-50未満
            if df.iloc[0]["rci26"] < -50:
                return True

    # 上記以外
    return False
