
    21j#                        d Z ddlmZ 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  ej        e          ZddZ G d d          Z G d d          Z e            Z e            ZdS )u  Repositories over `city_briefs` and `city_briefs_runs`.

The repository layer is the only code that owns SQL for these two tables.
The orchestrator and API layer call repo methods and never write raw SQL
themselves — this keeps the surface narrow and audit-friendly.
    )annotationsN)datedatetimetimezone)Any)UUID)db)STAGE_COLUMNSreturnstrc                 b    t          j        t          j                                                  S )z1Current timestamp as an ISO string usable in SQL.)r   nowr   utc	isoformat     7/workspace/show-city-briefing-agent/app/repositories.py_tsr      s     <%%//111r   c                      e Zd ZdZd8dZd8dZd9dZddddd:dZd;dZd<dZ		 	 	 	 	 	 	 	 	 	 	 d=d>d,Z
d?d.Zd@d1ZdAd3ZdBdCd7ZdS )D	BriefRepoz!Reads + writes for `city_briefs`.show_idr   r   dict | Nonec                >   K   t          j        d|f           d {V S )Nz,SELECT * FROM city_briefs WHERE show_id = %sr	   fetchoneselfr   s     r   fetch_by_showzBriefRepo.fetch_by_show   s@      [:J
 
 
 
 
 
 
 
 	
r   c                >   K   t          j        d|f           d {V S )NzESELECT * FROM city_briefs WHERE show_id = %s AND status = 'published'r   r   s     r   fetch_existing_publishedz"BriefRepo.fetch_existing_published#   s@      [SJ
 
 
 
 
 
 
 
 	
r   payloaddict[str, Any]dictc                $  K   d                     |                                          }d                     d |D                       }t          j        d| d| dt	          |                                                     d {V }|d         S )N, c              3     K   | ]}d V  dS )z%sNr   ).0_s     r   	<genexpr>z#BriefRepo.insert.<locals>.<genexpr>+   s"       8 81 8 8 8 8 8 8r   zINSERT INTO city_briefs (z
) VALUES (z) RETURNING *r   )joinkeysr	   fetchtuplevalues)r   r!   colsplaceholdersrowss        r   insertzBriefRepo.insert)   s      yy((yy 8 8 8 8 888XSSSSSS'..""##
 
 
 
 
 
 
 
 Awr   Nz	max-amini)venuecapacitycomedian_id	show_dater   citycountryr3   
str | Noner4   
int | Noner5   c          	        K   |                      |           d{V }|r|S |||||||dd}	|                     |	           d{V S )zCreate a pending brief row if none exists; return the row either way.

        `UNIQUE(show_id)` guarantees we cannot race a sibling into two rows.
        Npending)r   r6   r7   r8   r3   r4   r5   status)r   r2   )
r   r   r6   r7   r8   r3   r4   r5   existingr!   s
             r   ensure_pendingzBriefRepo.ensure_pending2   s       ++G44444444 	O" &	
 	
 [[)))))))))r   brief_id
UUID | strc                   K   d                     d |                                D                       }g |                                |R }t          j        d| d|           d {V }|d         S )Nr%   c              3      K   | ]	}| d V  
dS  = %sNr   r'   ks     r   r)   z#BriefRepo.update.<locals>.<genexpr>I   (      ==A======r   zUPDATE city_briefs SET z  WHERE brief_id = %s RETURNING *r   )r*   r+   r.   r	   r,   )r   r@   r!   r/   paramsr1   s         r   updatezBriefRepo.updateH   s      yy==gllnn====="?GNN$4$4"?h"?"?XLdLLL
 
 
 
 
 
 
 
 Awr   c                \   K   |                      |dt                      d           d {V S )N
generating)r=   generated_atrJ   r   )r   r@   s     r   set_generatingzBriefRepo.set_generatingQ   s;      [[lTWTYTY+Z+Z[[[[[[[[[r   generated_topicslistranked_topicslist | Noneverified_factsremoved_factscity_intelligencerecent_newscompetitor_warnings
crowd_workrecent_transcriptsprevious_show_datedate | Noneprevious_show_venueprevious_tickets_soldc                t   K   |                      |dt                      ||||||||	|
|||d           d {V S )N	generated)r=   rM   rP   rR   rT   rU   rV   rW   rX   rY   rZ   r[   r]   r^   rN   )r   r@   rP   rR   rT   rU   rV   rW   rX   rY   rZ   r[   r]   r^   s                 r   set_generatedzBriefRepo.set_generatedT   sv       [[!EE 0*,*!2&#6$"4"4#6%:,
 ,
         	r   
public_urlc                D   K   |                      |d|d           d {V S )N	deploying)r=   rb   rJ   )r   r@   rb   s      r   set_deployingzBriefRepo.set_deployingq   s5      [[kQ[+\+\]]]]]]]]]r   generation_duration_msintc                `   K   |                      |dt                      |d d           d {V S )N	published)r=   published_atgeneration_durationerrorrN   )r   r@   rg   s      r   mark_publishedzBriefRepo.mark_publishedt   sV      [[!EE#9	,
 ,
         	r   rm   c                \   K   |                      |d|r
|d d         nd d           d {V S )Nfailed  )r=   rm   re   )r   r@   rm   s      r   mark_failedzBriefRepo.mark_failed|   s]      [[%*4U5D5\\,
 ,
         	r      limit
list[dict]c                >   K   t          j        d|f           d{V S )z3For the API's status dashboard / manual inspection.zSELECT brief_id, show_id, show_date, city, country, status, public_url, error, published_at, created_at FROM city_briefs ORDER BY created_at DESC LIMIT %sNr	   r,   )r   rt   s     r   recent_briefszBriefRepo.recent_briefs   sE      XA H	
 
 
 
 
 
 
 
 	
r   )r   r   r   r   )r!   r"   r   r#   )r   r   r6   r   r7   r   r8   r   r3   r9   r4   r:   r5   r   r   r#   )r@   rA   r!   r"   r   r#   )r@   rA   r   r#   )NNNNNNNNNNN)r@   rA   rP   rQ   rR   rS   rT   rS   rU   rS   rV   r   rW   rS   rX   rS   rY   rS   rZ   rS   r[   r\   r]   r9   r^   r:   r   r#   )r@   rA   rb   r   r   r#   )r@   rA   rg   rh   r   r#   )r@   rA   rm   r9   r   r#   )rs   )rt   rh   r   ru   )__name__
__module____qualname____doc__r   r    r2   r?   rJ   rO   ra   rf   rn   rr   rx   r   r   r   r   r      s?       ++
 
 
 

 
 
 
    26d0;* * * * * *,   \ \ \ \ :>:>9==A7;?C6:>B>B>B@D    :^ ^ ^ ^      
 
 
 
 
 
 
r   r   c                  L    e Zd ZdZddddd
ZddZ	 dd dZ	 	 dd!dZd"dZdS )#RunRepouB   Reads + writes for `city_briefs_runs` — per-stage observability.N)r   r6   r   r9   r6   r\   r   r#   c                  K   |d}n||f}|t          j        d           d {V }nt          j        d||f           d {V }|d         S )Nr   zQINSERT INTO city_briefs_runs (show_id, show_date) VALUES (NULL, NULL) RETURNING *zMINSERT INTO city_briefs_runs (show_id, show_date) VALUES (%s, %s) RETURNING *r   rw   )r   r   r6   rI   r1   s        r   r2   zRunRepo.insert   s      ?&(FFy)F?2       DD
 .)$       D
 Awr   brief_run_idrA   r   c                >   K   t          j        d|f           d {V S )Nz6SELECT * FROM city_briefs_runs WHERE brief_run_id = %sr   r   r   s     r   r,   zRunRepo.fetch   s@      [DO
 
 
 
 
 
 
 
 	
r   stager   staterm   rb   c                  K   |t           vrt          d|          |dvrt          d|          | dg}|g}|>| d}|                    | d           |                    |r
|dd         nd           |0|dk    r*|                    d	           |                    d
           |                    |           t          j        dd                    |           dt          |                     d{V }	|	r|	d         ndS )zSet a stage's state (+ optional error / public_url scratch).

        `stage` must be one of STAGE_COLUMNS. `state` must be one of
        'pending','running','ok','failed','skipped'.
        zunknown stage )r<   runningokrp   skippedzunknown stage state rE   N_errorrq   vps_deploymentzurl_verification = %sr<   UPDATE city_briefs_runs SET r%   $ WHERE brief_run_id = %s RETURNING *r   )r
   
ValueErrorappendr	   r,   r*   r-   )
r   r   r   r   rm   rb   setsrI   err_colr1   s
             r   	set_stagezRunRepo.set_stage   si      %%7e77888III=E==>>>#???+"G&&&GKK7)))***MM%9%,,T:::!e/?&?&?KK/000MM)$$$l###X3499T?? 3 3 3&MM
 
 
 
 
 
 
 

 (tAwwD(r   r=   duration_msrh   retry_countr:   c                @  K   t                      ||d}||r
|d d         nd |d<   |||d<   d                    d |                                D                       }g |                                |R }t	          j        d| d|           d {V }	|	d	         S )
N)completed_atr=   durationrq   rm   r   r%   c              3      K   | ]	}| d V  
dS rD   r   rF   s     r   r)   z(RunRepo.mark_complete.<locals>.<genexpr>   rH   r   r   r   r   )r   r*   r+   r.   r	   r,   )
r   r   r=   r   rm   r   r!   r/   rI   r1   s
             r   mark_completezRunRepo.mark_complete   s        EE##
 #

 /4>uUdU||$GG"%0GM"yy==gllnn=====27>>##2\22XU4UUU
 
 
 
 
 
 
 
 Awr   Nonec                B   K   t          j        d|f           d {V  d S )NzQUPDATE city_briefs_runs SET retry_count = retry_count + 1 WHERE brief_run_id = %s)r	   executer   s     r   increment_retryzRunRepo.increment_retry   sL      j&O
 
 	
 	
 	
 	
 	
 	
 	
 	
 	
r   )r   r9   r6   r\   r   r#   )r   rA   r   r   )NN)r   rA   r   r   r   r   rm   r9   rb   r9   r   r   )r   rA   r=   r   r   rh   rm   r9   r   r:   r   r#   )r   rA   r   r   )	ry   rz   r{   r|   r2   r,   r   r   r   r   r   r   r~   r~      s        LL48SW      &
 
 
 
 LP) ) ) ) )> DH7;    (
 
 
 
 
 
r   r~   )r   r   )r|   
__future__r   loggingr   r   r   typingr   uuidr   app.dbr	   
app.modelsr
   	getLoggerry   loggerr   r   r~   
brief_reporun_repor   r   r   <module>r      s6    # " " " " "  - - - - - - - - - -                   $ $ $ $ $ $		8	$	$2 2 2 2
o
 o
 o
 o
 o
 o
 o
 o
dS
 S
 S
 S
 S
 S
 S
 S
n Y[[
799r   