"""Cockpit ORM models — its own Declarative Base so create_all is independent of the factory's Base.
JSON columns work on both SQLite (tests) and Postgres (prod). The forward_nav table becomes a TimescaleDB
hypertable in prod via a guarded DDL call (see forward_nav.py); on SQLite it stays a plain table."""
from __future__ import annotations

import datetime as dt

from sqlalchemy import JSON, Boolean, Date, DateTime, Float, Integer, String
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column


class CockpitBase(DeclarativeBase):
    pass


class ForwardNavRow(CockpitBase):
    __tablename__ = "forward_nav"
    strategy_id: Mapped[str] = mapped_column(String(64), primary_key=True)
    date: Mapped[dt.date] = mapped_column(Date, primary_key=True)   # real DATE — TimescaleDB hypertable dimension
    ret: Mapped[float] = mapped_column(Float)
    nav: Mapped[float] = mapped_column(Float)
    src_updated_at: Mapped[dt.datetime] = mapped_column(DateTime)


class ForwardSummaryRow(CockpitBase):
    __tablename__ = "forward_summary"
    strategy_id: Mapped[str] = mapped_column(String(64), primary_key=True)
    as_of: Mapped[str] = mapped_column(String(10))
    days: Mapped[int] = mapped_column(Integer)
    nav: Mapped[float] = mapped_column(Float)
    total_return: Mapped[float] = mapped_column(Float)
    sharpe: Mapped[float] = mapped_column(Float)
    maxdd: Mapped[float] = mapped_column(Float)
    gate_status: Mapped[str] = mapped_column(String(8), default="WAIT")
    gate_reason: Mapped[str] = mapped_column(String(256), default="")
    src_updated_at: Mapped[dt.datetime] = mapped_column(DateTime)


class StrategyRegistryRow(CockpitBase):
    __tablename__ = "strategy_registry"
    strategy_id: Mapped[str] = mapped_column(String(64), primary_key=True)
    display_name: Mapped[str] = mapped_column(String(96))
    sleeve: Mapped[str] = mapped_column(String(32))
    venue: Mapped[str] = mapped_column(String(32), default="")
    capital_base: Mapped[float] = mapped_column(Float, default=0.0)
    gate_spec: Mapped[dict] = mapped_column(JSON)
    enabled: Mapped[bool] = mapped_column(Boolean, default=True)


class ExecFillRow(CockpitBase):
    __tablename__ = "exec_fills"
    client_id: Mapped[str] = mapped_column(String(64), primary_key=True)
    rebalance_id: Mapped[str] = mapped_column(String(48), index=True)
    symbol: Mapped[str] = mapped_column(String(32))
    side: Mapped[str] = mapped_column(String(4))
    qty: Mapped[float] = mapped_column(Float)
    price: Mapped[float] = mapped_column(Float)
    fee: Mapped[float] = mapped_column(Float)
    status: Mapped[str] = mapped_column(String(12))
    shortfall_bps: Mapped[float] = mapped_column(Float)
    at: Mapped[dt.datetime] = mapped_column(DateTime)


class FactoryCycleRow(CockpitBase):
    __tablename__ = "factory_cycles"
    cycle_id: Mapped[str] = mapped_column(String(48), primary_key=True)
    proposed: Mapped[int] = mapped_column(Integer)
    tested: Mapped[int] = mapped_column(Integer)
    survived: Mapped[int] = mapped_column(Integer)
    forward: Mapped[int] = mapped_column(Integer)
    deployed: Mapped[int] = mapped_column(Integer)
    retired: Mapped[int] = mapped_column(Integer)
    global_trials: Mapped[int] = mapped_column(Integer)
    at: Mapped[dt.datetime] = mapped_column(DateTime)


class FactoryAllocationRow(CockpitBase):
    __tablename__ = "factory_allocation"
    cycle_id: Mapped[str] = mapped_column(String(48), primary_key=True)
    strategy_id: Mapped[str] = mapped_column(String(64), primary_key=True)
    weight: Mapped[float] = mapped_column(Float)
    at: Mapped[dt.datetime] = mapped_column(DateTime)


class FactoryFlagRow(CockpitBase):
    """Persisted kill-switch and other factory flags (key/value). key="kill", value="1"/"0"."""
    __tablename__ = "factory_flags"
    key: Mapped[str] = mapped_column(String(32), primary_key=True)
    value: Mapped[str] = mapped_column(String(16))
