"""Read AccountSummary with bounded retries for explicit throttling only.

Set MRPC_API_KEY and MRPC_TERMINAL_ID. No connection or trading methods are called.
Transport timeouts are raised to the caller; this is not an order retry wrapper.
"""
import email.utils
import json
import math
import os
import random
import time
import urllib.error
import urllib.request


def retry_seconds(error):
    properties={p.get('errorArgKey'):p.get('errorArgValue') for p in error.get('properties',[])}
    seconds=float(properties['RetryAfterSeconds'])
    if not math.isfinite(seconds) or seconds<0:
        raise ValueError('Invalid RetryAfterSeconds')
    return seconds


def read_account(api_key, terminal_id, attempts=3, send=urllib.request.urlopen, sleep=time.sleep):
    for attempt in range(attempts):
        request=urllib.request.Request('https://mt5.mrpc.pro/AccountSummary',
            headers={'APIKey':api_key,'id':terminal_id,'Accept':'application/json'})
        try:
            with send(request,timeout=30) as response:
                body=json.load(response)
        except urllib.error.HTTPError as exc:
            if exc.code!=429 or not exc.headers.get('Retry-After'):
                raise
            value=exc.headers['Retry-After']
            try:
                delay=float(value)
            except ValueError:
                delay=max(0,email.utils.parsedate_to_datetime(value).timestamp()-time.time())
        else:
            error=body.get('error')
            if error is None:
                if not isinstance(body.get('data'),dict):
                    raise ValueError('AccountSummary returned no account data')
                return body['data']
            if error.get('errorCode') not in {'TERMINAL_RATE_LIMIT_EXCEEDED','TERMINAL_BUSY'}:
                raise RuntimeError(error.get('errorCode','API_ERROR')+': '+error.get('errorMessage',''))
            delay=retry_seconds(error)
        if not math.isfinite(delay) or delay<0 or delay>120:
            raise RuntimeError('Retry delay requires operator review; no early retry sent')
        if attempt+1==attempts:
            break
        sleep(delay+random.uniform(.25,.75))
    raise RuntimeError('Read retry budget exhausted')


if __name__=='__main__':
    account=read_account(os.environ['MRPC_API_KEY'],os.environ['MRPC_TERMINAL_ID'])
    print(json.dumps({key:account.get(key) for key in ['accountCurrency','accountBalance','accountEquity']},indent=2))
