from __future__ import annotations

from pathlib import Path

import pandas as pd

from psx_signal.data.schema import CONSTITUENT_COLUMNS, CORPORATE_ACTION_COLUMNS


def read_constituents(path: str | Path) -> pd.DataFrame:
    frame = pd.read_csv(path)
    missing = set(CONSTITUENT_COLUMNS[:3]) - set(frame.columns)
    if missing:
        raise ValueError(f"Missing constituent columns: {', '.join(sorted(missing))}")
    frame["effective_date"] = pd.to_datetime(frame["effective_date"], errors="raise").dt.normalize()
    frame["symbol"] = frame["symbol"].astype("string").str.strip().str.upper()
    frame["index"] = frame["index"].astype("string").str.strip().str.upper()
    if "source_reference" not in frame:
        frame["source_reference"] = Path(path).name
    return frame[list(CONSTITUENT_COLUMNS)].drop_duplicates(["effective_date", "symbol", "index"])


def read_corporate_actions(path: str | Path) -> pd.DataFrame:
    frame = pd.read_csv(path)
    missing = {"symbol", "action_date", "action_type", "source", "source_reference"} - set(frame.columns)
    if missing:
        raise ValueError(f"Missing corporate-action columns: {', '.join(sorted(missing))}")
    frame["symbol"] = frame["symbol"].astype("string").str.strip().str.upper()
    frame["action_date"] = pd.to_datetime(frame["action_date"], errors="raise").dt.normalize()
    for column in ("ratio", "cash_amount"):
        if column not in frame:
            frame[column] = pd.NA
        frame[column] = pd.to_numeric(frame[column], errors="coerce")
    if "provider" not in frame:
        frame["provider"] = frame["source"].astype("string").str.lower()
    if "provider_trust" not in frame:
        frame["provider_trust"] = pd.NA
    return frame[list(CORPORATE_ACTION_COLUMNS)].drop_duplicates(
        ["symbol", "action_date", "action_type", "source_reference"]
    )
