"""Prove the key, then land a sheet of stock as one sync. Python 3.10+, standard library only.

    FREEPORT_KEY=fp_test_... python sync-sheet.py stock-sheet-template.csv
"""

import csv
import json
import os
import sys
import time
import urllib.error
import urllib.request

BASE = os.environ.get("FREEPORT_API", "https://sandbox-api.freeport.gg/v1")
KEY = os.environ.get("FREEPORT_KEY") or sys.exit("set FREEPORT_KEY to your fp_test_ or fp_live_ key")
SHEET = sys.argv[1] if len(sys.argv) > 1 else "stock-sheet-template.csv"
NUMBERS = {"price_per_qty", "min_qty", "max_qty", "stock_qty", "low_stock_alert_qty", "delivery_eta_minutes"}


def api(method, path, body=None, headers=None):
    data = None if body is None else json.dumps(body).encode()
    request = urllib.request.Request(BASE + path, data=data, method=method)
    request.add_header("Authorization", f"Bearer {KEY}")
    request.add_header("Content-Type", "application/json")
    for name, value in (headers or {}).items():
        request.add_header(name, value)
    try:
        with urllib.request.urlopen(request, timeout=30) as response:
            return json.load(response)
    except urllib.error.HTTPError as error:
        problem = json.load(error).get("error", {})
        sys.exit(f"{method} {path}: {problem.get('code')} {problem.get('message')}")


# 1. Who am I?
print(api("GET", "/ping"))

# 2. The sheet, one line per row. Tiers are "min_qty:price;min_qty:price".
lines = []
with open(SHEET, newline="", encoding="utf-8") as handle:
    for row in csv.DictReader(handle):
        line = {k: (int(v) if k in NUMBERS else v) for k, v in row.items() if v and k != "tiers"}
        if row.get("tiers"):
            line["tiers"] = [
                {"min_qty": int(qty), "price": price}
                for qty, price in (rung.split(":") for rung in row["tiers"].split(";"))
            ]
        lines.append(line)

# 3. Open, stage (up to a thousand a call), commit with an idempotency key.
sync = api("POST", "/stock/syncs", {"mode": "replace"})
for start in range(0, len(lines), 1000):
    staged = api("PUT", f"/stock/syncs/{sync['id']}/lines", {"lines": lines[start : start + 1000]})
    refused = [r for r in staged["results"] if r["status"] != "staged"]
    print(f"staged {len(staged['results']) - len(refused)}, refused {len(refused)}")
api("POST", f"/stock/syncs/{sync['id']}/commit", headers={"Idempotency-Key": f"commit-{sync['id']}"})

# 4. The worker applies it; poll the sync, not the listings.
while True:
    state = api("GET", f"/stock/syncs/{sync['id']}")
    if state["status"] != "committing":
        print(state.get("summary"))
        break
    time.sleep(1)

# 5. Any line that failed says why.
for line in api("GET", f"/stock/syncs/{sync['id']}/lines?action=failed")["data"]:
    print(line["external_id"], line["error"])
