o
    *Eh-0                     @   s  d dl 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Zd dlmZmZ d dlmZ d dlZd dlmZ d dlZd dlZd dlZedeZe Zd	d
 Zdd Zejddgddd Zejddgddd Z ejddgddd Z!ejddgddd Z"d dl#Z#d dl$m%Z% e&dZ'dZ(dd  Z)d!d" Z*d#e+d$e+d%e,fd&d'Zd(d) Z-d*d+ Z.d#e+d,e/fd-d.Z0d/d0 Z1dS )1    )	Blueprintjsonifyrequestcurrent_app)dbCustomerContentSentMessage
SubscriberSchedule)datetime	timedeltaN)MailMessage)BackgroundScheduler)generate_unique_link	schedulerc                 C   sL   t || gd}||_t  t| W d   dS 1 sw   Y  dS )zFunction to send an email.)subject
recipientsN)r   bodyr   app_contextmailsend)tor   r   msg r   G/home/www/bk.finsightngr.online/FinSight/app/routes/scheduler_routes.py
send_email   s
   
"r   c                 C   s   |   Q t }tj }|D ]2}|j|k|_tj	tj
|jktj|jkB  }|r1|j|_qt|j|jd|jd}tj| qtj  td W d    d S 1 sXw   Y  d S )NzNew Customer)mobile_numberemailnamesubscription_statusu.   ✅ Subscription statuses checked and updated.)r   r   utcnowr
   queryallendtimesubscribeStatusr   filterr   phoner   firstr   sessionaddcommitlogginginfo)appnowsubscribers
subscribercustomernew_customerr   r   r   check_subscriptionsD   s0   





"r5   z	/scheduleGET)methodsc                   C   s   t   tddidfS )z(Route to trigger the scheduling process.messagezScheduled messages processed.   )Zsend_daily_messagesr   r   r   r   r   schedule_daily_messagesd   s   r:   z/scheduled_contentsc               
   C   s   t jjddtd} t jjddtd}tjjdd }g }|D ]6}|jt	dd }t
 |krUtjtj t
  k }|D ]}||j|j|j|d	d
 qBq| d | }|| }	|||	 }
t|
t|| |dS )zDGet the list of scheduled contents and their recipients (paginated).page   typeper_page
   T)r!   )hours%Y-%m-%d %H:%M:%S)	recipientheadlinelinkscheduled_time)scheduled_contentstotalr;   r?   )r   argsgetintr   r#   	filter_byr$   
created_atr   r   r0   r   r'   dateappendr   rD   rE   strftimer   len)r;   r?   active_subscribersrG   r2   rF   contentscontentstartendZpaginated_contentsr   r   r   get_scheduled_contentsm   s2   "
rW   z/sent_contentsc               	   C   s   t jjddtd} t jjddtd}tjj| |dd}g }|jD ]!}tj|j	}t
j|j}||j|j|j|jdd	 q t||j| |d
S )Nr;   r<   r=   r?   r@   F)r;   r?   	error_outrB   )rD   rE   rC   sent_at)sent_contentsrH   r;   r?   )r   rI   rJ   rK   r	   r#   paginateitemsr   
content_idr   recipient_idrO   rD   rE   r   rY   rP   r   rH   )r;   r?   Zsent_messages_queryrZ   sent_messagerT   rC   r   r   r   get_sent_contents   s&   


r`   z/push_contentPOSTc               
   C   s   t  } | d}| d}td z?tj|}tj|}t	|j
|j
d}tj| tj  d|j d|j d|j }td| d	 td
didfW S  tyx } ztdt|  tdt|idfW  Y d}~S d}~ww )z0Endpoint to manually push content to a customer.customer_idr]   z,Received request to push content to customer)r]   r^   zHello z,
Today's News:
z: zContent pushed to customer z successfullyr8   z'Content pushed to customer successfullyr9   z#Error pushing content to customer: errori  N)r   get_jsonrJ   r-   r.   r   r#   
get_or_404r   r	   idr   r*   r+   r,   r    rD   rE   r   	Exceptionrc   str)	json_datarb   r]   r3   rT   r_   r8   er   r   r   push_content_to_customer   s$   



 rk   )SQLAlchemyErrorzAfrica/Lagosz#https://bk.finsightngr.online:30976c                   C   s   t t S N)r   r0   WATrN   r   r   r   r   
_wat_today   s   ro   c                   C   s   t tjS rm   )r   r0   rn   hourr   r   r   r   _current_wat_hour   s   rq   r]   subscriber_idreturnc                 C   sh   t |dr	| nt|}|  d| d| dt   }t|  }t	 d|  d| d| S )N	isoformat_z	/content//)
hasattrrt   rh   r   r"   hashlibmd5encode	hexdigest	BASE_HOST)r]   scheduled_daterr   sdunique_stringunique_hashr   r   r   r      s   "r   c                  C   sB   t  } tjj| dtj  }|sdS |d j}|t	|fS )z|Return a primary content_id for today (pick the earliest/lowest id if multiple).
       If none scheduled, return None.
    )rN   )Nr   r   )
ro   r   r#   rL   order_byrf   ascr$   r]   rQ   )todayr\   primaryr   r   r    _get_todays_scheduled_content_id   s   
r   c                  C   s   z.t jjddt jd} |  }| jt jdidd tj	
  tjd| d |W S  tyC   tjd tj	  Y d	S w )
z%Bulk clear news_link for active subs.Tr&   NF)synchronize_sessionz#[DailyLinks] Cleared news_link for  active subscribers.z1[DailyLinks] Clearing links failed; rolling back.r   )r
   r#   rL   r'   	news_linkisnotcountupdater   r*   r,   r   loggerr.   rl   	exceptionrollback)qr   r   r   r   #_clear_links_for_active_subscribers   s   

r   only_missingc                 C   s  d}d}t  }tjjdd}|r|tjd}zS|tj	 }d}	 |}|dur3|tj|k}|
| }	|	s=q]|	D ]}
t| ||
j|
_tj|
 |
j}|d7 }q?tj  q%tjd| d| d	 |W S  ty   tjd
 tj  | Y S w )z_Populate links for active subscribers; if only_missing=True, fill only where news_link is NULL.i  r   Tr   Nr<   z+[DailyLinks] Populated links (only_missing=z) for r   z1[DailyLinks] Populate links failed; rolling back.)ro   r
   r#   rL   r'   r   is_r   rf   r   limitr$   r   r   r*   r+   r,   r   r   r.   rl   r   r   )r]   r   ZBATCHrH   r   Z
base_queryr#   Zlast_idZpage_qbatchsubr   r   r   _populate_links_for_subscribers  s<   


r   c                  C   s  t  } t \}}|stjd|  d dd| dS d}| dkr#d}n| d	kr*d
}n	| dv r1d}nd}| |||d}|dkrFt }||d< n0|d
krUt|dd}||d< n!|dkrdt|dd}||d< ntjd|  d d|d< d|d< tjd|  |S )a!  
    Runs at 4,5,6,7,8 WAT.
    - 4:00  => clear all links for active subscribers (phase CLEAR)
    - 5:00  => generate links for all active subscribers (phase POPULATE_ALL)
    - 6-8   => fill only missing links (phase TOP_UP)
    Only runs if there is scheduled content for *today*.
    z<[DailyLinks] No scheduled content for today; skipping (hour=z).TZno_scheduled_content)skippedreasonrp   N   ZCLEAR   ZPOPULATE_ALL)         ZTOP_UPUNKNOWN)rp   phasescheduled_countr]   clearedF)r   	populatedZ	topped_upz$[DailyLinks] Unknown phase for hour=z; doing nothing.r   Zunknown_phaser   z[DailyLinks] Result: )rq   r   r   r   r.   r   r   )Zwat_hourZprimary_content_idr   r   resultr   r   Ztoppedr   r   r   run_daily_link_maintenance0  s8   



r   )2flaskr   r   r   r   
app.modelsr   r   r   r	   r
   r   r   r   r-   
flask_mailr   r   !apscheduler.schedulers.backgroundr   pytz	app.utilsr   	threadingtime__name__scheduler_bpr   r   r5   router:   rW   r`   rk   rx   Zsqlalchemy.excrl   timezonern   r|   ro   rq   rK   rh   r   r   boolr   r   r   r   r   r   <module>   sD    
, 

(

#
%