"""Shared fixtures for the eapctf.ctf test suite."""

from __future__ import annotations

import textwrap
from pathlib import Path

import numpy as np
import pandas as pd
import pytest


# ---------------------------------------------------------------------------
# Synthetic CTF data fixtures
# ---------------------------------------------------------------------------


@pytest.fixture
def ctf_weights_df() -> pd.DataFrame:
    """Minimal valid CTF weights DataFrame (id, eom, w)."""
    np.random.seed(0)
    dates = pd.date_range("2020-01-31", periods=24, freq="ME")
    ids = [101, 102, 103, 104]
    rows = []
    for d in dates:
        w = 1.0 / len(ids)
        for i in ids:
            rows.append({"id": i, "eom": d.date().isoformat(), "w": w})
    return pd.DataFrame(rows)


@pytest.fixture
def ctf_daily_ret_df() -> pd.DataFrame:
    """Synthetic daily excess returns for 4 stocks over 2 years."""
    np.random.seed(1)
    ids = [101, 102, 103, 104]
    dates = pd.date_range("2020-02-01", "2022-01-31", freq="B")
    rows = []
    for d in dates:
        for i in ids:
            rows.append({"id": i, "date": d, "ret_exc": np.random.normal(0.0, 0.01)})
    return pd.DataFrame(rows)


@pytest.fixture
def minimal_model_script(tmp_path: Path) -> Path:
    """Write a minimal valid CTF model.py to a temp dir."""
    src = textwrap.dedent("""\
        import numpy as np
        import pandas as pd


        def main(
            chars: pd.DataFrame,
            features: pd.DataFrame,
            daily_ret: pd.DataFrame,
        ) -> pd.DataFrame:
            \"\"\"Equal-weight portfolio.\"\"\"
            np.random.seed(42)
            eom_dates = chars["eom"].drop_duplicates()
            rows = []
            ids = chars["id"].unique()[:4]
            w = 1.0 / len(ids)
            for d in eom_dates:
                for i in ids:
                    rows.append({"id": int(i), "eom": str(pd.Timestamp(d).date()), "w": w})
            return pd.DataFrame(rows)
    """)
    p = tmp_path / "model.py"
    p.write_text(src)
    return p


@pytest.fixture
def minimal_ctf_data_dir(tmp_path: Path) -> Path:
    """Write stub ctff_chars, ctff_features, ctff_daily_ret Parquet files."""
    data_dir = tmp_path / "ctf_data"
    data_dir.mkdir()

    ids = [101, 102, 103, 104]
    dates = pd.date_range("2020-01-31", periods=24, freq="ME")

    # ctff_chars: id, eom, ret_exc_lead1m, ctff_test
    rows = []
    for d in dates:
        for i in ids:
            rows.append({
                "id": i,
                "eom": d.date().isoformat(),
                "ret_exc_lead1m": float(np.random.normal(0.005, 0.02)),
                "ctff_test": d.year >= 2021,
            })
    pd.DataFrame(rows).to_parquet(data_dir / "ctff_chars.parquet", index=False)

    # ctff_features: single column
    pd.DataFrame({"features": ["ret_exc_lead1m"]}).to_parquet(
        data_dir / "ctff_features.parquet", index=False
    )

    # ctff_daily_ret: id, date, ret_exc
    np.random.seed(2)
    daily_rows = []
    for d in pd.date_range("2020-02-01", "2022-01-31", freq="B"):
        for i in ids:
            daily_rows.append({"id": i, "date": d, "ret_exc": float(np.random.normal(0, 0.01))})
    pd.DataFrame(daily_rows).to_parquet(data_dir / "ctff_daily_ret.parquet", index=False)

    return data_dir
