#!/usr/bin/env python3
"""Current Foundry pool hashrate, split by region, for the status performance modal.

As of the 2026-08-01 worker cutover the fleet reports into TWO regional
sub-accounts — marangonnd001 (ND: Dan/Nate/Stout/GN/Will/WW) and marangontx001
(TX: Butz/Ellyson/Walker/Fortson/John/Osprey) — instead of one sub-account per
site. Region membership is NOT hardcoded here; the frontend attributes our own
hashrate using each site's `worker_name1` from master_config, so a site moving
regions is a config edit.

The pre-cutover per-site sub-accounts are kept in LEGACY_ACCOUNTS: a handful of
stubborn miners never took the new pool config and still hash into them, so
they're summed into one "Other Subaccounts" figure that should trend to zero.

Uses each sub-account's live 5-minute average (`hashrate5minAvg` from
/subaccount_stats) so pool numbers track the live status graph in real time.
The /subaccount_hashrate_hour source lagged wakes/sleeps by up to an hour, and
the grouped /current_subaccount_hashrate endpoint is internal-only (403s
customer keys). Foundry hashrate fields are GH/s -> divide by 1e6 for PH/s.

API keys are read from /opt/ngon/config/reporting_config.json (the Report
Builder's Foundry block) rather than duplicated here — one place to rotate.
That file is ngon:ngon 660 and www-data is in the ngon group.
"""

import json
import requests
from concurrent.futures import ThreadPoolExecutor

print("Content-Type: application/json\n")

REPORTING_CONFIG = "/opt/ngon/config/reporting_config.json"

# Post-cutover regional sub-accounts — every miner should be reporting here.
REGIONAL_ACCOUNTS = [
    {"name": "marangonnd001", "region": "ND"},
    {"name": "marangontx001", "region": "TX"},
]

# Pre-cutover per-site sub-accounts. "label" is the site they used to serve —
# it's how an operator knows where to chase a straggler that's still hashing here.
LEGACY_ACCOUNTS = [
    {"name": "maratxngonalpha001", "label": "Butz"},
    {"name": "maratxngonhm002", "label": "Fortson"},
    {"name": "maratxngonjohn001", "label": "John"},
    {"name": "maratxngonosprey001", "label": "Osprey"},
    {"name": "maratxngonew001", "label": "EW"},
    {"name": "marandngondanielle001", "label": "Dan"},
    {"name": "marandngonnate001", "label": "Nate"},
    {"name": "maratxngongn001", "label": "GN"},
    {"name": "maratxngonwill001", "label": "Will"},
]

# Live per-subaccount stats (~400 bytes). hashrate5minAvg is the real-time value.
STATS_ENDPOINT = "{base}/subaccount_stats/{name}"


def load_foundry_config():
    """Base URL + {subaccount: api_key} from the Report Builder config."""
    with open(REPORTING_CONFIG) as f:
        foundry = json.load(f).get("foundry", {})
    return (foundry.get("base_url") or "https://api.foundryusapool.com",
            foundry.get("api_keys") or {})


def fetch_stats(account, base_url, api_keys):
    """Live stats for one sub-account.

    Returns the account dict enriched with ph / workers / offline_15m / ok, with
    ok=False on failure (or a missing key) so one dead sub-account doesn't take
    down the response. Foundry hashrate is GH/s -> /1e6 = PH/s.
    """
    out = dict(account, ph=0.0, workers=0, offline_15m=0, last_share=None, ok=False)
    api_key = api_keys.get(account['name'])
    if not api_key:
        return out
    url = STATS_ENDPOINT.format(base=base_url, name=account['name'])
    try:
        response = requests.get(url, headers={"X-API-KEY": api_key,
                                              "User-Agent": "ngon-status"}, timeout=15)
        response.raise_for_status()
        stats = response.json()
        out.update({
            'ph': (stats.get('hashrate5minAvg', 0) or 0) / 1000000.0,
            'workers': stats.get('activeWorkers', 0) or 0,
            'offline_15m': stats.get('offline15MinWorkerCount', 0) or 0,
            'last_share': stats.get('lastShareTime'),
            'ok': True,
        })
    except requests.exceptions.RequestException:
        pass
    return out


def run_pool_data():
    """Fetch every sub-account in parallel, split into regional + legacy."""
    base_url, api_keys = load_foundry_config()
    accounts = REGIONAL_ACCOUNTS + LEGACY_ACCOUNTS
    with ThreadPoolExecutor(max_workers=len(accounts)) as executor:
        results = list(executor.map(lambda a: fetch_stats(a, base_url, api_keys), accounts))

    regions = [r for r in results if 'region' in r]
    legacy = [r for r in results if 'label' in r]
    # Only surface legacy subs that are still doing something — the rest are
    # retired and would just be a wall of zeros.
    stragglers = sorted([r for r in legacy if r['ph'] > 0 or r['workers'] > 0],
                        key=lambda r: r['ph'], reverse=True)

    return {
        'regions': regions,
        'legacy': {
            'ph': sum(r['ph'] for r in legacy),
            'workers': sum(r['workers'] for r in legacy),
            'accounts': stragglers,
        },
    }


try:
    result = {'success': True}
    result.update(run_pool_data())
except Exception as e:
    result = {
        'success': False,
        'error': str(e)
    }

print(json.dumps(result))
