o
    K 8i/@                     @   s   d dl 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ZeeZdd	lmZmZmZmZmZ dd
lmZmZmZmZmZmZ ddlmZm Z  d dl!m"Z" d dl#m$Z$ G dd dej%Z&G dd dej%Z'G dd dej%Z(dS )    )viewsetsstatus)action)Response)IsAuthenticated)get_object_or_404timezoneN   )CallCallLog
CallPromptVapiAssistantUserAssistantPreference)CallSerializerCallLogSerializerCallPromptSerializerCallPromptListSerializerVapiAssistantSerializer!UserAssistantPreferenceSerializer)initiate_call_taskprocess_vapi_webhook_task)Senior)Conversationc                   @   s    e Zd ZdZg ZeZdd ZdS )VapiAssistantViewSetz
    ViewSet for viewing VAPI assistants.
    
    Provides read-only access to active VAPI assistants for user selection.
    c                 C   s   t jjddS )zReturn all active assistantsT	is_active)r   objectsfilterself r!   $/var/www/html/philips/calls/views.pyget_queryset   s   z!VapiAssistantViewSet.get_querysetN)__name__
__module____qualname____doc__permission_classesr   serializer_classr#   r!   r!   r!   r"   r      s
    r   c                   @   s$   e Zd ZdZg Zdd Zdd ZdS )CallPromptViewSetzc
    ViewSet for viewing call prompts.
    
    Provides read-only access to prompt templates.
    c                 C   s   t jjdd}|S )zReturn all active promptsTr   )r   r   r   )r    querysetr!   r!   r"   r#   -   s   zCallPromptViewSet.get_querysetc                 C   s   | j dkrtS tS )Nlist)r   r   r   r   r!   r!   r"   get_serializer_class2   s   
z&CallPromptViewSet.get_serializer_classN)r$   r%   r&   r'   r(   r#   r-   r!   r!   r!   r"   r*   $   s
    r*   c                   @   s   e Zd ZdZg Zdd Zdd Zeddgddd
dZeddgddd Z	eddgddd Z
eddgddd Zeddgddd Zeddgddd Zeddgddd Zeddgddd Zeddgddd Zd	S )CallViewSetzv
    ViewSet for viewing call information.
    
    Provides read-only access to call data and webhook endpoints.
    c                 C   s   t j dS )zReturn all calls for testingsenior)r   r   allselect_relatedr   r!   r!   r"   r#   A   s   zCallViewSet.get_querysetc                 C   s   t S N)r   r   r!   r!   r"   r-   E   s   z CallViewSet.get_serializer_classTget)detailmethodsNc                 C   s6   |   }|j d}t|dd}t|j|jdS )zZ
        Get logs for a specific call.
        
        GET /api/calls/{id}/logs/
        -created_atTmany)call_idlogs)
get_objectr:   r0   order_byr   r   iddata)r    requestpkcallr:   
serializerr!   r!   r"   r:   H   s   zCallViewSet.logsFpostc                 C   s   |j d}|j d}|stdditjdS zLtjj|d}| |_| dkr@t	
 |_|jr?|j|j  }t||_n| dkrKt	
 |_|  tjj|d	d
| |j d tddiW S  tjyv   tdditjd Y S w )z`
        Handle Twilio webhook events.
        
        POST /api/calls/twilio_webhook/
        CallSid
CallStatuserrorzCallSid is requiredr   )
twilio_sid	completedansweredwebhook_receivedzTwilio webhook received: rA   
event_typemessager>   r   successzCall not found)r>   r3   r   r   HTTP_400_BAD_REQUESTr   r   lowertwilio_statusr	   nowcall_end_timecall_start_timetotal_secondsintdurationsaver   createDoesNotExistHTTP_404_NOT_FOUND)r    r?   call_sidcall_statusrA   rX   r!   r!   r"   twilio_webhookX   s<   




zCallViewSet.twilio_webhookc                 C   s   t |j}td|jdS )z_
        Handle Vapi.ai webhook events.
        
        POST /api/calls/vapi_webhook/
        rK   )r   task_id)r   delayr>   r   r=   )r    r?   taskr!   r!   r"   vapi_webhook   s
   zCallViewSet.vapi_webhookc                 C   s$   ddl m} | }td|jdS )zq
        Update call statuses by checking Vapi.ai API.
        
        POST /api/calls/update_statuses/
        r
   )check_and_update_call_statuseszCall status update initiated)rN   r`   )tasksrd   ra   r   r=   )r    r?   rd   rb   r!   r!   r"   update_statuses   s   zCallViewSet.update_statusesc                 C   s   ddl m} |jdd}tjjg dd}| s!tdddS g }|D ]}|	|j
|jj|j|j d	 q%|rJtd
|  d|dddS d}|D ] }d|_d|_|  |d7 }tjj|ddd|  id qNtd| d||dS )z
        Clear all active calls by updating their status to completed.
        
        POST /api/calls/clear_active/
        Body: {"dry_run": true} (optional)
        r   r   dry_runF)	initiatedringingzin-progress)twilio_status__inzNo active calls found to clear.)rN   cleared_count)r=   senior_namer   
created_atzFound z active calls (dry run)T)rN   callsrk   rg   rI   endedr
   cleared_by_adminzCall cleared by admin API
cleared_atrL   zSuccessfully cleared z active calls.)rN   rk   calls_cleared)django.utilsr	   r>   r3   r   r   r   existsr   appendr=   r/   namerR   rm   	isoformatcountvapi_statusrY   r   rZ   rS   )r    r?   r	   rg   active_callscall_detailsrA   rk   r!   r!   r"   clear_active   sT   

zCallViewSet.clear_activec                 C   s   |   }| }|jdd }|jdd }|jddd}d}| r4tdd |D }||  }|d	d
d }	t|	ddj}
t||||dkrR|| d nd||
dS )zh
        Get call statistics for the authenticated user.
        
        GET /api/calls/stats/
        rI   )rR   failedF)rR   duration__isnullr   c                 s   s    | ]}|j V  qd S r2   )rX   ).0rA   r!   r!   r"   	<genexpr>   s    z$CallViewSet.stats.<locals>.<genexpr>r6   N   Tr7   d   )total_callscompleted_callsfailed_callssuccess_rateaverage_duration_secondsrecent_calls)	r#   rx   r   rt   sumr<   r   r>   r   )r    r?   
user_callsr   r   r   completed_calls_with_durationavg_durationtotal_durationr   recent_calls_datar!   r!   r"   stats   s,   zCallViewSet.statsc                 C   sp   ddl m} |jjdddid\}}ztjj|d}t|}t|jW S  tj	y7   tdd	d
t
jd Y S w )zs
        Get the current user's assistant preference.
        
        GET /api/calls/get_user_preference/
        r   Usertestuseremailtest@example.comusernamedefaults)userzNo assistant preference setF)rN   has_preferencerG   )django.contrib.auth.modelsr   r   get_or_creater   r3   r   r   r>   r[   r   r\   )r    r?   r   	test_usercreated
preferencerB   r!   r!   r"   get_user_preference	  s"   

zCallViewSet.get_user_preferencec           	      C   s   ddl m} |jjdddid\}}|jd}|s#tdd	itjd
S z
t	jj|dd}W n t	j
y@   tdditjd
 Y S w tjj|d|id\}}t|}td|j|dS )z
        Set or update the current user's assistant preference.
        
        POST /api/calls/set_user_preference/
        Body: {"assistant_id": 1}
        r   r   r   r   r   r   assistant_idrF   zassistant_id is requiredrG   T)r=   r   zAssistant not found or inactive	assistant)r   r   z)Assistant preference updated successfully)rN   r   r   )r   r   r   r   r>   r3   r   r   rP   r   r[   r\   r   update_or_creater   )	r    r?   r   r   r   r   r   r   rB   r!   r!   r"   set_user_preference"  s>   


zCallViewSet.set_user_preferencec              
   C   s  |j dp|j d}|stdddtjdS zz	tjj|d}W n tjy5   tddd	 Y W S w tjj	|d
d
d }|sMtddd	W S z	tjj|d}W n tjyh   tddd	 Y W S w g }|jrw|d|j  |jrt|jtrd|jnt|j}|d|  |jrt|jtrd|jnt|j}|d|  |jrt|jtrd|jnt|j}	|d|	  |jrt|jtr|jdd ng }
|
rd|
}|d|  |rd|nd}|r|d7 }|d7 }|d7 }|d7 }|d7 }|d7 }t|d|j |j|j|jdW S  tyL } ztd| d t|  td!ddd"tjdW  Y d}~S d}~ww )#aN  
        Get last conversation context for a phone number.
        This endpoint is called by Vapi.ai Server URL/Function Calling.
        
        POST /api/calls/get_last_conversation/
        Body: {
            "phone_number": "+49123456789"
        }
        
        Returns conversation context in format Vapi can use.
        phone_numberphoneNumberzphone_number is requiredz0This is the first conversation with this person.)rF   contextrG   )r   F)r   has_previous_conversationrI   )r/   rR   r6   )rA   zSummary of last conversation: z, zTopics discussed: zEmotions observed: zTopics to follow up on: N   zQuestions to ask: 
zZ

IMPORTANT: Use this previous conversation context naturally and empathetically. You can:zB
- Reference topics they mentioned before if it comes up naturallyz6
- Ask follow-up questions about things they discussedz.
- Check on any concerns or interests they hadzE
- Acknowledge their previous conversation warmly if they remember itz|

Remember: Don't force connections - only mention previous conversations if relevant and natural to the current discussion.T)r   r   last_conversation_datesummarytopicsemotionsz$Error getting last conversation for z: z7An error occurred while retrieving conversation context)rF   r   r   )r>   r3   r   r   rP   r   r   r[   r   r   r<   firstr   r   ru   topics_discussed
isinstancer,   joinstremotions_detectedfollow_up_topicsfollow_up_questionsrm   rw   	ExceptionloggerrF   HTTP_500_INTERNAL_SERVER_ERROR)r    r?   r   r/   	last_callconversationcontext_partsr   r   
follow_ups	questionsquestions_strr   er!   r!   r"   get_last_conversationN  s   

"""

	z!CallViewSet.get_last_conversationr2   )r$   r%   r&   r'   r(   r#   r-   r   r:   r_   rc   rf   r|   r   r   r   r   r!   r!   r!   r"   r.   8   s.    
-


=
$

+r.   ))rest_frameworkr   r   rest_framework.decoratorsr   rest_framework.responser   rest_framework.permissionsr   django.shortcutsr   rs   r	   logging	getLoggerr$   r   modelsr   r   r   r   r   serializersr   r   r   r   r   r   re   r   r   seniors.modelsr   conversations.modelsr   ReadOnlyModelViewSetr   r*   r.   r!   r!   r!   r"   <module>   s     
 