o
    @Tjy                     @   sl  d Z ddlZddlmZ ddlmZ 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mZ ddlmZ ddlmZ ddlmZ ddlmZmZmZmZ ee Z!eddgdZ"G dd de
Z#G dd de
Z$e"j%dedeefdefddZ&e"j'dedeeeefde$dedefddZ(e"j'd e#dd!eefd"e)defd#d$Z*dS )%z0Admin endpoints for data management and cleanup.    NPath)Literal)	APIRouterDepends)	BaseModel)select)AsyncSession)settings)get_dbget_garment_service)FaceEmbedding)Garment)GarmentService)ResetSummarySeedSummaryreset_all_dataseed_wardrobez/api/v1/adminadmin)prefixtagsc                   @   s"   e Zd ZU ee ed< eed< dS )OrphanCleanupResponseorphaned_filesdeleted_countN)__name__
__module____qualname__liststr__annotations__int r!   r!   1/home/ubuntu/htdocs/ootd-api/app/routers/admin.pyr   "   s   
 r   c                   @   s2   e Zd ZU dZed ed< dZee dB ed< dS )SeedRequestadd)resetr$   modeNresource_dirs)	r   r   r   r&   r   r   r'   r   r   r!   r!   r!   r"   r#   '   s   
 r#   z/reset)response_modeldbc                    s   t | I dH S )zDelete ALL data (garments, faces, non-global users) and clear storage.

    The global user is preserved but its garments are deleted.
    N)r   )r)   r!   r!   r"   	reset_all1   s   r*   z/seedreqgarment_servicec                    s4   | j rdd | j D nd}t||| j|dI dH S )u   Populate the unknown user's wardrobe from preset garment images.

    Blocking for minutes (17 images × analyze + ghost LLM calls). For POC use.
    Set mode="reset" to wipe existing data first.
    c                 S   s   g | ]}t |qS r!   r   ).0dr!   r!   r"   
<listcomp>L   s    zseed.<locals>.<listcomp>N)r&   r'   )r'   r   r&   )r+   r)   r,   dirsr!   r!   r"   seedA   s   r1   z/cleanupTdry_runc              	      s  | ttI dH }|  }| ttI dH }|  }t }|D ]}|jr1||j |j	r:||j	 q&|D ]}|j
rH||j
 q=ttj}	g }
dD ](}|	| }| s]qR|dD ]}| siqbt||	}||vry|
| qbqRd}| s|
D ]'}|	| }z|  |d7 }td| W q ty   tjd|dd	 Y qw dD ]%}|	| }| sqt|ddd
D ]}| rt| s|  qqt|
|dS )zFind and optionally delete orphaned files not referenced in DB.

    - dry_run=true (default): list orphaned files without deleting
    - dry_run=false: actually delete orphaned files
    N)	originalsghost_mannequinfacessegmentation*r      zDeleted orphan: %szFailed to delete orphan: %sT)exc_info)reverse)r   r   )executer   r   scalarsallr   setsource_image_pathr$   ghost_image_path
image_pathr   r
   
UPLOAD_DIRis_dirrglobis_filer   relative_toappendunlinkloggerinfoOSErrorwarningsortedanyiterdirrmdirr   )r2   r)   garment_resultgarmentsface_resultr5   db_pathsgfbaseorphanedsubsub_dirfilepathrelr   	full_pathr.   r!   r!   r"   cleanup_orphansU   sl   

r^   )+__doc__loggingpathlibr   typingr   fastapir   r   pydanticr   
sqlalchemyr   sqlalchemy.ext.asyncior	   
app.configr
   app.dependenciesr   r   app.models.facer   app.models.garmentr   app.services.garment_servicer   app.services.seed_servicer   r   r   r   	getLoggerr   rI   routerr   r#   deleter*   postr1   boolr^   r!   r!   r!   r"   <module>   sR    

