"""near-close schedule cutover + paper trade fill_mode era tag

Revision ID: 023
Revises: 022
Create Date: 2026-07-18 00:00:00.000000

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa


revision: str = "023"
down_revision: Union[str, None] = "022"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None

# Deliberate schedule rewrite (not a soft defaults refresh). Old stored values
# are logged then replaced so prod does not keep scanning at 07:00 Berlin.
_SCHEDULE_REWRITE: dict[str, str] = {
    "schedule_timezone": "America/New_York",
    "schedule_daily_pipeline_cron": "0 2 * * *",
    "schedule_near_close_pipeline_cron": "30 15 * * 1-5",
    "schedule_after_close_pipeline_cron": "45 16 * * 1-5",
    "schedule_intraday_pipeline_cron": "0 10-15 * * 1-5",
    "schedule_fundamentals_cron": "0 1 * * 1",
}


def upgrade() -> None:
    op.add_column(
        "paper_trades",
        sa.Column("fill_mode", sa.String(length=20), nullable=True),
    )

    conn = op.get_bind()
    settings = sa.table(
        "system_settings",
        sa.column("id", sa.Integer),
        sa.column("key", sa.String),
        sa.column("value", sa.Text),
        sa.column("updated_at", sa.DateTime(timezone=True)),
    )
    now = sa.func.now()

    for key, new_value in _SCHEDULE_REWRITE.items():
        row = conn.execute(
            sa.select(settings.c.value).where(settings.c.key == key)
        ).fetchone()
        old_value = row[0] if row is not None else None
        # Always log so ops can recover the pre-cutover schedule from migration output.
        print(
            f"schedule_cutover {key}: {old_value!r} -> {new_value!r}",
            flush=True,
        )
        if row is None:
            conn.execute(
                sa.insert(settings).values(
                    key=key, value=new_value, updated_at=now
                )
            )
        else:
            conn.execute(
                sa.update(settings)
                .where(settings.c.key == key)
                .values(value=new_value, updated_at=now)
            )


def downgrade() -> None:
    op.drop_column("paper_trades", "fill_mode")
    # Do not restore old crons — unknown prior values; leave stored schedule as-is.
