#!/usr/bin/env python3
"""Reproduce September 2026 OPA chart arithmetic from the companion CSV.

Standard library only: python3 reproduce.py crack.csv (or ttf.csv / diesel.csv).
Writes a calculated CSV alongside the input. Does not call the API.
"""
import csv
import datetime
import math
import pathlib
import sys


def calculate(path):
    kind = path.stem
    if kind not in ('crack', 'ttf', 'diesel'):
        raise ValueError('Use crack.csv, ttf.csv or diesel.csv from the article')
    columns = ['crude_usd_bbl', 'product_usd_bbl', 'spread_usd_bbl'] if kind == 'crack' else ['price']
    with path.open(newline='') as handle:
        reader = csv.DictReader(handle)
        if reader.fieldnames != ['date', *columns]:
            raise ValueError('Unexpected CSV columns')
        rows = list(reader)
    if not rows:
        raise ValueError('No observations: calculation stopped')
    seen = set()
    results = []
    for row in rows:
        if None in row or any(value is None or not value.strip() for value in row.values()):
            raise ValueError('Malformed CSV row')
        date = datetime.date.fromisoformat(row['date'])
        if not datetime.date(2026, 6, 1) <= date <= datetime.date(2026, 9, 11):
            raise ValueError('Observation outside the published snapshot window')
        if date in seen:
            raise ValueError('Duplicate observation date')
        seen.add(date)
        values = {column: float(row[column]) for column in columns}
        if not all(math.isfinite(value) for value in values.values()):
            raise ValueError('Nonfinite input: calculation stopped')
        if kind != 'crack' and values['price'] < 0:
            raise ValueError('Negative price is invalid for this snapshot')
        if kind == 'crack':
            calculated = values['product_usd_bbl'] - values['crude_usd_bbl']
            if abs(calculated - values['spread_usd_bbl']) > 0.011:
                raise ValueError('Component arithmetic disagrees with reported spread')
            result = {'date': date.isoformat(), 'spread_usd_bbl': values['spread_usd_bbl']}
        elif kind == 'diesel':
            result = {'date': date.isoformat(), 'diesel_usd_gal': values['price'],
                      'illustrative_surcharge_usd_1000_miles': round(max(0, values['price'] - 1.25) / 6 * 1000, 2)}
        else:
            result = {'date': date.isoformat(), 'ttf_eur_mwh': values['price']}
        if not all(math.isfinite(value) for column, value in result.items() if column != 'date'):
            raise ValueError('Nonfinite calculated result')
        results.append(result)
    return sorted(results, key=lambda row: row['date'])


def main():
    try:
        if len(sys.argv) != 2:
            raise ValueError('Usage: python3 reproduce.py crack.csv|ttf.csv|diesel.csv')
        path = pathlib.Path(sys.argv[1])
        rows = calculate(path)
        output = path.with_name(path.stem + '-calculated.csv')
        with output.open('w', newline='') as handle:
            writer = csv.DictWriter(handle, fieldnames=rows[0])
            writer.writeheader()
            writer.writerows(rows)
        print(f'{len(rows)} observations checked; wrote {output}')
        print('First:', rows[0])
        print('Last: ', rows[-1])
    except (ValueError, KeyError, TypeError, OSError) as error:
        print(f'Cannot reproduce: {error}', file=sys.stderr)
        return 1
    return 0


if __name__ == '__main__':
    sys.exit(main())
