import sys, json, time, re, os
sys.path.insert(0, '/tmp')
from amd_lib import session, call

IDS = json.load(open('/tmp/s2_ids.json'))
OUT = '/tmp/s2_contacts.json'
contacts = {}
if os.path.exists(OUT):
    try: contacts = json.load(open(OUT))
    except: contacts = {}

def extract(raw):
    m = re.search(r'<contactinfo\b([^>]*?)/?>', raw)
    if not m: return {'phone':'', 'email':''}
    seg = m.group(1)
    def g(a):
        mm = re.search(a + r'="([^"]*)"', seg)
        return (mm.group(1).strip() if mm else '')
    other = g('otherphone'); home = g('homephone'); office = g('officephone')
    # priority cell(other) > home > work(office)
    phone = other or home or office
    email = g('email')
    return {'phone':phone, 'email':email}

def status(sid):
    try: return call(sid,'auth_status',{})
    except: return {}

def sleep_cooldown(sid):
    st = status(sid)
    cds = st.get('cooldowns',{})
    mins = max((v.get('minsLeft',0) for v in cds.values()), default=0)
    if mins > 0:
        print(f"[cooldown] sleeping {mins+2}m", flush=True)
        time.sleep((mins+2)*60)
        return session()
    return sid

sid = session()
sid = sleep_cooldown(sid)
done = sum(1 for i in IDS if i in contacts)
print(f"start: {done}/{len(IDS)} already done", flush=True)

i = 0
while i < len(IDS):
    pid = IDS[i]
    if pid in contacts and contacts[pid].get('_ok'):
        i += 1; continue
    try:
        r = call(sid, 'get_patient_demographics', {'patientid': pid})
        c = extract(r.get('rawXml',''))
        c['_ok'] = True
        contacts[pid] = c
        json.dump(contacts, open(OUT,'w'))
        i += 1
        done = sum(1 for x in IDS if x in contacts and contacts[x].get('_ok'))
        if done % 10 == 0 or i == len(IDS):
            print(f"[progress] {done}/{len(IDS)}", flush=True)
        time.sleep(1.5)  # gentle pacing
    except Exception as e:
        msg = str(e)
        low = msg.lower()
        if any(t in low for t in ['cool','rate','limit','lock','class creation','expired','every credential']):
            st = status(sid); cds = st.get('cooldowns',{})
            mins = max((v.get('minsLeft',0) for v in cds.values()), default=0)
            if mins == 0: mins = 60
            print(f"[rate-limit] at {done}/{len(IDS)}, sleeping {mins+2}m", flush=True)
            time.sleep((mins+2)*60)
            sid = session()
            # do not advance i; retry same patient
        else:
            print(f"[err] pid err: {msg[:120]}", flush=True)
            contacts[pid] = {'phone':'','email':'','_ok':True,'_err':msg[:80]}
            json.dump(contacts, open(OUT,'w'))
            i += 1
            time.sleep(2)

ph = sum(1 for x in IDS if contacts.get(x,{}).get('phone'))
em = sum(1 for x in IDS if contacts.get(x,{}).get('email'))
print(f"DONE: phone {ph}/{len(IDS)}, email {em}/{len(IDS)}", flush=True)
