#!/usr/bin/env python3
"""Build 1-minute bid/ask bars from whatever Dukascopy hours are cached. Standard library only.

Usage:
    python3 bars.py XAUUSD 2026-01-01 2026-08-31

Writes ~/data/bars/<INST>_m1.csv with columns:
    minute (ISO 8601, UTC), bid_open, bid_high, bid_low, bid_close,
    ask_open, ask_high, ask_low, ask_close, ticks
Minutes without ticks are absent. Hours not yet cached are skipped and counted, so the
output is honest about coverage: check the printed "hours missing" before trusting a result.
"""
import os
import sys
from datetime import date, datetime, timezone

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from fetch import DATA, days, decode_hour, hour_path  # noqa: E402


def main():
    inst, start, end = sys.argv[1], date.fromisoformat(sys.argv[2]), date.fromisoformat(sys.argv[3])
    out_dir = os.path.join(DATA, "bars")
    os.makedirs(out_dir, exist_ok=True)
    out = os.path.join(out_dir, f"{inst}_m1.csv")
    n_bars = n_ticks = missing = present = 0
    with open(out, "w") as f:
        f.write("minute,bid_open,bid_high,bid_low,bid_close,ask_open,ask_high,ask_low,ask_close,ticks\n")
        for d in days(start, end):
            for h in range(24):
                p = hour_path(inst, d, h)
                if not os.path.exists(p):
                    if d.weekday() != 5:
                        missing += 1
                    continue
                present += 1
                cur, bar = None, None
                for ms, bid, ask in decode_hour(p, inst, d, h):
                    n_ticks += 1
                    m = ms // 60000
                    if m != cur:
                        if bar:
                            f.write(",".join([datetime.fromtimestamp(cur * 60, tz=timezone.utc).isoformat()]
                                             + [f"{x:.3f}" for x in bar[:8]] + [str(bar[8])]) + "\n")
                            n_bars += 1
                        cur, bar = m, [bid, bid, bid, bid, ask, ask, ask, ask, 0]
                    if bid > bar[1]: bar[1] = bid
                    if bid < bar[2]: bar[2] = bid
                    bar[3] = bid
                    if ask > bar[5]: bar[5] = ask
                    if ask < bar[6]: bar[6] = ask
                    bar[7] = ask
                    bar[8] += 1
                if bar:
                    f.write(",".join([datetime.fromtimestamp(cur * 60, tz=timezone.utc).isoformat()]
                                     + [f"{x:.3f}" for x in bar[:8]] + [str(bar[8])]) + "\n")
                    n_bars += 1
    print(f"{present} hours cached, {missing} non-Saturday hours missing; {n_ticks} ticks -> {n_bars} bars in {out}")


if __name__ == "__main__":
    main()
