"""Read-only old/new Alpaca authentication check. No asserted revocation from mocks or wrong endpoints."""
import json,re,ssl,urllib.request,urllib.error
from infinbot_common import private_read,strict_json,Rejected,timestamp
from verify_live_feeds_standalone import load_private_credentials

ENDPOINTS={'paper':'https://paper-api.alpaca.markets','live':'https://api.alpaca.markets'}

def credentials(path,mode):
    if mode not in ENDPOINTS:raise Rejected('Explicit existing credential account mode required')
    raw=private_read(path,8192)
    if raw.lstrip().startswith(b'{'):
        config=strict_json(raw)
        if not isinstance(config,dict) or set(config)!={'mode','api_key','api_secret'} or config['mode']!=mode:raise Rejected('Explicit broker key-pair JSON/mode required')
        key,secret=config['api_key'],config['api_secret']
    else:
        config=load_private_credentials(path)
        if config.get('ALPACA_BASE_URL')!=ENDPOINTS[mode]:raise Rejected('Exact matching broker endpoint required; no implicit relabeling')
        prefix='ALPACA_PAPER_' if mode=='paper' else 'ALPACA_LIVE_'
        key,secret=config.get(prefix+'KEY'),config.get(prefix+'SECRET')
    for v in (key,secret):
        if not isinstance(v,str) or not re.fullmatch(r'[A-Za-z0-9]{10,128}',v) or any(w in v.lower() for w in ('sample','mock','placeholder','replace_me','your_')):raise Rejected('Real separate Alpaca key ID/secret pair required')
    return {'APCA-API-KEY-ID':key,'APCA-API-SECRET-KEY':secret}

class NoRedirect(urllib.request.HTTPRedirectHandler):
    def redirect_request(self,*args,**kwargs):raise Rejected('Redirect blocked')

def account_status(headers,mode):
    url=ENDPOINTS[mode]+'/v2/account'
    opener=urllib.request.build_opener(urllib.request.ProxyHandler({}),NoRedirect(),urllib.request.HTTPSHandler(context=ssl.create_default_context()))
    try:
        with opener.open(urllib.request.Request(url,headers=headers,method='GET'),timeout=8) as response:
            body=response.read(1024*1024+1)
            payload=strict_json(body)
            valid=isinstance(payload,dict) and isinstance(payload.get('id'),str) and bool(payload['id'])
            return {'http_status':response.status,'account_payload_valid':valid}
    except urllib.error.HTTPError as error:
        code=error.code;error.close();return {'http_status':code,'account_payload_valid':False}

class AlpacaCredentialRotationCheck:
    """New diagnostic component; not the owner's unseen TradingBotEngine."""
    def __init__(self,*,transport=account_status):self.transport=transport;self.current_headers=None
    def run(self,old_file,new_file,mode):
        self.current_headers=None
        result={'product':'InFinBot','observed_at':timestamp(),'status':'BROKER_ROTATION_CHECK_UNVERIFIED',
                'checks':[],'orders_submitted':0,'production_configuration_changed':False,
                'production_engine_binding_verified':False,'global_revocation_verified':False,
                'secret_values_displayed':False,'credentials_read_from_chat':False}
        try:
            old=credentials(old_file,mode);new=credentials(new_file,mode)
            if old==new:raise Rejected('Old/new broker credentials must be distinct')
            observed=self.transport(old,mode);code=observed.get('http_status')
            result['checks'].append({'check':'old_credentials_account_get','endpoint':ENDPOINTS[mode]+'/v2/account',
                                    'http_status':code,'status':'OBSERVED_401_REJECTION' if code==401 else 'BLOCKED'})
            if code!=401:
                result['status']='OLD_CREDENTIALS_STILL_ACCEPTED' if code==200 else 'OLD_CREDENTIAL_REJECTION_UNVERIFIED';return result
            # Require a separately authenticated replacement on exactly the same declared account-mode endpoint.
            observed=self.transport(new,mode);code=observed.get('http_status')
            result['checks'].append({'check':'new_private_credentials_account_get','http_status':code,
                                    'status':'AUTHENTICATED_READ' if code==200 and observed.get('account_payload_valid') is True else 'BLOCKED'})
            if code!=200 or observed.get('account_payload_valid') is not True:return result
            self.current_headers=new
            result.update(status='OLD_401_AND_NEW_AUTHENTICATION_OBSERVED',diagnostic_credential_source='NEW_PRIVATE_FILE_ONLY',
                          scope='Observed rejection of the supplied old pair and successful new account read on the selected endpoint; broker revocation record and production binding remain separate')
        except Exception:result['reason']='Private old/new broker credentials, matching mode or network evidence unavailable; no offline/mock pass and no raw error body displayed'
        return result
