from sqlalchemy import Column, Float, Integer, Date, String, Text
from sqlalchemy.sql.sqltypes import BigInteger


# 動的にモデルクラスを定義
def create_stock_model(table_name, Base):
    # クラス名をテーブル名に基づいて一意にする
    class_name = f"{table_name}Model"

    if table_name in Base.metadata.tables:
        # Base 内に登録されたクラス
        for cls in Base.registry._class_registry.values():
            if hasattr(cls, "__tablename__") and cls.__tablename__ == table_name:
                return cls

    # モデルクラスの定義
    StockModel = type(
        class_name,
        (Base,),
        {
            "__tablename__": table_name,
            "__table_args__": {"extend_existing": True},
            "date": Column(Date, primary_key=True),  # 日付をプライマリキーに設定
            "open": Column(Float),
            "high": Column(Float),
            "low": Column(Float),
            "close": Column(Float),
            "volume": Column(BigInteger),  # BIGINT 型を使用
            "ma5": Column(Float),  # 5日移動平均
            "ma25": Column(Float),  # 25日移動平均
            "ma75": Column(Float),  # 75日移動平均
            "upper2": Column(Float),  # ボリンジャーバンド　 +2σ
            "lower2": Column(Float),  # ボリンジャーバンド -2σ
            "macd": Column(Float),  # MACD
            "macd_signal": Column(Float),  # Signal
            "hist": Column(Float),  # ヒストグラム
            "rsi14": Column(Float),  # RSI14
            "rsi28": Column(Float),  # RSI28
            "rci9": Column(Float),  # RCI9
            "rci26": Column(Float),  # RCI26
            "__repr__": lambda self: f"<{class_name}(date={self.date}, close={self.close})>",
        },
    )

    # 定義したモデルクラスを返却
    return StockModel


# Stock モデルクラスを取得
def get_stock_class(Base):
    # テーブル名
    table_name = "stocks"

    # 既存クラスを確認
    for cls in Base.registry._class_registry.values():
        if hasattr(cls, "__tablename__") and cls.__tablename__ == table_name:
            return cls

    class Stock(Base):
        __tablename__ = table_name

        # id: 主キーでオートインクリメントを有効
        id = Column(Integer, primary_key=True, autoincrement=True)

        # code: ４文字以内でNULLと重複を許可しない
        code = Column(String(4), unique=True, nullable=False)

        # name: 16文字以内でNULLを許可しない
        name = Column(String(16), nullable=False)

        memo = Column(Text, nullable=True)

        def __repr__(self):
            return f"<Stock(id={self.id}, code='{self.code}', name='{self.name}')>"

    return Stock
