"""Proxy-only Alpaca observations. No broker credentials, direct fallback or orders."""
import argparse,json,ssl,urllib.request,urllib.error,urllib.parse
from datetime import datetime,timezone
from decimal import Decimal,InvalidOperation

PROXY_BASE_URL='https://sotality.com'
READ_PATHS={'/v2/account','/v2/positions','/v2/stocks/bars','/v1beta1/options/bars',
            '/v1beta3/crypto/us/latest/quotes'}
LEGACY_HOSTS={'api.alpaca.markets','paper-api.alpaca.markets','data.alpaca.markets'}

class ProxyError(ValueError):
    def __init__(self,reason,http_status=None):
        super().__init__(reason);self.http_status=http_status

def unique_fields(items):
    result={}
    for key,value in items:
        if key in result:raise ProxyError('Duplicate proxy JSON field')
        result[key]=value
    return result

class NoRedirect(urllib.request.HTTPRedirectHandler):
    def redirect_request(self,*args,**kwargs):return None

def proxy_target(value):
    parsed=urllib.parse.urlsplit(value)
    if (parsed.scheme!='https' or parsed.netloc not in LEGACY_HOSTS|{'sotality.com'}
            or parsed.fragment or parsed.path not in READ_PATHS):
        raise ProxyError('Unsupported read-only proxy route')
    if parsed.path in ('/v2/account','/v2/positions') and parsed.query:
        raise ProxyError('Account/position query rejected')
    if len(parsed.query)>4096:raise ProxyError('Proxy query exceeds bounds')
    allowed={'symbols'} if parsed.path.endswith('/latest/quotes') else {'symbols','timeframe','start','end','limit','adjustment','feed','sort','page_token'}
    query=urllib.parse.parse_qs(parsed.query,keep_blank_values=True,strict_parsing=True)
    if set(query)-allowed or any(len(values)!=1 for values in query.values()):
        raise ProxyError('Unknown, duplicate or credential-bearing query field rejected')
    return PROXY_BASE_URL+parsed.path+('?' + parsed.query if parsed.query else '')

def read_proxy_json(url,*,opener=None):
    target=proxy_target(url)
    # No caller headers or API keys are accepted by this interface.
    opener=opener or urllib.request.build_opener(NoRedirect(),
                    urllib.request.HTTPSHandler(context=ssl.create_default_context()))
    request=urllib.request.Request(target,headers={'Accept':'application/json'},method='GET')
    try:
        with opener.open(request,timeout=10) as response:
            if response.status!=200:raise ProxyError('Proxy did not return HTTP 200',response.status)
            if response.headers.get('Content-Type','').split(';')[0].lower()!='application/json':
                raise ProxyError('Proxy returned a non-JSON response',response.status)
            raw=response.read(1000001)
            if len(raw)>1000000:raise ProxyError('Proxy response exceeds limit',response.status)
            try:return json.loads(raw,parse_float=str,object_pairs_hook=unique_fields,
                       parse_constant=lambda _:(_ for _ in ()).throw(ProxyError('Nonfinite proxy JSON')))
            except (ValueError,UnicodeError):raise ProxyError('Malformed proxy JSON',response.status) from None
    except urllib.error.HTTPError as error:
        code=error.code;error.close()
        raise ProxyError('Proxy HTTP response rejected; no redirect or direct fallback',code) from None
    except (urllib.error.URLError,OSError,TimeoutError):
        raise ProxyError('Proxy network unavailable; no direct fallback') from None

def validate_account(account):
    if (not isinstance(account,dict) or not isinstance(account.get('id'),str) or not account['id']
            or not isinstance(account.get('status'),str) or not account['status']
            or type(account.get('trading_blocked')) is not bool):
        raise ProxyError('Complete proxy account response required')
    for name in ('cash','equity','buying_power'):
        try:
            value=Decimal(str(account[name]))
            if not value.is_finite():raise ValueError()
        except (KeyError,ValueError,InvalidOperation):raise ProxyError('Complete finite account values required') from None
    return 'PROXY_ACCOUNT_READ_VALIDATED'

def check_account():
    report={'product':'InFinBot','observed_at':datetime.now(timezone.utc).isoformat(),
            'target':PROXY_BASE_URL+'/v2/account','credential_headers_sent':False,
            'broker_credential_files_read':False,'direct_alpaca_calls':0,'redirects_followed':False,
            'orders_submitted':0,'engine_started':False,'upstream_account_mode':'UNVERIFIED',
            'upstream_token_storage_verified':False}
    try:
        report['status']=validate_account(read_proxy_json(report['target']));report['http_status']=200
    except ProxyError as error:
        report.update(status='PROXY_ACCOUNT_ACCESS_UNVERIFIED',http_status=error.http_status,reason=str(error))
    return report

def main(argv=None):
    parser=argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--base-url',default=PROXY_BASE_URL)
    args=parser.parse_args(argv)
    if args.base_url!=PROXY_BASE_URL:
        print(json.dumps({'status':'PROXY_TARGET_REJECTED','direct_alpaca_calls':0}));return 1
    report=check_account();print(json.dumps(report,indent=2))
    return 0 if report['status']=='PROXY_ACCOUNT_READ_VALIDATED' else 1

if __name__=='__main__':raise SystemExit(main())
