;==============================================================================
; extensions.conf  —  ePhone routing dialplan
;
;   OUTBOUND:  [from-mobile]  app dials number -> format -> PJSIP/...@trunk2
;   INBOUND:   [from-trunk]   carrier DID -> find engineer -> ring WebRTC over WSS
;==============================================================================

[globals]
TRUNK=trunk2                         ; matches endpoint name in pjsip.conf
OUTBOUND_CID=+15551234567            ; your DID, shown to the customer as caller ID
DEFAULT_ENGINEER=6001                ; fallback if a DID isn't mapped to a person


;==============================================================================
; OUTBOUND  —  calls that originate FROM a mobile app
;   Endpoint [66xx] has context=from-mobile, so every app-dialed number arrives
;   here. We normalise to E.164 then dial the trunk.
;==============================================================================
[from-mobile]

; --- 1. Internal engineer-to-engineer calls (6000-6999) stay on Asterisk ------
exten => _6XXX,1,NoOp(Internal call ${CALLERID(num)} -> ${EXTEN})
 same => n,Dial(PJSIP/${EXTEN},30)
 same => n,Hangup()

; --- 2. E.164 numbers the app already formatted (+1..., +91...) ---------------
exten => _+.,1,NoOp(Outbound E164 ${CALLERID(num)} dialing ${EXTEN})
 same => n,Set(CALLERID(num)=${OUTBOUND_CID})
 same => n,Dial(PJSIP/${EXTEN}@${TRUNK},60)
 same => n,Hangup()

; --- 3. North-American 10-digit -> prepend +1 --------------------------------
exten => _NXXNXXXXXX,1,NoOp(Outbound 10-digit -> +1${EXTEN})
 same => n,Set(CALLERID(num)=${OUTBOUND_CID})
 same => n,Dial(PJSIP/+1${EXTEN}@${TRUNK},60)
 same => n,Hangup()

; --- 4. Anything with a leading 0 international access -> strip and +  ---------
exten => _0.,1,NoOp(Outbound intl ${EXTEN:1})
 same => n,Set(CALLERID(num)=${OUTBOUND_CID})
 same => n,Dial(PJSIP/+${EXTEN:1}@${TRUNK},60)
 same => n,Hangup()

; --- Call outcome handling (busy / no answer / congestion) --------------------
; The Dial() in each pattern above falls through to here on failure; the hangup
; handler logs the final DIALSTATUS (BUSY / NOANSWER / CONGESTION / CHANUNAVAIL).
exten => h,1,NoOp(Outbound hangup, status=${DIALSTATUS})


;==============================================================================
; INBOUND  —  customer calls our DID, carrier delivers it on trunk2
;   Endpoint [trunk2] has context=from-trunk, so carrier INVITEs arrive here.
;   ${EXTEN} = the DID/DNIS the carrier sends (often the full +1... number).
;==============================================================================
[from-trunk]

; --- Map each purchased DID -> the engineer who owns it -----------------------
; Direct DID -> single engineer
exten => +15551234567,1,NoOp(Inbound to DID ${EXTEN} from ${CALLERID(num)})
 same => n,Goto(ring-engineer,6001,1)

exten => +15559876543,1,Goto(ring-engineer,6002,1)

; Catch-all: any DID the carrier delivers -> hunt/queue of engineers
exten => _[+0-9].,1,NoOp(Inbound unmapped DID ${EXTEN} -> default engineer)
 same => n,Goto(ring-engineer,${DEFAULT_ENGINEER},1)

exten => h,1,NoOp(Inbound call ended)


;==============================================================================
; RING-ENGINEER  —  shared subroutine that rings a WebRTC extension over WSS
;   arg = the 6xxx extension to ring. Handles offline / no-answer gracefully.
;   This is where the "wake the phone" push should be triggered (see below).
;==============================================================================
[ring-engineer]

exten => _6XXX,1,NoOp(Ringing WebRTC engineer ${EXTEN})
 ; Fire a VoIP push so a backgrounded/locked phone wakes and registers in time.
 ; Runs your push script asynchronously; DEVICE state check keeps calls flowing
 ; even if push infra is down.
 same => n,System(/usr/local/bin/ephone-push.sh ${EXTEN} "${CALLERID(num)}" &)
 same => n,Set(TIMEOUT(absolute)=45)
 ; Give the app a moment to wake + re-REGISTER before we send the INVITE.
 same => n,Wait(2)
 same => n,GotoIf($["${DEVICE_STATE(PJSIP/${EXTEN})}" = "UNAVAILABLE"]?offline)
 same => n,Dial(PJSIP/${EXTEN},40,rtT)     ; ring the app; r=ringback, t/T=transfer
 same => n,Goto(after-dial)

 same => n(offline),NoOp(Engineer ${EXTEN} not registered -> voicemail/failover)
 same => n(after-dial),NoOp(Dial status ${DIALSTATUS})
 same => n,GotoIf($["${DIALSTATUS}" = "ANSWER"]?done)
 ; No answer / busy / offline -> voicemail (or reroute to a colleague / PSTN cell)
 same => n,Voicemail(${EXTEN}@ephone,u)
 same => n(done),Hangup()
