
    %j,<                       d 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 ddl	m	Z	m
Z
 ddlm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 ddlmZ ddlmZ ddlmZ ddl m!Z!  ejD                  e#      Z$ddZ%ddZ& G d d      Z'y)u  ReferencePhase1Service — Phase 1 (base reference) 단독 서비스.

F24.4.2 (2026-04-24): `ReferencePipelineOrchestrator.run()`의 Phase 1 루프
(batch 단위 base reference 이미지 생성 + early return)를 literal lift.

반환:
- None: Phase 1 성공 or 0건. 다음 Phase로 진행.
- Dict: Phase 1 부분 실패. orchestrator가 early return.
- raise AppError: Phase 1 전체 실패.
    )annotationsN)ThreadPoolExecutoras_completed)datetimetimezone)Path)AnyDictOptional)Session)AppError)to_relative_image_path)annotate_generated_asset)bind_current_budget)ActivityLogger)
ImageAsset)ReferencePipelineContextc                 d    t        j                  t        j                        j	                         S N)r   nowr   utc	isoformat     [/Users/manta/Documents/Projects/TheRoad-I1/backend/app/services/reference_phase1_service.py_nowr   "   s    <<%//11r   c                 <    t        t        j                               S r   )struuiduuid4r   r   r   _new_idr!   &   s    tzz|r   c                  4    e Zd ZdZ	 	 	 	 	 	 	 	 	 	 ddZddZy)ReferencePhase1Serviceu=   Phase 1: 엔티티별 base reference 이미지 병렬 생성.c                <    || _         || _        || _        || _        y r   )_db_project_id	_actor_id_logger)selfdb
project_idactor_idactivity_loggers        r   __init__zReferencePhase1Service.__init__-   s!     %!&r   c                    !"#$%&'()*+,-./ ddl m( ddlm mm!m)m+ ddlm	} t         |             }ddlm}  | j                  |j                        /|j                  }|j                   %|j"                  }|j$                  }|j&                  $|j(                  ,|j*                  }|j,                  #|j.                  "ddlm. |j4                  *|j6                  '|j8                  -|j:                  }	|j<                  }
|j>                  }|j                  &|j@                  }|jB                  }|jD                  }tG        |      D ]  \  }}|D cg c])  }|%v r#||vr||vr%|   jI                  d      |v r%|   + }}|s>|
jK                  d|jL                  |z    d	tO        |       |jL                  |        !"#$%&'()*+,-. /fd
}tQ        tS        |	tO        |                  5 }tU        |      }|D ci c]  }|jW                  ||      | }}tY        |      D ]  }	 |j[                         \  }}t]        |jI                  dd            }|j_                         r|ja                         ,|<    jb                  je                  tf              ji                  tf        jj                   j                  k(  tf        jl                  |d   k(  tf        jn                  dk(        jK                  ddi       tg        |d    j                  d|d   &tq        |d         |d   |d   |d   |jI                  d      |jI                  d      d|d         } jb                  js                  |       tu        |dg |    |    i        jb                  jw                          |xjL                  dz  c_&        |jy                  |d|d   d|d    |    i       |
jK                  d|jL                  |z    d	tO        |       d%jI                  |i       jI                  dd       |jL                  |        	 d d d         |jL                  dkD  rF|j                  |jL                  k(  r-|
j                  d!       t        d"d|j                   d#d $      |j                  dkD  rdt|        j                  d%|j                         |
j                          |jL                  |||j                  tO        |      d|j                   d&d'S y c c}w c c}w # tz        $ r|}||   }|jI                  dd      }t|        j                  d|jI                  d|      |       |j                  |t        |      d d         |xj                  dz  c_B        Y d }~wd }~ww xY w# 1 sw Y   lxY w)(Nr   )generate_and_validate_reference)GROUNDING_INPUT_DIGEST_KEYGROUNDING_INPUTS_KEYGROUNDING_REFERENCE_LABELgrounding_input_digestprovenance_of)canonical_ref_owner_types) load_printed_prop_anchor_context)reference_entity_typeentity_typeu   참조 이미지 /c           $        j                  | d   t                     }t        |      xr | j                  d      dk(  }| d   v }|D cg c]Y  }|v rS|r'|s%dj                  |i       j                  dd       n$dj                  |i       j                  dd       |   f[ }}| j                  d      xs | j                  d	      xs | d   }| j                  d	d      }| j                  d      d
k(  rz#rx#j                  d      xs i j                  | j                  d      xs d      }|r?ddlm}	  |	||      } |	||d      }t
        j                  d| j                  d             |rh| j                  d      dk(  rT|sR|D cg c](  }|v r"j                  |i       j                  dd      * }
}ddj                  |
       d}||z   }||z   }j                  | j                  d      xs d      xs dD cg c]	  }|d   f }}| d   v } !| j                  dd      ||      } | d   ||| ||z   xs d d"j                  d| d   d	      }dt               d| d   dddd d|d   d |d!|d!   d"d d#d d$d%d&t        j                  |j                  d'i       d(      d)|j                  d'i       j                  d*      d+t                j                  | j                  d      xs d      xs g        j                  | j                  d      xs d      xs g       i}| d   |fS c c}w c c}w c c}w ),Nidr9   	characteru   Base form — KEEP THIS FACE: name zReference: 
t2i_promptdescriptionpropby_propshort_idr   )build_prop_ref_prompt_overlayF)include_framinguM   visual_continuity_anchor: prop %s ref prompt overlay 적용 (canon 비변경)u'   CRITICAL — This is a VARIANT form of z, z. The reference image shows the base form. Keep the EXACT same face, bone structure, skin tone, and identity. Only change what the description below specifies.

r   bytes)is_body_identityis_null_outlookref_image_gen_phase1)r+   
episode_idoperation_type	entity_id)	gemini_cliententity_nameentity_descriptionr9   r@   
output_dirextra_referencesstyle_context
trace_metarM   
asset_type	referencestill_id	file_pathprompt_usedgeneration_modelwidthheightstatus	generatedreview_notes
validation)ensure_asciivalidation_scorescore
created_at)getsetbool2app.modules.pipeline.visual_continuity_anchor_planrE   loggerinfojoinr&   r!   jsondumpsr   )$entityentity_deps
is_variantrI   ddep_refst2idesc_anchorrE   
base_namesvariant_instructionggrounding_refsrH   ref_entity_typepipe_resultresultr2   r1   r3   _body_identity_ids_o00_char_idsdepsentity_by_idrK   rN   r0   r4   grounding_referencesr5   ref_image_mapreference_dirr8   r)   vca_prop_ctxs$                     r   _gen_refz,ReferencePhase1Service.run.<locals>._gen_refr   s    "hhvd|SU;!+.[6::m3LP[3[
"(,-"? )
 )A,> #? 6l6F6Fq"6M6Q6QRXZ\6]5^_"<#3#3Ar#:#>#>vr#J"KL"1%' )   jj.]&**]2K]vV\~zz-4 ::m,6<+//	:@bEE

:.4"6G <GSI<#T5 B017J1G 

= 9[ HQ`+6"N+6a!}:L #/"2"21b"9"="=fb"I+6  "N B$))JBWAX YP Q ( /5D-3C 366vzz*7M7SQSTZXZZ"Z /'
;Z  " $*$<3E#E "7JJ}k:%5$3#5
 >"/ &v'+ /",&.&?%HD"$ '+&6&6&0*@%+D\	 $ ') +[!9!3&4F(GTdk"DJJ{|R/P_d$e&b(I(M(Mg(V $&(-,00J1G1M2NTRT+V /0F,00J1G1M2NTRT1V%* d|V++I@"N "s   AM-M

M)max_workersrX   r?   rM      
is_primaryr<   rV   rY   rZ   r]   r_   rb   rd   )r<   r+   rU   rM   rK   rX   rY   rZ   r]   r_   rb   r   rd   reference_face)pipeline_roleinput_image_idspipeline_metadataasset_idz: r>   zRef image failed (%s): %si  u2   참조 이미지 생성 전부 실패 (API 오류)zimage.all_ref_failedu=   개 모두 실패했습니다. API 상태를 확인하세요.)codemessagestatus_codeus   참조 이미지 %d개 실패 — 합성 이미지 생성 건너뜀. resume으로 참조를 먼저 완성하세요.u,   개 실패. resume으로 재시도하세요.)r^   skippedlow_freq_skippedfailedtotalr   )F'app.modules.pipeline.ref_image_pipeliner0   3app.modules.pipeline.grounding_canonical_ref_inputsr1   r2   r3   r4   r5   .app.modules.pipeline.grounding_entity_contractr6   rf   ,app.core.steps.visual_continuity_anchor_stepr7   r&   rK   batchesr   already_donelow_freq_skip_idsr   r   ref_cpo00_char_idsbody_identity_char_idsapp.core.body_identityr8   r   rN   r   max_concurrentprogressentitiesskipped_countr   total_to_gen	enumeratere   updategenerated_countlenr   minr   submitr   r|   r   exists
read_bytesr%   queryr   filterr+   rM   r   r   addr   commitmark_completed	Exceptionri   warningmark_failedr   failed_counterrorr   complete)0r)   ctxr6   _canonical_owner_typesr7   r   r   _low_freq_skip_idsr   r   r   r   r   r   r   	batch_idxbatcheidbatch_entitiesr   executor_submit_gen_refefuturesfuturer|   fpassetexcfailed_entity
eid_failedr2   r1   r3   r}   r~   r   r   rK   rN   r0   r4   r   r5   r   r   r8   r   s0   `                              @@@@@@@@@@@@@@@@@r   runzReferencePhase1Service.run9   s   [	
 	
	
 "%%>%@!A
	
 88H8H#..Y ++'''' 22xx))(( 77@"77))))++<<<<^^
))//'' )' 2Iu-2-2c,&3l+B11 %))-8<RR S!U   "OO#C$7$7-$G#H#h-Y##\
i, i, i,V $NCDW0XY]e #6h"?KYZ>a8???A>A>Z*73F4.&,mmoV!&**[""=>99;13M#.z299&11T5E5EE&00F;4GG&11Q6 !&,!23 *%d|8H8HU`&,[&9j&<VK=P&Q(.}(=-34F-G#)(#3)/N)C-3ZZ8J-K'('-l';! U+0!1ASU !5f=Q6R :FC]<^/	 )++q0+--c&tk6+CV6?Y8Z4  !/0C0Cm0S/TTUVYZbVcUddfgsgwgwx{}  hA  hE  hE  FL  NP  hQ  gR  S//Y 4 ZYu !3l "s'7'73;N;N'NNNOP++C,<,<+==z{  aNN F    00($4**X.s/?/?.@@lm  Yz [b % .(/%2%6%6tR%@
'BMDUDUV\^hDikno**:s3x~F((A-((.k ZYsP    .T%V7T*+V7=HT/V7*V7/	V4	8A1V/	)V7/V4	4V77W	N)
r*   
OrmSessionr+   r   r,   r   r-   r   returnNone)r   r   r   zOptional[Dict[str, Any]])__name__
__module____qualname____doc__r.   r   r   r   r   r#   r#   *   s@    G
'
' 
' 	
'
 (
' 

'wr   r#   )r   r   )(r   
__future__r   rl   loggingr   concurrent.futuresr   r   r   r   pathlibr   typingr	   r
   r   sqlalchemy.ormr   r   app.core.errorsr   app.core.file_pathsr   #app.services.image_capture.annotater   app.core.image_call_budgetr   app.logging.activity_loggerr   app.models.projectr   'app.services.reference_pipeline_contextr   	getLoggerr   ri   r   r!   r#   r   r   r   <module>r      sg   	 #    ? '  & & 0 $ 6 H : 6 ) L			8	$2F Fr   