o
    Սdh~                     @   s  d 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Zdd
lZdd
lZdd
lZddlmZmZ ddlmZmZ ddlmZ dd
lZdd
lZdd
lZddlm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z& ddl'm(Z(m)Z)m*Z*m+Z+m,Z, e Z-e.e/Z0eddddd Z1edd Z2edd Z3d@ddZ4dAddZ5ed d! Z6ed"d# Z7ed$d% Z8d&d' Z9d(d) Z:d*d+ Z;ed,d- Z<edBd.d/Z=edCd1d2Z>ed3d4 Z?ed5d6 Z@edBd7d8ZAedDd:d;ZBd<d= ZCd>d? ZDd
S )Eai  Creative Management Asynchronous Tasks

Celery tasks for creative asset processing and management.
Handles file processing, optimization, compliance checking, and notifications.

Task Categories:
- File Processing: Upload, conversion, optimization
- Compliance: Automated compliance checking
- Performance: Analytics and reporting
- Notifications: Email and system notifications
- Cleanup: File cleanup and maintenance
- Batch Operations: Bulk processing tasks

Tasks:
- process_creative_file: Process uploaded creative files
- optimize_creative: Optimize creative assets
- check_compliance: Check creative compliance
- generate_thumbnails: Generate preview thumbnails
- extract_metadata: Extract file metadata
- send_approval_notification: Send approval notifications
- cleanup_old_versions: Clean up old file versions
- batch_process_creatives: Process multiple creatives
- update_performance_metrics: Update performance data
- generate_creative_report: Generate performance reports

Integrations:
- FFmpeg for video processing
- Pillow for image processing
- External compliance APIs
- Email services
- Cloud storage services
    )shared_task)	send_mail)settings)timezone)ContentFile)default_storage)render_to_string)get_user_modelN)datetime	timedelta)ImageImageOps)BytesIO   )CreativeCreativeVersionCreativeAssetCreativeApprovalCreativePerformanceCreativeComplianceCreativeFormat)get_file_metadatavalidate_creative_filegenerate_thumbnailoptimize_imagecompress_videoT   )bindmax_retriesc           
      C   s6  zt jj|d}|jstdtd|j d| d d|_|	  ||jj
g d}t|}|d d	 t|}|d d
 t|jj
}|d s]d|_|	  td|d  |d d |jdkrvt|}|d d n|jdkrt|}|d d t|}|d d d|_|	  t|dd td|j  |W S  t jy   td|    ty }	 zQtd| dt|	  zt jj|d}d|_|	  W n
 t jy   Y nw | jj| jk r	td|  | jd| jjd  d t|d!d"t|	   d#}	~	ww )$z
    Process uploaded creative file.
    
    Args:
        creative_id (int): Creative instance ID
        
    Returns:
        dict: Processing results
    idNo file to processzProcessing creative file: z (ID: )
processing)creative_id	file_pathprocessing_stepsr&   Zmetadata_extractionZthumbnail_generationis_validrejectedzFile validation failed: errorsZfile_validationimageZimage_optimizationvideoZvideo_optimizationZcompliance_checkpending_review	completedz&File processing completed successfullyz$Creative file processing completed: Creative not found: zError processing creative file : draftzRetrying creative processing: <   r   )	countdownfailedzFile processing failed: N)r   objectsgetprimary_file
ValueErrorloggerinfonamecreative_statussavepathextract_metadatadelayappendgenerate_thumbnailsr   creative_typeoptimize_image_taskoptimize_video_taskcheck_compliancesend_processing_notificationDoesNotExisterror	Exceptionstrrequestretriesr   retry)
selfr$   creativeresultsZmetadata_taskZthumbnail_taskZvalidation_resultZoptimize_taskZcompliance_taskexc rR   HC:\Users\vibe-look\OneDrive\Desktop\Adtlas_V\src\apps\creatives\tasks.pyprocess_creative_fileD   sz   






rT   c              
   C   s  zIt jj| d}|jsddiW S td|j  t|jj}d|v r(|d |_	d|v r1|d |_
d|v r:|d |_|  td|j  |W S  t jy_   td	|   dd
i Y S  ty } ztd|  dt|  dt|iW  Y d}~S d}~ww )z
    Extract metadata from creative file.
    
    Args:
        creative_id (int): Creative instance ID
        
    Returns:
        dict: Extracted metadata
    r   rH   r!   z"Extracting metadata for creative: 	file_sizeduration
dimensionsz!Metadata extracted for creative: r.   Creative not foundz'Error extracting metadata for creative r/   N)r   r4   r5   r6   r8   r9   r:   r   r=   rU   rV   rW   r<   rG   rH   rI   rJ   )r$   rO   metadatarQ   rR   rR   rS   r>      s.   



r>   c              
   C   s`  zut jj| d}|jsddiW S td|j  d}|jdkr't|jj	}n|jdkr2t
|jj	}|rqt|d}|jjd	|j d
t| dd W d   n1 sVw   Y  t| td|j  d|jjdW S ddiW S  t jy   td|   ddi Y S  ty } ztd|  dt|  dt|iW  Y d}~S d}~ww )z
    Generate thumbnails for creative.
    
    Args:
        creative_id (int): Creative instance ID
        
    Returns:
        dict: Thumbnail generation results
    r   rH   r!   z$Generating thumbnails for creative: Nr*   r+   rbZthumb_.jpgTr<   z"Thumbnail generated for creative: )successthumbnail_pathzCould not generate thumbnailr.   rX   z)Error generating thumbnails for creative r/   )r   r4   r5   r6   r8   r9   r:   rB   generate_image_thumbnailr=   generate_video_thumbnailopen	thumbnailr<   r    r   readosremoveurlrG   rH   rI   rJ   )r$   rO   r^   Z
thumb_filerQ   rR   rR   rS   rA      s<   





rA   ,  rh   c              
   C   s   zBt | 2}|jdv r|d}||t jj dt| 	 
  d}|j|ddd |W  d   W S 1 s;w   Y  W dS  ty_ } ztd	t|  W Y d}~dS d}~ww )
z
    Generate thumbnail for image file.
    
    Args:
        image_path (str): Path to image file
        size (tuple): Thumbnail size
        
    Returns:
        str: Path to generated thumbnail
    )ZRGBAZLAPRGB/tmp/thumb_r[   ZJPEGU   )qualityNz"Error generating image thumbnail: )r   ra   modeconvertrb   Z
ResamplingZLANCZOShashlibmd5encode	hexdigestr<   rI   r8   rH   rJ   )Z
image_pathsizeimg
thumb_pathrQ   rR   rR   rS   r_   
  s   

(r_   00:00:01c                 C   s   z<dt |    d}dd| d|dddd	d
|g}tj|ddd}|jdkr1tj	|r1|W S t
d|j  W dS  tyY } zt
dt|  W Y d}~dS d}~ww )z
    Generate thumbnail for video file using FFmpeg.
    
    Args:
        video_path (str): Path to video file
        time_offset (str): Time offset for thumbnail
        
    Returns:
        str: Path to generated thumbnail
    rk   r[   Zffmpegz-iz-ssz-vframes1z-vfz2scale=300:300:force_original_aspect_ratio=decreasez-yT)capture_outputtextr   zFFmpeg error: Nz"Error generating video thumbnail: )rp   rq   rr   rs   
subprocessrun
returncoderd   r=   existsr8   rH   stderrrI   rJ   )Z
video_pathZtime_offsetrv   cmdresultrQ   rR   rR   rS   r`   )  s(   
r`   c              
   C   P  zmt jj| d}|jr|jdkrddiW S td|j  t|jj	}|rgt
|d}|jj|jjt| dd W d	   n1 sEw   Y  t| |jj|_|  td
|j  dddW S ddddW S  t jy   td|   ddi Y S  ty } ztd|  dt|  dt|iW  Y d	}~S d	}~ww )z
    Optimize image creative.
    
    Args:
        creative_id (int): Creative instance ID
        
    Returns:
        dict: Optimization results
    r   r*   rH   z#Invalid file for image optimizationzOptimizing image creative: rZ   Tr\   Nz+Image optimization completed for creative: r]   	optimizedFNo optimization neededr]   r   messager.   rX   z Error optimizing image creative r/   )r   r4   r5   r6   rB   r8   r9   r:   r   r=   ra   r<   r   rc   rd   re   rt   rU   rG   rH   rI   rJ   )r$   rO   Zoptimized_pathZopt_filerQ   rR   rR   rS   rC   O  8   



rC   c              
   C   r   )z
    Optimize video creative.
    
    Args:
        creative_id (int): Creative instance ID
        
    Returns:
        dict: Optimization results
    r   r+   rH   z#Invalid file for video optimizationzOptimizing video creative: rZ   Tr\   Nz+Video optimization completed for creative: r   Fr   r   r.   rX   z Error optimizing video creative r/   )r   r4   r5   r6   rB   r8   r9   r:   r   r=   ra   r<   r   rc   rd   re   rt   rU   rG   rH   rI   rJ   )r$   rO   Zcompressed_pathZ	comp_filerQ   rR   rR   rS   rD     r   rD   c              
   C   s  zt jj| d}td|j  | g ddg d}t|}|d | |jdv r4t	|}|d | t
|}|d | tdd	 |d D }t|d d
 }|dkr\|| d
 nd|d< |d dk|d< |d D ]}|d |dg  ql|d |_|d |_|  tjj||d rdnd|d |t dd\}	}
|
s|d rdnd|	_|d |	_||	_t |	_|	  td|j d|d dd |W S  t jy   td|   ddi Y S  ty
 } ztd|  dt|  dt|iW  Y d}~S d}~ww )z
    Check creative compliance.
    
    Args:
        creative_id (int): Creative instance ID
        
    Returns:
        dict: Compliance check results
    r   z"Checking compliance for creative: r   T)r$   checksscoreis_compliantissuesr   r*   r+   c                 s   s    | ]}|d  V  qdS )r   NrR   ).0checkrR   rR   rS   	<genexpr>  s    z#check_compliance.<locals>.<genexpr>d   r   P   r   r   	compliantnon_compliant)compliance_statuscompliance_scorecompliance_data
checked_at)rO   defaultsz)Compliance check completed for creative: z	 (Score: z.1fr"   r.   rH   rX   z'Error checking compliance for creative r/   N)r   r4   r5   r8   r9   r:   check_file_format_compliancer@   rB   check_content_compliancecheck_technical_compliancesumlenextendr   r   r<   r   get_or_creater   nowr   r   r   rG   rH   rI   rJ   )r$   rO   Zcompliance_resultsZformat_checkZcontent_checkZtechnical_checkZtotal_scoreZ	max_scorer   
compliancecreatedrQ   rR   rR   rS   rE     sb   	






 rE   c              
   C   s  ddg d}z| j sd|d< |d d |W S tj| j jd  }g d	g d
g dddgg dd}| j|v rT||| j vrT|d  d8  < |d d|  | jrk| jdkrk|d  d8  < |d d | jdkr| j	rt
t| j	d\}}|dks|dkr|d  d8  < |d d |W S  ty } z"tdt|  d|d< |d dt|  |W  Y d}~S d}~ww )z
    Check file format compliance.
    
    Args:
        creative (Creative): Creative instance
        
    Returns:
        dict: Format compliance results
    Zfile_formatr   Z
check_typer   r   r   r   r   zNo file uploadedr   )r[   .jpeg.png.gif.webp)z.mp4z.movz.aviz.webm)z.mp3z.wavz.aacz.ogg.htmlz.htm)r[   r   r   r   r   r   )r*   r+   audiohtmlbanner   zInvalid file extension: i      zFile size exceeds 50MB limitr*   xi   
   z'Image dimensions exceed 4096x4096 limitz'Error in file format compliance check: zError checking file format: N)r6   r@   rd   r=   splitextr:   lowerrB   rU   rW   mapintsplitrI   r8   rH   rJ   )rO   r   file_extallowed_extensionswidthheightrQ   rR   rR   rS   r   	  sH   
r   c              
   C   s   ddg d}zddl }|d d}|dk r!||d	< |d
 d |W S  tyQ } z"tdt|  d|d	< |d
 dt|  |W  Y d}~S d}~ww )z
    Check content compliance using external API.
    
    Args:
        creative (Creative): Creative instance
        
    Returns:
        dict: Content compliance results
    contentr   r   r   Nr   _   r   r   r   z%Content may violate platform policiesz#Error in content compliance check: zError checking content: )timesleepr@   rI   r8   rH   rJ   )rO   r   r   Zcontent_scorerQ   rR   rR   rS   r   D  s&   
r   c              
   C   s  ddg d}z| j rWz4| jdkr,t| j j}|  W d   n1 s&w   Y  n| jdkr=tj| j js=tdW n t	yV   |d  d	8  < |d
 
d Y nw | jsi|d  d8  < |d
 
d | jdv r| js|d  d8  < |d
 
d | jdkr| js|d  d8  < |d
 
d |W S  t	y } z"tdt|  d|d< |d
 
dt|  |W  Y d}~S d}~ww )z
    Check technical compliance.
    
    Args:
        creative (Creative): Creative instance
        
    Returns:
        dict: Technical compliance results
    Z	technicalr   r   r*   Nr+   zVideo file not foundr   2   r   zFile appears to be corruptedr   zMissing file size informationr   zMissing dimensions informationzMissing duration informationz%Error in technical compliance check: r   z%Error checking technical compliance: )r6   rB   r   ra   r=   verifyrd   r~   r7   rI   r@   rU   rW   rV   r8   rH   rJ   )rO   r   ru   rQ   rR   rR   rS   r   l  sH   


r   c           	   
   C   s  zOt jj| d}|jrI|jjrId|  d|j }||||jd}td|}td|}t|||t	j
|jjgdd td	|j  d
d
dW S d
dddW S  t jye   td|   ddi Y S  ty } ztdt|  dt|iW  Y d}~S d}~ww )z
    Send processing notification.
    
    Args:
        creative_id (int): Creative instance ID
        status (str): Processing status
        message (str): Notification message
        
    Returns:
        dict: Notification results
    r   zCreative Processing r/   )rO   statusr   userz-creatives/emails/processing_notification.htmlz,creatives/emails/processing_notification.txtFsubjectr   html_message
from_emailrecipient_listfail_silentlyz+Processing notification sent for creative: Tr]   
email_sentNo email addressr]   r   r   r.   rH   rX   z'Error sending processing notification: N)r   r4   r5   
created_byemailtitler:   r   r   r   DEFAULT_FROM_EMAILr8   r9   rG   rH   rI   rJ   )	r$   r   r   rO   r   contextr   plain_messagerQ   rR   rR   rS   rF     s<   

	rF   c              
   C   s>  zWt jj| d}tjj|d}|jrQ|jjrQd|  d|j }|||||jd}td|}td|}	t	||	|t
j|jjgdd td	|j  d
d
dW S d
dddW S  t jtjfy} }
 ztdt|
  dt|
iW  Y d}
~
S d}
~
w ty }
 ztdt|
  dt|
iW  Y d}
~
S d}
~
ww )a"  
    Send approval notification.
    
    Args:
        creative_id (int): Creative instance ID
        approval_status (str): Approval status
        reviewer_id (int): Reviewer user ID
        comments (str): Optional comments
        
    Returns:
        dict: Notification results
    r   	Creative r/   )rO   approval_statusreviewercommentsr   z+creatives/emails/approval_notification.htmlz*creatives/emails/approval_notification.txtFr   z)Approval notification sent for creative: Tr   r   r   zObject not found: rH   Nz%Error sending approval notification: )r   r4   r5   Userr   r   r   r:   r   r   r   r   r8   r9   rG   rH   rJ   rI   )r$   r   reviewer_idr   rO   r   r   r   r   r   rQ   rR   rR   rS   send_approval_notification  sB   

	r   r   c                 C   s  zgt  t| d }tjj|djdd}d}d}|D ]9}|jrLz|jj}|j	  ||7 }W n t
yK } ztdt|  W Y d}~nd}~ww |	  |d7 }qtd| d	| d
 d||dW S  t
y } ztdt|  dt|iW  Y d}~S d}~ww )z
    Clean up old creative versions.
    
    Args:
        days (int): Number of days to keep versions
        
    Returns:
        dict: Cleanup results
    )days)Zcreated_at__ltr   )Z"creative__versions__version_numberr   zError deleting version file: NzCleaned up z old versions, freed z bytesT)r]   deleted_countfreed_spacez Error cleaning up old versions: rH   )r   r   r   r   r4   filterexcludefilert   deleterI   r8   warningrJ   r9   rH   )r   cutoff_dateZold_versionsr   r   versionrU   rQ   rR   rR   rS   cleanup_old_versions  s@   
 
r   c               
   C   s\   zt d dddW S  ty- }  zt dt|   dt| iW  Y d} ~ S d} ~ ww )z[
    Clean up orphaned creative files.
    
    Returns:
        dict: Cleanup results
    zOrphaned file cleanup completedT)r]   r   z"Error cleaning up orphaned files: rH   N)r8   r9   rI   rH   rJ   )rQ   rR   rR   rS   cleanup_orphaned_files?  s   
r   c                 C   s   zTt | ddg d}| D ]:}zt| |d  d7  < W q tyF } z|d  d7  < |d d| dt|  W Y d	}~qd	}~ww td
|d  d |W S  tyv } ztdt|  dt|iW  Y d	}~S d	}~ww )z
    Process multiple creatives in batch.
    
    Args:
        creative_ids (list): List of creative IDs
        
    Returns:
        dict: Batch processing results
    r   )total	processedr3   r)   r   r   r3   r)   r   r/   NzBatch processing initiated for z
 creativeszError in batch processing: rH   )	r   rT   r?   rI   r@   rJ   r8   r9   rH   )Zcreative_idsrP   r$   rQ   rR   rR   rS   batch_process_creativesT  s,   
*r   c           	   
   C   sB  zit jj| d}|rt|d }nt  }dddddd}tjj	|||d	\}}tjj
|d
jtdtdtdd}|d pGd|_|d pNd|_|d pUd|_|  td|j  d|dW S  t jy   td|   ddi Y S  ty } ztdt|  dt|iW  Y d}~S d}~ww )z
    Update performance metrics for creative.
    
    Args:
        creative_id (int): Creative instance ID
        date (str): Date for metrics (YYYY-MM-DD)
        
    Returns:
        dict: Update results
    r   z%Y-%m-%di  r      g      Y@g     @o@)impressionsclicksconversionsspendrevenue)rO   dater   )rO   r   r   r   )total_impressionstotal_clickstotal_conversionsr   r   r   r   z*Performance metrics updated for creative: T)r]   r   r.   rH   rX   z$Error updating performance metrics: N)r   r4   r5   r
   strptimer   r   r   r   update_or_creater   	aggregatemodelsSumr   r   r   r<   r8   r9   r:   rG   rH   rI   rJ   )	r$   r   rO   Zmetric_dateperformance_dataperformancer   Ztotal_performancerQ   rR   rR   rS   update_performance_metricsx  sL   	
r   r   c              
   C   s   z;t jj| d}td| d|j  |dkrt|}n|dkr&t|}ntd| td|j  d|d	W S  t j	yQ   t
d
|   ddi Y S  tyr } zt
dt|  dt|iW  Y d}~S d}~ww )z
    Generate creative report.
    
    Args:
        creative_id (int): Creative instance ID
        report_type (str): Type of report to generate
        
    Returns:
        dict: Report generation results
    r   zGenerating z report for creative: r   r   zUnknown report type: zReport generated for creative: T)r]   report_datar.   rH   rX   zError generating report: N)r   r4   r5   r8   r9   r:   generate_performance_reportgenerate_compliance_reportr7   rG   rH   rI   rJ   )r$   Zreport_typerO   r   rQ   rR   rR   rS   generate_creative_report  s$   

r   c                 C   sR   | j  ddd }| j| j| j| j| jr| j| j d nddd |D dS )	z
    Generate performance report data.
    
    Args:
        creative (Creative): Creative instance
        
    Returns:
        dict: Performance report data
    z-dateNr   r   r   c                 S   s&   g | ]}|j  |j|j|jd qS ))r   r   r   r   )r   	isoformatr   r   r   )r   prR   rR   rS   
<listcomp>  s    z/generate_performance_report.<locals>.<listcomp>)creative_namer   r   r   ctrZdaily_performance)r   allorder_byr:   r   r   r   )rO   r   rR   rR   rS   r     s   
r   c                 C   s<   | j  }| j| j| j|r|j nd|r|j dS ddS )z
    Generate compliance report data.
    
    Args:
        creative (Creative): Creative instance
        
    Returns:
        dict: Compliance report data
    N)r  r   r   Zcompliance_detailsZlast_checked)r   firstr:   r   r   r   r   )rO   r   rR   rR   rS   r     s   

r   )rg   )rw   )N)r   )r   )E__doc__celeryr   django.core.mailr   django.confr   django.utilsr   django.core.files.baser   django.core.files.storager   django.template.loaderr   django.contrib.authr	   rd   jsonloggingr{   r
   r   PILr   r   ior   requestsrp   	mimetypesr   r   r   r   r   r   r   r   utilsr   r   r   r   r   r   	getLogger__name__r8   rT   r>   rA   r_   r`   rC   rD   rE   r   r   r   rF   r   r   r   r   r   r   r   r   rR   rR   rR   rS   <module>   sp    !$


d
,

3
&
2
3
R;(7
37/

#>%