"""Datos sintéticos para las pruebas: nunca se lee data/.

Reproducen el formato de los cinco archivos reales (CSV de la H.10 con CRLF y cabecera de seis
filas, CSV SDMX del BCE y tablas HTML por año del FOMC) con series inventadas y una semilla fija.
"""

from __future__ import annotations

import hashlib
import random
from collections.abc import Sequence
from datetime import date, timedelta
from pathlib import Path

CANONICAL = (
    "01-h10-daily-rates.csv",
    "02-h10-hist-euro.htm",
    "03-fomc-openmarket.htm",
    "04-fomc-openmarket-archive.htm",
    "05-ecb-dfr.csv",
)
ANNEX = "anexo-datos-2026-10-22.md"
ANNEX_TEXT = "# Anexo de datos sintético (solo para las pruebas)\n"
PINS: dict[str, dict[str, str]] = {}  # huellas de cada directorio al crearlo, antes de alterarlo


def weekdays(start: date, end: date) -> list[date]:
    days, current = [], start
    while current <= end:
        if current.weekday() < 5:
            days.append(current)
        current += timedelta(days=1)
    return days


def h10_text(rows: list[tuple[str, str]]) -> str:
    """CSV de la H.10 con cabecera de seis filas; la columna del euro es la tercera de cuatro."""
    header = [
        '"Series Description","Australian Dollar","Euro-Area Euro","New Zealand Dollar"',
        '"Unit:","Currency","Currency","Currency"',
        '"Multiplier:","1","1","1"',
        '"Currency:","AUD","EUR","NZD"',
        '"Unique Identifier: ","H10/H10/RXI$US_N.B.AL","H10/H10/RXI$US_N.B.EU","H10/H10/X"',
        '"Time Period","RXI$US_N.B.AL","RXI$US_N.B.EU","RXI$US_N.B.NZ"',
    ]
    body = [f"{day},0.5,{value},0.7" for day, value in rows]
    return "\r\n".join(header + body)


def ecb_text(observations: list[tuple[str, str]]) -> str:
    header = "KEY,FREQ,TIME_PERIOD,OBS_VALUE,OBS_STATUS"
    body = [f"FM.B.U2.EUR.4F.KR.DFR.LEV,B,{day},{value},A" for day, value in observations]
    return "\r\n".join([header, *body]) + "\r\n"


def fomc_html(tables: dict[int, list[tuple[str, str]]], footnotes: Sequence[str] = ()) -> str:
    """Página con un encabezado de año y una tabla por año; filas (fecha, nivel).

    La celda de fecha puede llevar HTML (por ejemplo un enlace de nota al pie) y `footnotes` son
    los párrafos de nota que van al final de la página.
    """
    parts = ["<html><body><h3>Open Market Operations</h3>"]
    for year, rows in tables.items():
        parts.append(f"<h4>{year}</h4><div><table><thead><tr>")
        parts.append("<th>Date</th><th>Increase</th><th>Decrease</th><th>Level (%)</th>")
        parts.append("</tr></thead><tbody>")
        for day, level in rows:
            parts.append(f"<tr><td>{day}</td><td>25</td><td>...</td><td>{level}</td></tr>")
        parts.append("</tbody></table></div>")
    for note in footnotes:
        parts.append(f'<p class="footnotes2">{note} <a href="#fnr2">Return to Text</a></p>')
    parts.append("</body></html>")
    return "\n".join(parts)


ECB_OBSERVATIONS = [
    ("1999-01-01", "2"),
    ("1999-01-04", "2.75"),
    ("2000-11-06", "3.75"),
    ("2003-06-06", "1"),
    ("2011-04-13", "1.25"),
    ("2014-06-11", "-0.1"),
    ("2022-07-27", "0"),
    ("2023-09-20", "4"),
    ("2025-06-11", "2"),
]
FOMC_ARCHIVE = {
    2002: [("November 6", "1.25")],
    1994: [("February 4", "3.25")],
    1992: [("September 4", "3.00")],
    1990: [("July 13", "8.00")],
}
STAR_DATE = 'March 4<a href="#fn2" id="fnr2" name="fnr2">*</a>'
STAR_NOTE = "* On July 10, 2024, this date was corrected from March 3, 2020, to March 4, 2020."
FOMC_CURRENT = {
    2026: [("September 17", "3.75-4.00")],
    2020: [("March 16", "0-0.25"), (STAR_DATE, "1.00-1.25")],
    2018: [("December 19", "2.25-2.50")],
    2015: [("December 16", "0.25-0.50")],
    2008: [("December 16", "0-0.25"), ("October 29", "1.00")],
    2004: [("June 30", "1.25")],
    2003: [("June 25", "1.00")],
}


def make_data_dir(path: Path, seed: int = 7, flat: bool = False) -> Path:
    """Escribe los cinco archivos sintéticos, un anexo sintético y su SHA256SUMS en path.

    Con flat=True el precio es constante y no hay días ND: ninguna variante tiene posición.
    Las huellas de los seis archivos quedan en PINS[str(path)]: son las que run_study recibiría
    como `pinned`, calculadas antes de que una prueba altere nada.
    """
    rng = random.Random(seed)
    days = weekdays(date(1999, 1, 4), date(2026, 9, 30))
    price, rows = 1.1, []
    for day in days:
        price *= 1.0 + rng.gauss(0.0, 0.006)
        if flat:
            rows.append((day.isoformat(), "1.0000"))
        else:
            rows.append((day.isoformat(), "ND" if rng.random() < 0.04 else f"{price:.4f}"))
    files = {
        "01-h10-daily-rates.csv": h10_text(rows),
        "02-h10-hist-euro.htm": "<html><body>placeholder de control</body></html>\n",
        "03-fomc-openmarket.htm": fomc_html(FOMC_CURRENT, [STAR_NOTE]),
        "04-fomc-openmarket-archive.htm": fomc_html(FOMC_ARCHIVE),
        "05-ecb-dfr.csv": ecb_text(ECB_OBSERVATIONS),
    }
    path.mkdir(parents=True, exist_ok=True)
    sums = []
    for name in CANONICAL:
        data = files[name].encode("utf-8")
        (path / name).write_bytes(data)
        sums.append(f"{hashlib.sha256(data).hexdigest()}  {name}\n")
    (path / "SHA256SUMS").write_text("".join(sums), encoding="ascii")
    (path / ANNEX).write_bytes(ANNEX_TEXT.encode("utf-8"))
    PINS[str(path)] = pins_of(path)
    return path


def pins_of(path: Path) -> dict[str, str]:
    """sha256 de los cinco archivos y del anexo tal como están ahora en path."""
    return {
        name: hashlib.sha256((path / name).read_bytes()).hexdigest() for name in (*CANONICAL, ANNEX)
    }
