
    @i,                         d dl Z d dlmZmZmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZmZmZmZmZmZ ddlmZ ddlmZ  e j@                  e!      Z"dZ#dZ$ G d d      Z%d Z&y)    N)DictAnyOptional)	timedelta)settings)ValidationError)BotType)EmailService)CompanyBotSettings)AppointmentRepository)WebhookEvent)to_utcdt_str_to_isotz_info_from_offsetsmart_parse_datetime	dt_to_utcInvalidAppointmentDatetime   )book_appointment_x_time)AppointmentNotificationService   -   c                       e Zd ZdZedeeef   deeef   fd       Zede	e   fd       Z
edeeef   fd       Zedeeef   fd	       Zed
efd       Zedede	e   fd       Zy)AppointmentServicez
    Service layer that handles webhook payload normalization and uses the repository.
    Services accept validated data (e.g. BookAppointmentInputSerializer output).
    webhook_payloadreturnc                 j   | j                  d      xs i }| j                  d      xs i }|j                  d      xs i }|j                  d      xs i }|j                  d      xs d}|j                  d      xs d}||j                  d      |j                  d	      |j                  d
      ||dS )zD
        Normalize webhook payload into predictable fields.
        argscalltelephony_identifierretell_llm_dynamic_variablestimezone_offsetNis_office_hourstwilio_call_sid	to_numberfrom_number)r   r$   r%   r&   r"   r#   )get)r   r   	call_infotel_identifierretell_variablesr"   r#   s          W/var/www/html/dp2/backend_v2.1/server/apps/appointments/services/appointment_service.py_extract_common_webhook_dataz/AppointmentService._extract_common_webhook_data$   s    
 ""6*0b#''/52	#--(>?E2<=C 	 +..
  	 +..
  	
 -112CD"{3$==7 / /
 	
    phone_numberc                     | st         j                  d       yt        j                  j	                  |       j                         }|st         j                  d|        y|j                  S )aL  
        Return Company instance matched from CompanyBotSettings or None if not found.
        This is defensive: original code used .first().company and would AttributeError
        if missing; returning None prevents server 500s. If your business rules require
        raising on missing setting, change this accordingly.
        z6No phone number provided in webhook to lookup company.N)r.   z*CompanyBotSettings not found for phone: %s)loggerwarningr   objectsfilterfirstcompany)r.   cbss     r+   _get_company_from_phonez*AppointmentService._get_company_from_phone?   s]     NNST ((//\/JPPRNN< {{r-   validated_payloadc                    t         j                  |       }|d   xs i }t         j                  |j                  d            }|j                  d      }|d   }t	        |      }t        ||      }|j                  d      ||j                  d      |j                  d      |dt        j                  j                  d	}t        j                  |      }	|	S )
zE
        Schedule a sales call back if person not available.
        r   r%   scheduler"   nameoffTimer$   N)r;   scheduled_dateofftimer$   r5   r   bot_type)r   r,   r7   r'   r   r   r	   	SALES_BOTvaluer   create_or_update_by_call_sid)
r8   datar   r5   dt_strr"   tz_infotz_schedule_dtpayloadappointments
             r+   book_sales_callbackz&AppointmentService.book_sales_callbackT   s    
 ">>?PQF|!r$<<TXXk=RS*%01%o60 HHV$,xx	*#xx(9:))//
 ,HHQr-   c           
         t         j                  |       }|d   xs i }t         j                  |j                  d            }|j                  d      xs |j                  d      }	 t	        |      }|d   }t        |      }t        ||      }	t        |d         j                         d	k(  rd
nd}
|d   }|j                  d      xs |j                  d      }|j                  d      xs dj                         j                         xs d}t        j                  d|        |||	|j                  d      |
|dt        j                   j"                  |d	}t%        j&                  |      }t        j                  d|        	 t)        j*                  ||j                  d      |j                  d      |j                  d      |j                  d      d       |S # t
        $ r3}t        j                  d|        t        dt        |      i      d}~ww xY w# t,        $ r.}t        j                  d|j.                  |d       Y d}~|S d}~ww xY w)zO
        Book an appointment for service bot using normalized payload.
        r   r%   appointment_datetimebooking_datetimezInvalid appointment datetime: Nr"   r#   truer   r&   r;   customer_nameservice 
oil changez:=================== Appointment Payload ===============
: r$   )	r;   appointment_phoner=   r$   r>   r5   r   r?   booking_typez7=================== Appointment Info ===============
: vehicle_makevehicle_modelvehicle_yearr.   )makemodelyearcustomer_number)extrazBFailed to send appointment notifications for appointment id=%s: %sT)exc_info)r   r,   r7   r'   r   r   r0   r1   r   strr   r   lowerstripinfor	   SERVICE_BOTrA   r   rB   r   process	Exceptionid)r8   rC   r   r5   rD   	dt_objectexcr"   rE   rF   r>   rZ   rN   rS   rG   rH   s                   r+   book_service_appointmentz+AppointmentService.book_service_appointmentp   sQ   
 ">>?PQF|!r$<<TXXk=RS /0 088./ 		,V4I 01%o6"9g64 12399;vE!4}-(EDHH_,E+1r88:@@BRlQRVQWXY "!0,#xx(9:++11(

 ,HHQN{m\]	*22 HH^4"hh7!XXn5(,(@	  g * 	NN;C5AB!&C#  	X  	NNT	    	s1   (G# 	AH" #	H,.HH"	I+#IIappointment_idc                 ,    t        j                  |       S )z4
        Retrieve an appointment by its ID.
        )r   	get_by_id)rh   s    r+   get_appointment_by_idz(AppointmentService.get_appointment_by_id   s    
 %..~>>r-   rL   c                 f    | syt        | t              rt        |       } | sy| j                  d      S )z?
        Return the weekday name for a given datetime.
        Nz%A)
isinstancer]   r   strftime)rL   s    r+   get_week_dayzAppointmentService.get_week_day   s8    
  &,,-=>#((..r-   N)__name__
__module____qualname____doc__staticmethodr   r]   r   r,   r   r7   rI   rg   intrk   ro    r-   r+   r   r      s    
 
d38n 
cSVh 
 
4 hsm  ( tCH~  6 CDcN C CJ ?c ? ? /s /x} / /r-   r   c                    d }	 | dk(  rt         nt        }t        j                  j	                  ddi i       }|j                         j                         }t        |      dk(  r|d   }d}	n|d   }dj                  |dd        }	|t        |	      z   }
|j                  d
      }|j                  d      }|j                  d      }|||j                  d      |||	|t        |||d|_        |j                  dg       |r|j                  d      }t        ||
||	d|t!        |      ||| 
      \  }}}}||||d|_        |j                  dg       |j                  d      du r|j%                          y |j                  d      xs d}|j'                  d|        dddddd | ||| t)        |      | d| d| t*        rt*        j,                  nd!d"d#d$d%d%d&d'd(}t/        j0                  dd)t2        j4                  |*       y # t6        $ r8}t8        j;                  d+|        |r|j'                  d+|        Y d }~y d }~ww xY w),NrQ   XTimeAppointment)source
event_typeheadersraw_payloadr   r   Unknown )minutesrU   rT   rV   r.   )rN   rZ   provided_numberparts
first_name	last_nameappointment_timerD   rU   rT   rV   r|   )update_fields+zm.mudassir@flutenai.com)
appointment_start_dtappointment_end_dtr   r   emailphonerY   rW   rX   service_name)x_booking_responsex_date_timeopcoderO   r}   successTmessagerP   zX Time Booking Success False zSupport TeamzX Time Booking Failedu   🚨z;An appointment booking attempt has failed and needs review.zBooking Errorz=X Time returned success = False with an invalid date format. zN/A)zCustomer NamezCustomer PhonezBooking TypezAppointment TimeVehicleCompanyzhttps://dp2.front.fluten.xyz/zOpen Admin Panelz#dc2626DealerPulsei  )recipient_namealert_title
alert_iconalert_message
alert_typealert_descriptiondetails
action_urlaction_textbutton_color
text_colorsystem_namecurrent_yearzalerts/general_alert.html)subjecthtml_contentrecipient_listkeyzX Time Booking Exception )OIL_CHANGE_DURATIONMINOR_SERVICE_DURATIONr   r2   creater_   splitlenjoinr   r'   rD   r|   savelstripr   ru   r}   mark_successmark_failedr]   r5   r;   r
   
send_emailr   EMPTY_RECIPIENT_NOTIFY_EMAILSrc   r0   r1   )rS   rN   rZ   re   r   eventr   r   r   r   end_dtrU   rT   rV   r   r   r   rO   r   ctxrf   s                        r+   x_time_appointmentr      s    Eq |+  ' 	 $$++$	 , 
 ##%++-u:?qJ!IqJqr+IY/?@@1xx/xx/ +.#xx7$" 0*((
 	

)
--44S9O;R!*%!+!\"%<
8K #5&	
 	

-
1!!),4 (,,Y7=2G/y9
 #16$!^-'deldm%n &3&5$0(+I".qaO/6w||E >1 )', $1C6 ##/8'EE	  23%89 9#?@	s   E4H 9BH 	I.II)'loggingtypingr   r   r   datetimer   django.confr   rest_framework.exceptionsr   apps.calls.constantsr	   apps.calls.servicesr
   apps.companies.modelsr   apps.appointments.repositoriesr   apps.appointments.modelsr   utils.timezone_utilsr   r   r   r   r   r   xtime_clientr    appointment_notification_servicer   	getLoggerrp   r0   r   r   r   r   rv   r-   r+   <module>r      sm     & &    5 ( , 4 @ 1  2 
		8	$  k/ k/\yr-   