o
    WTj2E                     @   s  d 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 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 dd	lmZ dd
lmZ ddlmZmZmZ ddlm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0 ddl1m2Z2 ddl3m4Z4 ddl5m6Z6 eddgdZ7dede!fddZ8e7j9de"dededededeeeeeefde	dej:dB de;de;d ed!e4d"e2fd#d$Z<e7j9d%e/dedeefde	d!e4fd&d'Z=e7j9d(e0dedeefde	d!e4fd)d*Z>e7j9d+e)deeeefd,e(d ed!e4fd-d.Z?e7j9d/e.deefd,e-d!e4fd0d1Z@e7j9d2e,dedd3d4eeeefd5ej:d6edB d ed!e4fd7d8ZAe7jBd9e'dedd:d4edd;d4edd<d4edd=d4edd>d4ed?d?d@edAd?dBdCeeeef	dej:dB dDeCdB dEeCdB dFeCdB dGeCdB dHeDdIeDd edJe6fdKdLZEe7jBdMe&deefd5ej:d efdNdOZFe7jGdPe$deefd,e#d efdQdRZHe7jGdMe+deefd5ej:d,e*d efdSdTZIe7jJdMe%deefd5ej:d efdUdVZKdS )Wz4Garment analysis, management, and listing endpoints.    N)	APIRouterDependsFileFormHTTPExceptionQuery
UploadFile)select)AsyncSession)
joinedload)GLOBAL_USER_ID)get_dbget_face_serviceget_garment_serviceget_wardrobe_service)Garment)User)GarmentBrief
ImageModelPageMeta)
FaceStatusGarmentAnalysisItemGarmentAnalyzeResponseGarmentBulkUpdateRequestGarmentBulkUpdateResponseGarmentDeleteResponseGarmentDetailGarmentListResponseGarmentSaveRequestGarmentSaveResponseGarmentUpdateRequestGarmentUpdateResponseGhostGenerateResponseGhostPreviewRequestGhostPreviewResponseStyleAnalyzeResponseStyleAnalyzeTempResponse)FaceService)GarmentService)WardrobeServicez/api/v1/garmentsgarments)prefixtagsgreturnc              	   C   sL   | j r	d| j  nd }| jrd| j nd }t| j| j| j| j| j||dS )N	/storage/idcategory_maincategory_subdescriptionr,   source_image_urlghost_image_url)source_image_pathghost_image_pathr   r1   r2   r3   r4   r,   )r-   
source_url	ghost_url r;   3/home/ubuntu/htdocs/ootd-api/app/routers/garment.py_garment_to_analysis_item)   s   r=   z/analyze)response_model.FTimageuser_iduse_face_id	auto_savedbgarment_svcface_svcc              
      s  |   I dH }t}d}	tj}
|dur4|}tj}
|tttj|kI dH }|	 }|r1|j
nd}	n-|raz|||I dH }|durP|d }|d }	tj}
ntj}
W n ty`   tj}
Y nw |rz||||I dH }W n ty } z	tdd| dd}~ww t||	|
dd	d
 |D dS z|||I dH \}}W n ty } z	tdd| dd}~ww |rd| nd  fdd
|D }t||	|
d||dS )u  Analyze garment from image.

    Args:
        auto_save: If True (default), save garments to DB immediately.
            If False, return analysis results only — use POST /save to persist later.

    Priority:
    - user_id provided → use it directly (face_status=skipped)
    - use_face_id=true → attempt face identification
    - neither → global user (face_status=skipped)
    Nunknownr@   	user_name  u   분석 실패: status_codedetailTc                 S      g | ]}t |qS r;   r=   .0r-   r;   r;   r<   
<listcomp>y       z#analyze_garment.<locals>.<listcomp>)r@   rG   face_statussavedr*   r/   c                    s*   g | ]}t d |j|j|j|j d dqS )Nr0   )r   r2   r3   r4   r,   )rO   itemr9   r;   r<   rP      s    
F)r@   rG   rR   rS   r7   r*   )readr   r   not_usedexecuter	   r   wherer1   scalar_one_or_nonenameidentifyknownrF   
ValueErrornot_detectedanalyze_and_save	Exceptionr   r   analyze_only)r?   r@   rA   rB   rC   rD   rE   image_bytesresolved_user_idrG   rR   user_resultuserresultr*   eitemssource_pathanalysis_itemsr;   rU   r<   analyze_garment<   sn    
	

rl   z/style-analyzec              
      b   |   I dH }z
||I dH }W n ty' } z	tdd| dd}~ww tdi | S )zAnalyze overall outfit style from image.

    Returns scores (1-5) for color palette, silhouette, and detail,
    plus an overall score, comment, and style tags.
    NrH      스타일 분석 실패: rI   r;   )rV   analyze_stylera   r   r%   
model_dumpr?   rD   rc   rg   rh   r;   r;   r<   style_analyze   s   
rr   z/style-analyze-tempc              
      rm   )zwContext-aware outfit style analysis (time/occasion/weather).

    Returns 5 contextual sections instead of scores.
    NrH   rn   rI   r;   )rV   analyze_style_tempra   r   r&   rp   rq   r;   r;   r<   style_analyze_temp   s   	rt   z/savebodyc              
      s   ddl m   fdd| jD }dd | jD }z|||| j| j|I dH }W n ty> } z	tdd| d	d}~ww | jpCt}t	|d
d |D dS )zSave analyzed garments to DB.

    Use after POST /analyze with auto_save=false.
    Client can selectively choose which garments to persist.
    r   GarmentAnalysisc                    s$   g | ]} |j |j|j|jd qS )r2   r3   r4   r,   rx   rN   rv   r;   r<   rP      s    z!save_garments.<locals>.<listcomp>c                 S   s   g | ]}|j qS r;   )r8   rN   r;   r;   r<   rP      s    NrH   u   저장 실패: rI   c                 S   rL   r;   rM   rN   r;   r;   r<   rP      rQ   )r@   r*   )
app.services.llm.baserw   r*   save_garmentsr7   r@   ra   r   r   r   )ru   rC   rD   ri   ghost_pathsr*   rh   rd   r;   rv   r<   rz      s&   


rz   z/ghost-previewc              
      s   ddl m} || j| j| j| jd}z|| j|| j| j	r"| j	j
ndI dH }W n; ty= } ztdt|dd}~w tyP } ztdt|dd}~w tyd } z	tdd	| dd}~ww d
| }t||dS )zGenerate ghost mannequin preview without saving to DB.

    Use after POST /analyze with auto_save=false, before POST /save.
    Returns ghost image URL and path (pass path to /save).
    r   rv   rx   N  rI     rH   u   마네킹 프리뷰 실패: r/   )r6   r8   )ry   rw   r2   r3   r4   r,   generate_ghost_previewr7   r@   image_modelvaluer^   r   strRuntimeErrorra   r$   )ru   rD   rw   rT   
ghost_pathrh   r:   r;   r;   r<   ghost_preview   s6   

r   z/{garment_id}/ghostuV   이미지 생성 모델 (gpt-image-2 / gpt-image-1.5). 미지정 시 서버 기본값.)r4   
garment_idr   c              
      s   z| || |r|jndI dH }W n; ty& } ztdt|dd}~w ty9 } ztdt|dd}~w tyM } z	tdd| dd}~ww |jrWd|j nd}t|j	|d	S )
z>Generate ghost mannequin image for a garment (slow operation).Nr|   rI   r}   rH   u   마네킹 생성 실패: r/    )r1   r6   )
generate_ghostr   r^   r   r   r   ra   r8   r"   r1   )r   r   rC   rD   garmentrh   r:   r;   r;   r<   r   !  s"   r   r   u    유저 필터 (없으면 전체)u*   대분류 필터 (top, bottom, outer, ...)u&   소분류 필터 (t-shirt, jeans, ...)u5   스타일 필터 (casual, formal, sporty, streetwear)u!   색상 필터 (black, white, ...)   )ge   d   )r   ler2   r3   stylecolorpagesizewardrobe_svcc	              
      sJ   |j || ||||||dI dH \}	}
dd |	D }t|t|||
ddS )u@   List garments with optional filters. user_id=null → all users.)r@   r2   r3   r   r   r   r   Nc                 S   sp   g | ]4}t |j|j|jr|jjnd |j|j|j|j|j	|j	r$d|j	 nd |j
|j
r0d|j
 nd |jdqS )Nr/   )r1   r@   rG   r2   r3   r4   r,   r7   r5   r8   r6   
created_at)r   r1   r@   rf   r[   r2   r3   r4   r,   r7   r8   r   rN   r;   r;   r<   rP   Z  s"    z!list_garments.<locals>.<listcomp>)r   r   total)ri   meta)list_garmentsr   r   )r@   r2   r3   r   r   r   r   rC   r   r*   r   ri   r;   r;   r<   r   B  s$   r   z/{garment_id}c                    s   | ttttjtj| kI dH }| 	 }|du r't
dddt|j|j|jr3|jjnd|j|j|j|j|j|jrGd|j nd|j|jrSd|j nd|j|jdS )zGet single garment detail.Nr|   %   아이템을 찾을 수 없습니다.rI   r/   )r1   r@   rG   r2   r3   r4   r,   r7   r5   r8   r6   r   
updated_at)rX   r	   r   optionsr   rf   rY   r1   uniquerZ   r   r   r@   r[   r2   r3   r4   r,   r7   r8   r   r   )r   rC   rg   r   r;   r;   r<   get_garmentw  s,   
r   z/bulkc                    s   | tttj| jkI dH }| }|du r tddd| tttj	| j
I dH }t|  }|D ]}| j|_q<| I dH  tt||j|jdS )z/Reassign multiple garments to a different user.Nr|   ,   대상 사용자를 찾을 수 없습니다.rI   )updated_countr@   rG   )rX   r	   r   rY   r1   r@   rZ   r   r   in_garment_idslistscalarsallcommitr   lenr[   )ru   rC   re   target_userrg   r*   r-   r;   r;   r<   bulk_update_garments  s"   "

r   c                    s   | tttj| kI dH }| }|du rtddd| tttj|jkI dH }| }|du r>tddd|j|_|	 I dH  t
|j|j|jdS )z8Update garment ownership (reassign to a different user).Nr|   r   rI   r   )r1   r@   rG   )rX   r	   r   rY   r1   rZ   r   r   r@   r   r!   r[   )r   ru   rC   rg   r   re   r   r;   r;   r<   update_garment  s     "r   c                    s   | tttj| kI dH }| }|du rtdddddlm} |j	}|j
}||I dH  | I dH  || || t| dS )zDelete a garment.Nr|   r   rI   r   )delete_image)r1   )rX   r	   r   rY   r1   rZ   r   app.utils.imager   r7   r8   deleter   r   )r   rC   rg   r   r   rj   r   r;   r;   r<   delete_garment  s    
r   )L__doc__uuidfastapir   r   r   r   r   r   r   
sqlalchemyr	   sqlalchemy.ext.asyncior
   sqlalchemy.ormr   
app.configr   app.dependenciesr   r   r   r   app.models.garmentr   app.models.userr   app.schemas.commonr   r   r   app.schemas.garmentr   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   app.services.face_servicer'   app.services.garment_servicer(   app.services.wardrobe_servicer)   routerr=   postUUIDboolrl   rr   rt   rz   r   r   getr   intr   r   patchr   r   r   r   r;   r;   r;   r<   <module>   s(   $Lb+) 





	4!! 