"""Market data: prices and corporate actions."""
from __future__ import annotations

from datetime import date
from typing import Optional

from sqlalchemy import Date, ForeignKey, String, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column

from app.models.base import Base, TimestampMixin, uuid_pk


class Price(Base, TimestampMixin):
    """Daily OHLCV. In production this table is partitioned by year (spec §71 scalability) —
    left as a plain indexed table here; see docs/DEPLOYMENT.md for the partitioning note."""

    __tablename__ = "prices"
    __table_args__ = (UniqueConstraint("security_id", "date", name="uq_price_security_date"),)

    id: Mapped[str] = uuid_pk()
    security_id: Mapped[str] = mapped_column(ForeignKey("securities.id"), index=True)
    date: Mapped[date] = mapped_column(Date, index=True)
    open: Mapped[Optional[float]] = mapped_column(nullable=True)
    high: Mapped[Optional[float]] = mapped_column(nullable=True)
    low: Mapped[Optional[float]] = mapped_column(nullable=True)
    close: Mapped[float] = mapped_column()
    adjusted_close: Mapped[Optional[float]] = mapped_column(nullable=True)
    volume: Mapped[Optional[float]] = mapped_column(nullable=True)
    currency: Mapped[str] = mapped_column(String(3))
    source_id: Mapped[Optional[str]] = mapped_column(ForeignKey("sources.id"), nullable=True)


class CorporateAction(Base, TimestampMixin):
    __tablename__ = "corporate_actions"

    id: Mapped[str] = uuid_pk()
    security_id: Mapped[str] = mapped_column(ForeignKey("securities.id"), index=True)
    action_type: Mapped[str] = mapped_column(String(24), index=True)
    # SPLIT | REVERSE_SPLIT | SPECIAL_DIVIDEND | MERGER | ACQUISITION | SPINOFF | TICKER_CHANGE | DELISTING
    effective_date: Mapped[date] = mapped_column(Date, index=True)
    ratio: Mapped[Optional[float]] = mapped_column(nullable=True)  # e.g. 2.0 for a 2:1 split
    details: Mapped[Optional[str]] = mapped_column(nullable=True)
    source_id: Mapped[Optional[str]] = mapped_column(ForeignKey("sources.id"), nullable=True)
