
    i#X              	       $   d dl mZmZmZmZ d dlmZ d dlmZmZ d dl	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 d dlZd	Z ee          Zed
         Z eddd          Ze                    edgddgdg            G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z G d de          Z d Z!dYde"d ed!e"d"efd#Z#d$ Z$e%                    d%          d&             Z&e%                    d'          dZd(e
e'         fd)            Z(e%                    d*          d+e"fd,            Z)e%                    d-          dYd.e
e"         d/e
e"         fd0            Z*e%                    d1          d2e"fd3            Z+e%                    d4           ed5d67           ed5d87           edd97          fd.e"d/e"d:e
e"         fd;            Z,e%                    d<           ed5d=7          fd>e"fd?            Z-e.                    d@           ed5dA          fd>e"fdB            Z/e%                    dC          dYd>e
e"         d:e
e"         fdD            Z0e.                    dE          dFefdG            Z1e.                    dH          dFefdI            Z2e%                    dJ          dKe"fdL            Z3e.                    dM          dFefdN            Z4e.                    dO          dFefdP            Z5e.                    dQ          dFe fdR            Z6e%                    dS          	 	 dYdTe
e"         dUe
e"         fdV            Z7e%                    dW          dX             Z8dS )[    )FastAPIHTTPExceptionQueryBody)CORSMiddleware)datetime	timedelta)OptionalListDictAny)	BaseModelField)MongoClient)ObjectIdNzCmongodb://admin:admin123@mongodb:27017/mcp_adcp_db?authSource=adminmcp_acdp_dbzADCP API2.3.0z4Ad Context Protocol compliant API for TV advertising)titleversiondescription*T)allow_originsallow_credentialsallow_methodsallow_headersc                   t    e Zd ZU dZeed<   dZeed<   eed<   eed<   dZee	         ed<   dZ
ee         ed	<   dS )
ADCPResponseadcpprotocolr   r   status	timestampNdatamessage)__name__
__module____qualname__r   str__annotations__r   r"   r
   r   r#        /app/src/api.pyr   r   *   sl         HcGSKKKNNND(3-!GXc]!!!!!r*   r   c                       e Zd ZU eed<   dZee         ed<   dZee         ed<   dZee         ed<   i Z	ee
         ed<   dS )ProductDiscoveryRequestqueryNchannel	date_fromdate_tofilters)r$   r%   r&   r'   r(   r/   r
   r0   r1   r2   r   r)   r*   r+   r-   r-   2   sk         JJJ!GXc]!!!#Ix}###!GXc]!!! GXd^     r*   r-   c                       e Zd ZU eed<   eed<   ee         ed<   eed<   eed<   eed<   dZeed<   d	gZ	ee         ed
<   i Z
eed<   dS )MediaBuyRequestname
advertiserpackages
start_dateend_datebudgetMADcurrencyreach
objectiveskpisN)r$   r%   r&   r'   r(   r   r   floatr<   r>   r?   r)   r*   r+   r4   r4   9   s         
IIIOOO4jOOOMMMMMMHc$IJS	%%%D$OOOOOr*   r4   c                   x    e Zd ZU eed<   ddgZee         ed<   dZeee                  ed<   i Z	ee
         ed<   dS )SignalDiscoveryRequestr.   audience
contextualsignal_typesN	providersr2   )r$   r%   r&   r'   r(   rE   r   rF   r
   r2   r   r)   r*   r+   rB   rB   D   sa         JJJ)<8L$s)888%)IxS	"))) GXd^     r*   rB   c                   >    e Zd ZU eed<   ee         ed<   i Zeed<   dS )SignalActivationRequest	signal_id	platformsconfigN)r$   r%   r&   r'   r(   r   r   rK   r)   r*   r+   rH   rH   J   s;         NNNDzFDr*   rH   c                   >    e Zd ZU eed<   ee         ed<   i Zeed<   dS )CreativeSyncRequestmedia_buy_id	creativesassignmentsN)r$   r%   r&   r'   r(   r   r   rP   r)   r*   r+   rM   rM   O   s>         DzKr*   rM   c                 >    d| v rt          | d                   | d<   | S )z/Convert MongoDB documents to JSON-safe objects._id)r'   )docs    r+   serialize_docrT   X   s#    ||U__E
Jr*   r    r"   r#   returnc                 `    dd| t          j                                                    dz   ||dS )zCreate ADCP-compliant responser   r   Z)r   r   r    r!   r"   r#   )r   utcnow	isoformatr    r"   r#   s      r+   create_adcp_responser[   ^   s>     _&&0022S8  r*   c                    | d         |d          ddd|d         |d         |                     dd	          |                     d
d          d|d         |d         |                     dd          |d                                         |d                                         d| d                                         | d         |                      dd          d|r|                     dd          nd|r|                     dd          nd|r|                     dd          ndd|                      dd           d d!| d         |d         |d         d"d#
S )$z)Transform ad break to ADCP Product formatad_break_idr   z - Ad Break	linear_tvvideo
channel_idchannel_namelanguagearcountryMA)idr5   rb   rd   
program_idcategorygeneral
start_timeend_time)rf   r   rh   rj   rk   duration_secondspositionzmid-roll)rj   rl   rm   
base_pricer   r<   r;   pricing_modelcpm)rn   r<   ro   is_soldF
guaranteed)	availableinventory_type)r]   rg   r`   )

product_idr5   typeformatr/   program	placementpricingavailabilitymetadata)getrY   )adbreakrx   r/   
price_datas       r+   transform_adbreak_to_productr   i   s    m,7#000,'N+J55{{9d33	
 
 ,'W%J	::!,/99;;
+5577
 
 ",/99;; '(: ;J
;;
 
 >HN*..q999Q=GR
z5999UGQ\Z^^OUCCCW\
 
 %[[E:::*
 

 #=1!,/!,/
 
A% % %r*   z/api/v1/channelsc                  r    t          t          d                                                   } d | D             S )zList all channels.channelsc                 ,    g | ]}t          |          S r)   rT   .0cs     r+   
<listcomp>z get_channels.<locals>.<listcomp>        ///M!///r*   )listdbfind)r   s    r+   get_channelsr      s5     BzN''))**H//h////r*   z/api/v1/adbreaksrs   c                 n    i }| |  |d<   t           d                             |          }d |D             S )z5List all ad breaks with optional availability filter.Nrq   	ad_breaksc                 ,    g | ]}t          |          S r)   r   r   s     r+   r   z get_adbreaks.<locals>.<listcomp>   r   r*   )r   r   )rs   r.   adbreakss      r+   get_adbreaksr      sF     E(=i+##E**H//h////r*   z/api/v1/channels/{channel_id}r`   c                     t           j                            d| i          }|st          dd          t	          |          S )zGet single channel by ID.r`     zChannel not foundstatus_codedetail)r   r   find_oner   rT   )r`   r/   s     r+   get_channelr      sI     k""L*#=>>G I4GHHHH!!!r*   z/api/v1/programsr/   datec                 Z   i }| r| |d<   |ri	 t          j        |          }t          j        |          }|                    ddd          }||d|d<   n# t          $ r t	          dd	          w xY wt          t          j                            |                    }d
 |D             S )z0Fetch EPG programs by channel and optional date.r`      ;   hourminutesecondz$gtez$lterj     #Invalid date format. Use YYYY-MM-DDr   c                 ,    g | ]}t          |          S r)   r   r   ps     r+   r   z get_programs.<locals>.<listcomp>   r   r*   )	r   fromisoformatreplace
ValueErrorr   r   r   programsr   )r/   r   r.   startendr   s         r+   get_programsr      s     E &%l _	_*400E(..C++2b+<<C+0#">">E, 	_ 	_ 	_C8]^^^^	_ BK$$U++,,H//h////s   AA A2z/api/v1/programs/{program_id}rg   c                     t           j                            d| i          }|st          dd          t	          |          S )Nrg   r   zProgram not foundr   )r   r   r   r   rT   )rg   rx   s     r+   get_programr      sG    k""L*#=>>G I4GHHHH!!!r*   z/api/v1/inventory.zChannel ID (e.g., al_aoula))r   zDate in YYYY-MM-DDzRegion (e.g., France)regionc                    	 t          j        |          }|                    ddd          }n# t          $ r t	          dd          w xY wt          t          j                            | ||dd                    }d	 |D             }|sg S t          t          j	                            d
d|ii                    }g }|D ]}	t          |	          }
t          j                            d|	d         i          }|rt          |          |
d<   |rCt          j                            |	d         d| dddd          }|rt          |          |
d<   |                    |
           |S )z8Return ad inventory by channel/date and optional region.r   r   r   r   r   r   r   )r`   rj   c                     g | ]
}|d          S rg   r)   r   s     r+   r   z!get_inventory.<locals>.<listcomp>   s    555q1\?555r*   rg   $ininventory_idr]   price^$iz$regexz$options)r   r   rC   )r   r   r   r   r   r   r   r   r   r   rT   inventory_pricesr   audience_dataappend)r/   r   r   r   r   r   program_idsr   resultsadad_datar   rC   s                r+   get_inventoryr      s   [&t,,mmBrm:: [ [ [4YZZZZ[ BK$$$c22& &    H 65H555K 	R\&&uk6J'KLLMMIG    ###,,nb>O-PQQ 	4,U33GG 	>'00 "= 1%2]]]DD2 2  H  >&3H&=&=
#wNs	   ,/ Az/api/v1/pricingzInventory/Ad Break IDr   c                     t           j                            d| i          }|st          dd          t	          |          S )z2Get pricing info for a given ad break (inventory).r   r   z'Pricing not found for this inventory IDr   )r   r   r   r   rT   )r   r   s     r+   get_pricingr      sJ     ((.,)GHHE _4]^^^^r*   z/api/v1/book_ad)embedc                    t           j                            d| i          }|st          dd          |                    dd          rt          dd          t           j                            d| id	dd
ii           d| dS )zMark an ad break as sold.r]   r   zAd break not foundr   rq   Fr   zThis ad is already sold$setTzAd booked successfully)r#   r   )r   r   r   r   r}   
update_one)r   ad_breaks     r+   book_adr      s     |$$m\%BCCH J4HIIII||Iu%% O4MNNNNL]L9FYPTDU;VWWW/NNNr*   z/api/v1/audiencec                     i }| r| |d<   |rd| ddd|d<   t          t          j                            |                    }d |D             S )z+Fetch audience data by inventory or region.r   r   r   r   r   r   c                 ,    g | ]}t          |          S r)   r   )r   ds     r+   r   z get_audience.<locals>.<listcomp>  s     +++M!+++r*   )r   r   r   r   )r   r   r.   r"   s       r+   get_audiencer     so     E - ,n E%2]]]DDh %%e,,--D++d++++r*   z/api/v1/adcp/productsrequestc           	         	 | j         rt          j        | j                   nt          j                    }| j        rt          j        | j                  n|t          d          z   }d||di}| j        r
| j        |d<   t          t          j	        
                    |                    }d |D             }t          t          j        
                    d|idd	                    }g }|D ]ۊt          fd
|D             d          }|s!t          j                            d|d         i          }	|	sKt          j                            dd         i          }
| j                            d          r(|
r&|
                    dd          | j        d         k    rt%          ||	|
          }|                    |           t)          d|t+          |          | j        ddt+          |           d| j         d          S # t.          $ r+}t)          ddt1          |                     cY d}~S d}~ww xY w)zY
    ADCP Task: get_products
    Natural language product discovery across inventory
       )daysrj   r   r`   c                     g | ]
}|d          S r   r)   r   s     r+   r   z%adcp_get_products.<locals>.<listcomp>(  s    9991q999r*   r   F)rg   rq   c              3   @   K   | ]}|d          d          k    |V  dS )rg   Nr)   )r   r   r~   s     r+   	<genexpr>z$adcp_get_products.<locals>.<genexpr>3  s6      \\!1\?glF[3[3[A3[3[3[3[\\r*   Nr   r]   
max_budgetrn   r   	completed)productstotalr.   Found z products matching ''rZ   failedzProduct discovery failed: r    r#   )r0   r   r   nowr1   r	   r/   r   r   r   r   r   nextr   r   r   r2   r}   r   r   r[   lenr.   	Exceptionr'   )r   r0   r1   r.   r   r   r   r   rx   r/   r   producter~   s                @r+   adcp_get_productsr     s   9
AHARfH*7+<===X`XdXfXf	=D_o((999R[^gmn^o^o^oRo 9g>>
 ? 	2")/E, ((//0099999 ** +.,
 ,
    	   	% 	%G\\\\x\\\^bccG k**L',:O+PQQG ,55~w}G]6^__J ""<00  *..q"A"AGOT`Da"a"a27GWjYYGOOG$$$$#$X  
 QS]]PPPPP
 
 
 	
  
 
 
#9Q99
 
 
 	
 	
 	
 	
 	
 	

s   HH 
I  H;5I ;I z/api/v1/adcp/media-buyc                    	 d | j         D             }t          t          j                            dd|ii                    }t          |          t          |          k    rt          dd          S d |D             }|rt          dd	d
 |D             id          S dt          j                    	                    d           }|| j
        | j        |t          j        | j                  t          j        | j                  | j        | j        | j        | j        dt          j                    t          j                    d}t          j                            |           t          j                            dd|iidd|di           t          dt/          |          d| j
         d          S # t0          $ r+}t          ddt3          |                     cY d}~S d}~ww xY w)zI
    ADCP Task: create_media_buy
    Create a new media buy campaign
    c                     g | ]
}|d          S )
package_idr)   )r   pkgs     r+   r   z)adcp_create_media_buy.<locals>.<listcomp>]  s    EEESs<(EEEr*   r]   r   r   zSome packages are not availabler   c                 >    g | ]}|                     d d          |S )rq   F)r}   r   abs     r+   r   z)adcp_create_media_buy.<locals>.<listcomp>k  s+    CCCr"&&E*B*BCCCCr*   zinput-requiredunavailable_packagesc                     g | ]
}|d          S )r]   r)   r   s     r+   r   z)adcp_create_media_buy.<locals>.<listcomp>o  s    .P.P.PRr-/@.P.P.Pr*   z.Some packages are already sold. Please review.rZ   mb_%Y%m%d%H%M%Sactive)rN   r5   r6   r7   r8   r9   r:   r<   r>   r?   r    
created_at
updated_atr   T)rq   rN   r   zMedia buy 'z' created successfullyzMedia buy creation failed: N)r7   r   r   r   r   r   r[   r   r   strftimer5   r6   r   r8   r9   r:   r<   r>   r?   rX   
media_buys
insert_oneupdate_manyrT   r   r'   )r   package_idsr   soldrN   	media_buyr   s          r+   adcp_create_media_buyr   U  sZ   <
EEG4DEEE **E;/,
    	 y>>S----'9    DCYCCC 	'',.P.P4.P.P.PQH    GX\^^44^DDFF(L!,#"01CDD .w/?@@n(!,L"/++"/++
 
	  	  +++ 	  UK01|DDE	
 	
 	

 $y))F',FFF
 
 
 	
  
 
 
#:#a&&::
 
 
 	
 	
 	
 	
 	
 	

s+   A1F7 4+F7  DF7 7
G, G'!G,'G,z./api/v1/adcp/media-buy/{media_buy_id}/deliveryrN   c           
      b   	 t           j                            d| i          }|st          dd          t	          t           j                            d| i                    }t          |          }|}| |                    dd          |||dk    r||z  dz  nd|dk    r|                    d	d          ||z  z  nd|                    d	d          d
d |D             d}t          d|d|            S # t          $ r+}t          ddt          |                     cY d}~S d}~ww xY w)zP
    ADCP Task: get_media_buy_delivery
    Get campaign performance metrics
    rN   r   Media buy not foundr   r    r   r   d   r:   )total_spotsdelivered_spotscompletion_ratebudget_spentbudget_totalc                 ,    g | ]}t          |          S r)   r   r   s     r+   r   z%adcp_get_delivery.<locals>.<listcomp>  s     AAA=,,AAAr*   )rN   r    metrics
placementsr   zDelivery data for rZ   r   z"Failed to retrieve delivery data: r   N)r   r   r   r   r   r   r   r   r}   r[   r   r'   )rN   r   r   r   r   delivery_datar   s          r+   adcp_get_deliveryr    s   %
M**NL+IJJ	 	OC8MNNNN **L,
    	
 )nn% )mmHh77*#2LWZ[OOOk$AC$G$Gab`kno`o`o	h : :oP[>[ \ \uv )h : :  BAyAAA
 
 $777
 
 
 	
  
 
 
#AQAA
 
 
 	
 	
 	
 	
 	
 	

s   C6C9 9
D. D)#D.)D.z/api/v1/adcp/signals/discoverc                 :   	 | j                                                                         }g }t          t          j                                                  }|D ]}d|                    d           d|                    dd           dd|                    d           dd	|                    d
d          |                    dd          |                    di           |                    dd          dt          |          d}|	                    |           t          d|dd         t          |          | j         ddt          |           d          S # t          $ r+}t          ddt          |                     cY d}~S d}~ww xY w)zK
    ADCP Task: discover_signals
    Natural language signal discovery
    sig_rR   z
Audience: r   UnknownrC   zAudience in z with demographicsinternalimpressionsr   	age_rangez18-65gender_split)r  genderr   )rI   r5   rv   r   providerscaledemographicsr|   r   N   )signalsr   r.   r   z signalsrZ   r   zSignal discovery failed: r   )r.   lowersplitr   r   r   r   r}   rT   r   r[   r   r   r'   )r   query_keywordsr  r   audsignalr   s          r+   adcp_discover_signalsr    s   *
 !,,..4466 R-224455  	# 	#C 5CGGENN44CSWWXy%A%ACC"Scggh.?.?SSS&22!$g!>!>!ggnb99!ggh	::! !
 *#.. F NN6""""#"3B3<W  
 4S\\333
 
 
 	
  
 
 
#8A88
 
 
 	
 	
 	
 	
 	
 	

s   E"E% %
F/ FFFz/api/v1/adcp/signals/activatec                    	 dt          j                                        d           }|| j        d | j        D             | j        dt          j                    d}t          j        	                    |           t          dt          |          dt          | j                   d	          S # t          $ r+}t          d
dt          |                     cY d}~S d}~ww xY w)zQ
    ADCP Task: activate_signal
    Activate signal on decisioning platforms
    act_r   c                     g | ]
}|d          S )platform_idr)   r   s     r+   r   z(adcp_activate_signal.<locals>.<listcomp>  s    FFFq!M*FFFr*   r   )activation_idrI   rJ   rK   r    activated_atr   zSignal activated on z
 platformsrZ   r   zSignal activation failed: r   N)r   r   r   rI   rJ   rK   rX   r   signal_activationsr   r[   rT   r   r   r'   )r   r   
activationr   s       r+   adcp_activate_signalr$    s    
Hx|~~66~FFHH* *FFG4EFFFn$O--
 

 	((444#z**M3w/@+A+AMMM
 
 
 	
  
 
 
#9Q99
 
 
 	
 	
 	
 	
 	
 	

s   B/B2 2
C'< C"C'"C'z/api/v1/adcp/creatives/syncc                 p   	 t           j                            d| j        i          }|st	          dd          g }| j        D ]}dt          j                                        d           }|| j        |d         | j	        t          j
                    d}t           j                            |           |                    |           t          d	|t          |          d
dt          |           d          S # t          $ r+}t          ddt!          |                     cY d}~S d}~ww xY w)zI
    ADCP Task: sync_creatives
    Upload and assign creative assets
    rN   r   r   r   cr_z%Y%m%d%H%M%S%furl)creative_idrN   r'  rP   uploaded_atr   )creative_idsr   zSynced z
 creativesrZ   r   zCreative sync failed: r   N)r   r   r   rN   r   rO   r   r   r   rP   rX   r   r   r[   r   r   r'   )r   r   r*  creativer(  creative_docr   s          r+   adcp_sync_creativesr-     s~   
M**NG<P+QRR	 	OC8MNNNN) 
	- 
	-HK 7 78H I IKKK* ' 4&2'00 L L##L111,,,,#".\9J9JKK;c,//;;;
 
 
 	
  
 
 
#5SVV55
 
 
 	
 	
 	
 	
 	
 	

s   C=D   
D5
 D0*D50D5/api/v1/adcp/propertiespublisher_domaintagsc                    	 i }| r| |d<   t          t          j                            |                    }g }|D ]}|d         |d         |                    dd          d|                    dd          |                    dd	          |                    d
ddg          |                    di           t          |          d	}|                    |           t          d|t          |          ddt          |           d          S # t          $ r+}t          ddt          |                     cY d}~S d}~ww xY w)z@
    Get publisher-owned property definitions (AdCP v2.3.0)
    r/  r`   ra   zsnrt.mar^   rb   rc   rd   re   r0  	broadcastnationalr=   )	property_idr5   r/  rv   rb   rd   r0  r=   r|   r   )
propertiesr   z
Retrieved z propertiesrZ   r   zProperty discovery failed: r   N)r   r   r   r   r}   rT   r   r[   r   r   r'   )r/  r0  r.   r   r5  r/   propr   s           r+   adcp_get_propertiesr7  H  s    
 	9(8E$%((//00
 	$ 	$G&|4/$+KK0BI$N$N##KK
D99";;y$77F[*,EFF Wb11)'22
 
D d##### *S__EE=Z===
 
 
 	
  
 
 
#:#a&&::
 
 
 	
 	
 	
 	
 	
 	

s   DD 
E E;EE/c            
          ddddddddd	d
dS )NokzADCP v2.3.0r   u'   Ad Context Protocol API is running 🚀z	/api/v1/*z-/api/v1/adcp/products, /api/v1/adcp/media-buyz/api/v1/adcp/signals/*z/api/v1/adcp/creatives/*r.  )legacyadcp_media_buyadcp_signalsadcp_creativesadcp_properties)r    apir   r#   	endpointsr)   r)   r*   r+   rootrB  v  s8     <!M488
 
  r*   )NN)N)9fastapir   r   r   r   fastapi.middleware.corsr   r   r	   typingr
   r   r   r   pydanticr   r   pymongor   bsonr   os	MONGO_URIclientr   appadd_middlewarer   r-   r4   rB   rH   rM   rT   r'   r[   r   r}   r   boolr   r   r   r   r   r   postr   r   r   r   r  r  r$  r-  r7  rB  r)   r*   r+   <module>rP     s  
 8 7 7 7 7 7 7 7 7 7 7 7 2 2 2 2 2 2 ( ( ( ( ( ( ( ( , , , , , , , , , , , , % % % % % % % %             				
 R		Y		M
 g
F     %%%    " " " " "9 " " "! ! ! ! !i ! ! !	 	 	 	 	i 	 	 	! ! ! ! !Y ! ! !    i   
    )     	 	 	C 	 	PT 	 	 	 	' ' 'Z 	0 0 0
 	0 0HTN 0 0 0 0 	())"C " " " *)" 	0 0(3- 0hsm 0 0 0 0" 	())"C " " " *)" 	5*GHHHc';<<<!E$4KLLL& &&
& SM& & & &P 	$)E#;R$S$S$S    c         
 $S 5 5 5 
O 
O# 
O 
O 
O 
O 		, 	,x} 	,Xc] 	, 	, 	, 	, 
!"">
6 >
 >
 >
 #">
@ 
"##A
? A
 A
 A
 $#A
F 	9::*
C *
 *
 *
 ;:*
` 
)**/
#9 /
 /
 /
 +*/
b 
)**
"9 
 
 
 +*
F 
'((!
!4 !
 !
 !
 )(!
N 	"##&*'
 '
sm'

3-'
 '
 '
 $#'
Z     r*   