"""Match reported fiscal periods to SEC acceptance dates before using fundamentals in research.

Research example. Live observations can change.
"""

from datetime import UTC, datetime
from textwrap import fill

import matplotlib.pyplot as plt
import pandas as pd

AS_OF = datetime.now(UTC).date()
NAVY, BLUE, PINK = "#132244", "#8fb9ff", "#e7a2cc"


def fetch(qj):
    return {
        "income": qj.fmp.get_income_statement(symbol="AAPL", period="annual", limit=5),
        "filings": qj.sec.get_company_filings(symbol="AAPL", form_type="10-K", limit=12),
    }


def analyze(raw):
    joined = verified_income(raw)
    if joined.empty:
        raise ValueError("No matching fiscal periods and SEC filings")
    joined["days_to_filing"] = (joined["accepted"] - joined["date"]).dt.total_seconds() / 86400
    joined["period"] = joined["date"].dt.strftime("%Y-%m-%d")
    fig, (ax,) = canvas("AAPL · the reporting clock", "Calendar days to SEC acceptance")
    ax.bar(joined["period"], joined["days_to_filing"], color=BLUE, width=0.6)
    ax.set_xlabel("Fiscal period end · FMP, matched to SEC report date")
    table = joined[["period", "accepted", "days_to_filing"]]
    return table, fig


def payload(response):
    if hasattr(response, "to_dict"):
        response = response.to_dict()
    while isinstance(response, dict):
        if response.get("error") or response.get("error_code") or response.get("success") is False:
            raise ValueError("Provider request failed")
        if "data" in response:
            response = response["data"]
        elif "value" in response:
            response = response["value"]
        else:
            break
    return response


def frame(response, date="date"):
    rows = payload(response)
    if not isinstance(rows, list) or not rows:
        raise ValueError("No provider observations returned")
    result = pd.DataFrame(rows)
    if date:
        result[date] = pd.to_datetime(result[date], utc=True)
        result = result.sort_values(date)
    return result


def verified_income(raw):
    income = frame(raw["income"])
    filings = frame(raw["filings"], "reportDate")
    filings = filings[["reportDate", "acceptanceDateTime", "filingDate"]].copy()
    filings["accepted"] = pd.to_datetime(filings["acceptanceDateTime"], utc=True)
    return income.merge(
        filings[["reportDate", "accepted"]],
        left_on="date",
        right_on="reportDate",
        validate="one_to_one",
    ).sort_values("date")


def canvas(title, ylabel, panels=1):
    plt.rcParams.update(
        {
            "figure.facecolor": NAVY,
            "axes.facecolor": NAVY,
            "savefig.facecolor": NAVY,
            "text.color": "#e9eef8",
            "axes.labelcolor": "#afc1dc",
            "xtick.color": "#afc1dc",
            "ytick.color": "#afc1dc",
            "axes.edgecolor": "#34486b",
            "grid.color": "#34486b",
            "font.size": 10,
            "axes.prop_cycle": plt.cycler(color=[BLUE, PINK, "#ba9dea"]),
        }
    )
    fig, axes = plt.subplots(panels, 1, figsize=(9, 6.1), squeeze=False, layout="constrained")
    fig.suptitle(fill(title, width=58), fontsize=17, x=0.04, ha="left", weight="medium")
    for ax in axes.flat:
        ax.grid(axis="y", alpha=0.45)
        ax.set_axisbelow(True)
        ax.spines[["top", "right"]].set_visible(False)
    axes.flat[0].set_ylabel(ylabel)
    return fig, list(axes.flat)


def run():
    from quantjourney.sdk import QuantJourneyAPI

    qj = QuantJourneyAPI.from_env()
    raw = fetch(qj)
    table, fig = analyze(raw)
    print(table.to_string(index=False))
    fig.savefig(OUTPUT, dpi=180)
    plt.show()


OUTPUT = "sdk_reporting_dates.png"

if __name__ == "__main__":
    run()
