"""Build SATIRE-S TSI reconstruction charts.

Source: Max Planck Institute for Solar System Research (MPS)
Version: 20260521
File: SATIRE-S_TSI_latest.txt
DOI: 10.1051/0004-6361/202554044 (Chatzistergos et al. 2025)
Attribution: MPS; Chatzistergos, Krivova, Solanki, Yeo

Columns (space-separated, header lines prefixed by ';'):
  0: Date in Julian day
  1: Reconstructed TSI (W m^-2)
  2: Lower uncertainty bound
  3: Upper uncertainty bound
  4: Source indicator (0=activity indices ... 8=SDO/HMI)
We plot the reconstructed TSI (index 1) as the primary series.
"""
from pathlib import Path

import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import pandas as pd


BASE_DIR = Path(__file__).parent
INPUT_FILE = (BASE_DIR / "tsi_raw" / "satire_s" / "raw"
              / "SATIRE-S_TSI_latest.txt")
OUT_DIR = BASE_DIR / "tsi_satellite_sources"
OUT_PNG = OUT_DIR / "satire_s_tsi_daily_monthly_annual.png"
OUT_CSV = OUT_DIR / "satire_s_tsi_daily.csv"
OUT_MANIFEST = OUT_DIR / "satire_s_tsi_manifest.txt"


def load_daily() -> pd.DataFrame:
    """Parse SATIRE-S file using Julian Dates."""
    df = pd.read_csv(INPUT_FILE, sep="\\s+", comment=";", header=None,
                     names=["jd", "tsi", "tsi_lower", "tsi_upper", "source"])

    # Integer Julian Days mark noon, so floor to the civil date of that noon.
    df["date"] = pd.to_datetime(df["jd"], unit="D", origin="julian").dt.floor("D")

    df = df[df["tsi"] > 1300].copy()
    return df[["date", "tsi", "tsi_lower", "tsi_upper", "source"]].sort_values("date")


def build_chart(frame: pd.DataFrame) -> None:
    monthly = frame.set_index("date")["tsi"].resample("MS").mean().reset_index(name="tsi")
    annual  = frame.set_index("date")["tsi"].resample("YS").mean().reset_index(name="tsi")
    annual["plot_date"] = annual["date"] + pd.offsets.Day(181)

    plt.style.use("seaborn-v0_8-whitegrid")
    fig, ax = plt.subplots(figsize=(12.5, 6.8), dpi=170)

    ax.scatter(frame["date"], frame["tsi"], s=8, color="#fcd34d",
               alpha=0.4, edgecolors="none", label="Daily reconstruction")
    ax.plot(monthly["date"], monthly["tsi"], color="#f59e0b", linewidth=1.6,
            label="Monthly means")
    ax.plot(annual["plot_date"], annual["tsi"], color="#b45309", linewidth=2.2,
            marker="o", markersize=3.2, label="Annual means")

    ax.set_title(
        "SATIRE-S TSI Reconstruction (latest, 20260521)\n"
        "MPS \u00b7 Spectral And Total Irradiance REconstruction (Satellite era)",
        fontsize=14, pad=14)
    ax.set_ylabel("Total Solar Irradiance (W m^-2)")
    ax.set_xlabel("Year")
    ax.xaxis.set_major_locator(mdates.YearLocator(4))
    ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y"))
    plt.setp(ax.get_xticklabels(), rotation=45, ha="right", fontsize=8.5)
    ax.set_xlim(frame["date"].min(), frame["date"].max())
    ax.legend(loc="upper left", frameon=True)

    note = (
        "Source: SATIRE-S_TSI_latest.txt (version 20260521)\n"
        "MPS \u00b7 Semi-empirical reconstruction from solar surface magnetism\n"
        "Plotted series: reconstructed TSI (lower/upper bounds retained in CSV)\n"
        "Ref: Chatzistergos et al. (2025), DOI 10.1051/0004-6361/202554044\n"
        "Attribution: MPS; Chatzistergos, Krivova, Solanki, Yeo"
    )
    ax.text(0.015, 0.03, note, transform=ax.transAxes, fontsize=7.8,
            bbox=dict(boxstyle="round,pad=0.35", facecolor="white", edgecolor="#cbd5e1", alpha=0.96))

    fig.tight_layout()
    fig.savefig(OUT_PNG, bbox_inches="tight")
    plt.close(fig)


def write_outputs(frame: pd.DataFrame) -> None:
    OUT_DIR.mkdir(parents=True, exist_ok=True)
    out = frame.copy()
    out["date"] = out["date"].dt.strftime("%Y-%m-%d")
    out.to_csv(OUT_CSV, index=False)

    lines = [
        "SATIRE-S TSI reconstruction manifest",
        "",
        "Dataset: SATIRE-S total solar irradiance reconstruction",
        "Provider: Max Planck Institute for Solar System Research (MPS)",
        "Source: MPS sun-climate data archive (HTTP)",
        f"Raw file: {INPUT_FILE.relative_to(BASE_DIR)}",
        "Version/Date: 20260521",
        "",
        "Plotted series: reconstructed TSI (Column 2)",
        "Also in CSV: lower bound (Column 3), upper bound (Column 4), source indicator (Column 5)",
        "",
        f"Date span: {frame['date'].min().date()} to {frame['date'].max().date()}",
        f"Daily rows: {len(frame)}",
        f"TSI range: {frame['tsi'].min():.4f} to {frame['tsi'].max():.4f} W m^-2",
        "",
        "Method: Semi-empirical reconstruction from solar surface magnetism",
        "Reference: Chatzistergos et al. (2025), DOI: 10.1051/0004-6361/202554044",
        "Attribution: MPS; Chatzistergos, Krivova, Solanki, Yeo",
    ]
    OUT_MANIFEST.write_text("\n".join(lines) + "\n")


def main() -> None:
    if not INPUT_FILE.exists():
        raise FileNotFoundError(f"Missing input: {INPUT_FILE}")
    OUT_DIR.mkdir(parents=True, exist_ok=True)
    frame = load_daily()
    build_chart(frame)
    write_outputs(frame)
    print(f"saved {OUT_PNG.name} ({len(frame)} rows)")


if __name__ == "__main__":
    main()
