#!/usr/bin/env python3
"""Administrative intake and resource-filtering demonstration, not clinical triage.
Example values illustrate selected techniques; operational data and the complete implementation are not disclosed.
"""
import argparse,json,shutil,subprocess,unittest
NOW=1000
RESOURCES=[
 {'name':'DEMO A','ward':'DEMO emergency entrance','services':['clinician_selected_service'],'accepting':True,'status_at':990,'travel_minutes':12,'handover_minutes':8},
 {'name':'DEMO B','ward':'DEMO regulated entrance','services':['clinician_selected_service'],'accepting':True,'status_at':980,'travel_minutes':18,'handover_minutes':1},
 {'name':'DEMO C','ward':'DEMO closed entrance','services':['clinician_selected_service'],'accepting':False,'status_at':995,'travel_minutes':3,'handover_minutes':1},
 {'name':'DEMO D','ward':'DEMO unverified entrance','services':['clinician_selected_service'],'accepting':True,'status_at':100,'travel_minutes':2,'handover_minutes':1}
]
def resource_candidates(service,resources,now,max_age=300):
 """service is supplied by a clinician/regulation adapter, never inferred from caller words."""
 if not service:return []
 eligible=[]
 for row in resources:
  age=now-row['status_at']
  if not row['accepting'] or not 0<=age<=max_age or service not in row['services']:continue
  r=dict(row);r['estimated_minutes']=r['travel_minutes']+r['handover_minutes'];eligible.append(r)
 return sorted(eligible,key=lambda r:r['estimated_minutes'])
def release_information(candidate,review):
 """In this teaching example review is a fixture. Production must verify operator identity,
 patient/session binding, authority, transport decision and an audit reference server-side."""
 if not candidate or not review or not review.get('reviewed_by_clinician') or not review.get('reference'):return None
 return {'resource':candidate['name'],'entrance':candidate['ward'],'review_reference':review['reference'],'kind':'educational_example'}
class Intake:
 def __init__(self):self.state='LOCATION';self.location=None;self.confirmed=False;self.retries=0;self.needs_clinician=True
 def prompt(self):
  return {'LOCATION':'Tell the operator your location and a nearby landmark.','CONFIRM':'I heard: '+str(self.location)+'. Is that location correct? Say yes or no.','HANDOFF':'Your details are ready for clinical regulation. This demo does not give medical advice or direct you to a hospital.'}[self.state]
 def step(self,text):
  text=text.strip()
  if self.state=='HANDOFF':return self.prompt()
  if text.lower() in {'operator','human','0'}:self.state='HANDOFF';return self.prompt()
  if not text:
   self.retries+=1
   if self.retries>=2:self.state='HANDOFF'
  elif self.state=='LOCATION':self.location=text;self.state='CONFIRM'
  elif self.state=='CONFIRM':
   if text.lower() in {'yes','sim'}:self.confirmed=True;self.state='HANDOFF'
   elif text.lower() in {'no','nao','não'}:self.location=None;self.confirmed=False;self.state='LOCATION'
   else:
    self.retries+=1
    if self.retries>=2:self.state='HANDOFF'
  return self.prompt()
 def packet(self):return {'location':self.location,'location_confirmed':self.confirmed,'needs_clinician':True,'state':self.state}
def speak(text):
 for binary,args in [('say',[]),('espeak',[]),('flite',['-t'])]:
  executable=shutil.which(binary)
  if executable:subprocess.run([executable]+args+[text],check=True);return
 print('[No local speech engine installed; text only.]')
class Tests(unittest.TestCase):
 def test_no_service_without_clinician_input(self):self.assertEqual(resource_candidates(None,RESOURCES,NOW),[])
 def test_closed_and_stale_excluded(self):self.assertEqual({x['name'] for x in resource_candidates('clinician_selected_service',RESOURCES,NOW)},{'DEMO A','DEMO B'})
 def test_nearest_not_necessarily_best(self):self.assertEqual(resource_candidates('clinician_selected_service',RESOURCES,NOW)[0]['name'],'DEMO B')
 def test_no_unreviewed_information(self):self.assertIsNone(release_information(RESOURCES[0],None))
 def test_no_reference_no_release(self):self.assertIsNone(release_information(RESOURCES[0],{'reviewed_by_clinician':True}))
 def test_location_correction(self):
  i=Intake();i.step('DEMO street');i.step('no');self.assertIsNone(i.location);i.step('DEMO square');i.step('yes');self.assertTrue(i.packet()['needs_clinician'])
 def test_silence_handoff(self):
  i=Intake();i.step('');i.step('');self.assertEqual(i.state,'HANDOFF')
 def test_unconfirmed_handoff_preserves_uncertainty(self):
  i=Intake();i.step('DEMO street');i.step('operator');self.assertFalse(i.packet()['location_confirmed'])
 def test_operator_without_location(self):
  i=Intake();i.step('operator');self.assertEqual(i.state,'HANDOFF');self.assertIsNone(i.location)
def main():
 parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('--test',action='store_true');parser.add_argument('--demo',action='store_true');parser.add_argument('--speak',action='store_true');args=parser.parse_args()
 if args.test:unittest.main(argv=['medical_intake.py']);return
 if args.demo:
  print('TECHNIQUE EXAMPLES. These values explain the algorithm; they are not operational routing data.')
  print(json.dumps(resource_candidates('clinician_selected_service',RESOURCES,NOW),indent=2));return
 i=Intake();print('LOCAL TEACHING LAB. No microphone, phone call, dispatch or real hospital recommendation. Type /quit to stop.');print(i.prompt())
 if args.speak:speak(i.prompt())
 while i.state!='HANDOFF':
  try:text=input('Caller: ')
  except EOFError:break
  if text=='/quit':break
  reply=i.step(text);print(reply)
  if args.speak:speak(reply)
 print(json.dumps(i.packet(),indent=2))
if __name__=='__main__':main()
