o
    jq|i                  
   @   sx  d dl Z d dlZd dlZd dlmZ d dlm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 d d	lmZ d d
lmZmZ d dlZd dlmZm Z m
Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z' d dl(m)Z) d dl*Z*d dl+Z+eddZ,e j-.e j-/e j-0e1dZ2e j34dZ5dZ6dd Z7e7 Z8d dl9Z9d dl:Z:dddZ;de<fddZ=e,j4dee*j> deefdefddZ?e,j@de*j>deefd e*jAdefd!d"ZBe,Cd#eefd$e<defd%d&ZDe,@d'eefdefd(d)ZEdefd*d+ZFe,@d,e
d-eefd.e	defd/d0ZGd1e<d2e<fd3d4ZHe,@d5eeee)fd6e*jIded7efd8d9ZJe,@d:ed-e
d-eeee)fd;e<d<ee	 ded7efd=d>ZKe,4d?eefdefd@dAZLe,4dBdCeefd;e<defdDdEZMe,CdFeeee)fd;e<dGe<ded7efdHdIZNe,CdJeeee)fdKe<ded7efdLdMZOe,4dNd;e<dGe<fdOdPZPdefdQdRZQe,@dSeefdefdTdUZRe,@dVe
d-eefd.e	defdWdXZSe,4dYeefdefdZd[ZTe,j@d\e*jUdeefd6e*jVdefd]d^ZWe,j4d_ee*jX deefdefd`daZYe,CdbeefdceZdefdddeZ[e,j@dfe*j\deeee)fd e*j]ded7efdgdhZ^e,j4dfee*j\ deeee)fded7efdidjZ_e,j`dke*j\deeee)fdceZd e*j]ded7efdldmZae,Cdkeeee)fdceZded7efdndoZbe,4dpeeee)fded7efdqdrZce,j4dsee*jd deeee)fdte<ded7efdudvZee,j@dpe*jddeeee)fd6e*jfded7efdwdxZge,4dyeeee)fdzeZded7efd{d|Zhe,@d}eeee)fdzeZd6e*jided7efd~dZje,@deefdeZdefddZke,Cdyeeee)fdzeZded7efddZlde<d2e<fddZmde<d2e<fddZndefddZodefddZpe,j@de*jqde
d-eefd.e	defddZre,j4dee*jq deefdefddZse,4deefdceZdefddZte,CdeefdceZdefddZudS )    N)extract_text)List)	APIRouter
UploadFileFileHTTPExceptionFormDependsstatus)FileResponse)Session)or_)genai)types)SessionLocalget_db)	UserFolderr   ChatSessionChatMessageDictionaryItemBibleQA
DailyBreadSundayMessage)get_current_userz/biblejyuku/api)prefixuploadsGEMINI_API_KEYu  
あなた(御言葉AI)は、聖書を教える教師です。
質問に対して、詳細かつ聖書の御言葉を中心に教えてください。
背景(歴史的・文化的文脈)を調べて説明することも可能です。
必ず日本語で回答してください。
c                   C   s    t dkr
td d S tjt dS )NINSERT_YOUR_API_KEY_HEREz0WARNING: Gemini API Key not set. Chat will fail.)api_key)r   printr   Client r"   r"   )/home/air/biblejyuku/back/bible_router.pyget_gemini_client&   s   r$      c                 C   s   t stdt|D ]a}z|rt jj| ||dW   S t jj| |dW   S  tyk } z:t|}d|v s9d|v re||d k red| tdd }td	|d
d|d  d| d t	
| W Y d}~q
|d}~ww dS )zV
    Wraps gemini_client.models.generate_content with retry logic for 429 errors.
    zGemini Client not initialized)modelcontentsconfig)r&   r'   429RESOURCE_EXHAUSTED      r   z'WARNING: Gemini 429 Error. Retrying in z.2fzs... (Attempt /)N)gemini_client	Exceptionrangemodelsgenerate_contentstrrandomuniformr    timesleep)
model_namer'   r(   retriesattempte	error_str
sleep_timer"   r"   r#   generate_content_with_retry3   s4   "
r?   queryc              
   C   s   t sdS z.d|  d}td|d}ddl}|j }|dr-|dd	d	 dd	d }||W S  t	yL } zt
d
|  W Y d}~dS d}~ww )ug   
    Gemini를 통해 사용자 질문에서 성경 책 이름, 장, 키워드를 추출합니다.
    NzE
        Analyze the user query for Bible reference.
        Query: "u  "
        
        Return ONLY a valid JSON object (no markdown, no ```json wrapper).
        Keys:
        - "book": (string or null) The filtered Bible book name (e.g. "マタイ", "創世記"). Normalize to simple name (remove "による福音書", "の福音書").
        - "chapter": (int or null) Chapter number if specified.
        - "keywords": (list of strings) Important keywords from the query.
        
        Example JSON: {"book": "マタイ", "chapter": 2, "keywords": ["東方", "博士"]}
        gemini-2.0-flashr9   r'   r   z```
r+   zIntent Analysis Failed: )r/   r?   jsontextstrip
startswithsplitrsplitloadsr0   r    )r@   promptresprD   rE   r<   r"   r"   r#   analyze_queryS   s&   

rM   z/dictionary)response_modeldbc                 C   s   |  t S N)r@   r   allrO   r"   r"   r#   get_dictionaryw   s   rS   z/dictionary/itemitemc                 C   sn   | ttj| jk }|r| j|_| j|_nt| j| j| jd}|| |  |	| t
| |S )Nterm
definitionverses)r@   r   filterrV   firstrW   rX   addcommitrefreshsave_db_to_excel)rT   rO   db_itemr"   r"   r#   add_dictionary_item{   s   


r`   z/dictionary/item/{term}rV   c                 C   sL   | ttj| k }|stddd|| |  t| ddiS )N  zItem not foundstatus_codedetailmessageDeleted)	r@   r   rY   rV   rZ   r   deleter\   r^   )rV   rO   r_   r"   r"   r#   delete_dictionary_item   s   
rh   z/dictionary/syncc              
   C   s>   z
t |  ddiW S  ty } ztdt|dd}~ww )z8
    Manually triggers ChromaDB rebuild from MySQL.
    re   zAI Synchronization Complete  rb   N)dictionary_servicerebuild_indexr0   r   r4   rO   r<   r"   r"   r#   sync_dictionary_to_ai   s   

rm   c                 C   sN   dd l }| t }dd |D }||}tjtd}|j	|dd d S )Nr   c                 S   s   g | ]}|j |j|jd qS ))Term
DefinitionVersesrU   .0ir"   r"   r#   
<listcomp>   s    
z$save_db_to_excel.<locals>.<listcomp>zdictionary.xlsxFindex)
pandasr@   r   rQ   	DataFrameospathjoinUPLOAD_DIRECTORYto_excelrO   pditemsdatadf
excel_pathr"   r"   r#   r^      s   
r^   z/dictionary/upload.filec           
   
      sp  | j dstddddd l}tjtd}t|d}t	
| j| W d    n1 s/w   Y  zl||}dd	 |jD |_d
|jvsMd|jvrStddd|t  | D ].\}}tt|d
  t|d  ||drt|dd nd d}|| q^|  t| ddt| diW S  ty }	 ztddt|	 dd }	~	ww )N.xlsx  Only .xlsx files are allowedrb   r   zdictionary_temp.xlsxwbc                 S      g | ]}|  qS r"   lowerrr   cr"   r"   r#   rt          z%upload_dictionary.<locals>.<listcomp>rV   rW   z/Excel must have 'Term' and 'Definition' columnsrX    rU   re   	Imported z items successfullyri   zError processing file: )filenameendswithr   rw   ry   rz   r{   r|   openshutilcopyfileobjr   
read_excelcolumnsr@   r   rg   iterrowsr4   rF   notnagetr[   r\   rj   rk   lenr0   )
r   rO   r   	temp_pathbufferr   _rowrT   r<   r"   r"   r#   upload_dictionary   s8   
&
r   contentreturnc              
   C   sd   t sdS ztdd|  d}|jdd W S  ty1 } ztd|  W Y d}~dS d}~ww )	z*Uses Gemini to extract keywords from text.r   rA   u   Extract 5 important keywords (strictly Nouns/名詞 ONLY) from this text in Japanese (日本語), separated by commas. Output ONLY the keywords. Do not include verbs or adjectives.

Text: rB   rC   ,zKeyword Extraction Error: N)r/   r?   rE   replacerF   r0   r    )r   responser<   r"   r"   r#   extract_keywords   s   r   z/create_folderrequestcurrent_userc              
      s   | j  }|rd|v sd|v rtddd|ttj|k r)tdddz!tj	tj
t|dd |t|d	 |  d
d| diW S  ty^ } ztdt|dd }~ww )Nz..r-   r   zInvalid folder namerb   zFolder already existsTexist_oknamere   zFolder 'z	' createdri   )folder_namerF   r   r@   r   rY   r   rZ   ry   makedirsrz   r{   r|   r[   r\   r0   r4   )r   rO   r   r   r<   r"   r"   r#   create_folder   s   
r   z/uploadfolderfilesc              	      s   | ttj| k }|s	 | dkrtntjt| }tj	|dd g }|D ]8}tj||j
}t|d}	t|j|	 W d    n1 sJw   Y  ||j
 t|j
| d}
||
 q)|  d|dS )NUncategorizedTr   r   )r   r   zFiles uploaded)re   	filenames)r@   r   rY   r   rZ   r|   ry   rz   r{   r   r   r   r   r   r   append	FileModelr[   r\   )r   r   rO   r   	db_folder
target_diruploaded_filesr   file_locationr   new_filer"   r"   r#   upload_files  s"   
r   z/foldersc                    s<   |  t }dd |D }d|vr|d dt|iS )Nc                 S   s   g | ]}|j qS r"   r   )rr   fr"   r"   r#   rt   #  s    z list_folders.<locals>.<listcomp>r   folders)r@   r   rQ   r   sorted)rO   r   resr"   r"   r#   list_folders   s
   r   z/videosr   c                    sr   | ttj| k }g }|D ]}|j dr+||j|j	
d|jd q|jdd dd d|iS )	N)
z.mp4z.movz.aviz.mkvz.webmz.jpgz.jpegz.pngz.gifz.webpz%Y-%m-%d)r   dater   c                 S   s   | d S )Nr   r"   )xr"   r"   r#   <lambda>2  s    zlist_videos.<locals>.<lambda>T)keyreversevideos)r@   r   rY   r   rQ   r   r   r   r   uploaded_atstrftimesort)r   rO   r   
video_listr   r"   r"   r#   list_videos'  s   
r   z /delete_file/{folder}/{filename}r   c                    s   | ttj|ktj| k }| dkrtntj	t| }tj	||}tj
|r1t| |r<|| |  ddiS )Nr   re   rf   )r@   r   rY   r   r   rZ   r|   ry   rz   r{   existsremoverg   r\   )r   r   rO   r   db_filer   	file_pathr"   r"   r#   delete_file5  s   "

r   z/delete_folder/{folder_name}r   c                    s   | dkrt ddd|ttj| k }tjt	| }tj
|r*t| |ttj| k  |r>|| |  ddiS )Nr   r   zCannot delete default categoryrb   re   rf   )r   r@   r   rY   r   rZ   ry   rz   r{   r|   r   r   rmtreer   r   rg   r\   )r   rO   r   r   folder_pathr"   r"   r#   delete_folderA  s   

r   z/download/{folder}/{filename}c                    sL   t }| dkrtjt | }tj||}tj|r"t|d|dS t|S )Nr   zapplication/octet-stream
media_typer   )r|   ry   rz   r{   r   r   )r   r   r   r   r"   r"   r#   download_fileO  s   r   c                 C   sP   dd l }| tj }dd |D }||}tjt	d}|j
|dd d S )Nr   c                 S   s"   g | ]}|j |j|j|jd qS ))QuestionAnswerKeywordsDate)questionanswerkeywords
created_atrq   r"   r"   r#   rt   `  s    
z*save_bible_qa_to_excel.<locals>.<listcomp>bible_qa.xlsxFru   )rw   r@   r2   r   rQ   rx   ry   rz   r{   r|   r}   r~   r"   r"   r#   save_bible_qa_to_excel]  s   
r   z/bible_qa/syncc              
   C   s>   z
t |  ddiW S  ty } ztdt|dd }~ww )Nre   zBibleQA Sync Completeri   rb   )rj   rebuild_qa_indexr0   r   r4   rl   r"   r"   r#   sync_bible_qak  s   

r   z/bible_qa/uploadc              
      s  | j dstddddd l}tjtd}t|d}t	
| j| W d    n1 s/w   Y  z||}dd	 |jD |_d
|jvsMd|jvrStddd|tj  | D ]B\}}t|d
  }||dr}t|dd nd}	|	strzt|}	W n   Y tj|t|d  |	d}
||
 q_|  t| ddt| diW S  ty } ztdt|dd }~ww )Nr   r   r   rb   r   zbible_qa_temp.xlsxr   c                 S   r   r"   r   r   r"   r"   r#   rt     r   z#upload_bible_qa.<locals>.<listcomp>r   r   z/Excel must have 'Question' and 'Answer' columnsr   r   r   r   r   re   r   z itemsri   )r   r   r   rw   ry   rz   r{   r|   r   r   r   r   r   r   r@   r2   r   rg   r   r4   rF   r   r   r/   r   r[   r\   rj   r   r   r0   )r   rO   r   r   r   r   r   r   r   r   rT   r<   r"   r"   r#   upload_bible_qas  sD   
(
r   z/bible_qa/exportc                 C   s<   t |  tjtd}tj|rt|dddS tddd)Nr   zAapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetr   ra   zExport failedrb   )r   ry   rz   r{   r|   r   r   r   )rO   r   r"   r"   r#   export_bible_qa  s
   r   z/bible_qa/check_similarityc           
      C   s  ze| j }tj|dd}g }|r2|D ] }||d |d |d|d dd|d d	dd
 q|radd |D }|tjtjj	
| }dd |D }|D ]}||d d|d< qTd|iW S  ty }	 ztd|	  tdt|	dd}	~	ww )z6
    Check vector similarity for a given message.
       kidscorecoveragemetadatar   Unknownr   )r   r   r   r   r   c                 S   s   g | ]}t |d  qS )r   )int)rr   mr"   r"   r#   rt         z$check_similarity.<locals>.<listcomp>c                 S   s   i | ]	}t |j|jqS r"   )r4   r   r   rr   rT   r"   r"   r#   
<dictcomp>  s    z$check_similarity.<locals>.<dictcomp>zQuestion not found in DBmatcheszSimilarity Check Error: ri   rb   N)re   rj   search_bible_qa_hybridr   r   r@   r2   r   rY   r   in_rQ   r0   r    r   r4   )
r   rO   search_queryvector_matchesr   r   idsdb_itemsid_mapr<   r"   r"   r#   check_similarity  s2   
 
r   z	/bible_qac                 C   s   |  tjtjj  S rP   )r@   r2   r   order_byr   descrQ   rR   r"   r"   r#   get_bible_qa  s   r   z/bible_qa/{id}r   c                 C   sP   | tjtjj| k }|r$|| |  t	|  t
| ddiS )Nre   rf   )r@   r2   r   rY   r   rZ   rg   r\   rj   delete_qa_item	init_bm25)r   rO   rT   r"   r"   r#   delete_bible_qa  s   


r  z/daily_breadc              
   C   s   t | d}ztrdt| j}|st| j}W n   d}Y tj| j	| j
| j| j| j| j||jd}|| |  || |S )Nr   r   )bookchapterverseend_chapter	end_verser   r   user_username)ensure_daily_bread_user_columnr/   r{   rj   tokenize_japaneser   r   r2   r   r  r  r  r  r  usernamer[   r\   r]   )rT   rO   r   r   r_   r"   r"   r#   create_daily_bread  s0   



r  c                 C   s6   t |  | tjtjj|jktjj	 
 S rP   )r  r@   r2   r   rY   r  r
  r   r   r   rQ   )rO   r   r"   r"   r#   get_daily_bread	  s
   
r  z/daily_bread/{id}c                 C   s   | tjtjj| ktjj|jk }|stddd|j	|_	|j
|_
|j|_|j|_|j|_|j|_dt|j|_|  || |S )Nra   #Item not found or permission deniedrb   r   )r@   r2   r   rY   r   r  r
  rZ   r   r  r  r  r  r  r   r{   rj   r	  r   r\   r]   )r   rT   rO   r   r_   r"   r"   r#   update_daily_bread  s$   

r  c                 C   sT   | tjtjj| ktjj|jk }|stddd|	| |
  ddiS )Nra   r  rb   re   rf   )r@   r2   r   rY   r   r  r
  rZ   r   rg   r\   )r   rO   r   r_   r"   r"   r#   delete_daily_bread+  s   

r  z/chat/sessionsc                 C   s"   |  ttj  }d|iS )Nsessions)r@   r   r   r   r   rQ   )rO   r   r  r"   r"   r#   get_sessions=  s   r  z/chat/searchqc              	   C   sR   | tttjtjkttj	d|  dtj
	d|  d  }|S )N%)r@   r   	outerjoinr   r   
session_idrY   r   titleiliker   distinctrQ   )r  rO   r   r  r"   r"   r#   search_sessionsC  s   r  c                 C   s0   t |j| jd}|| |  || |S )N)r  r  )r   r
  r  r[   r\   r]   )r   rO   r   new_sessionr"   r"   r#   create_sessionN  s
   

r  z/chat/sessions/{session_id}r  c                 C   s\   | ttj| k }|stddd| ttj| ktj	
 }|j|j|dS )Nra   Session not foundrb   )r   r  messages)r@   r   rY   r   rZ   r   r   r  r   	timestamprQ   r  )r  rO   r   sessionr  r"   r"   r#   get_session_messagesV  s
   "r   z#/chat/sessions/{session_id}/messagec           /   
      s  | ttj| k }|stdddt| d jd}|| |	  | ttj
| ktj|jktj }g }|D ]}|jdkrIdnd}	|tj|	tj|jdgd	 q@ztsdtd
t j}
td|
  |
rw|
dnd }|
r|
dnd }|
r|
dg ng }ztd j   j}td| d tj|dd}d }|r|d }|d }td|d  d|dd |dkr|}ntd |r|d d }|dd }|d!k r|d"7 }|d d d#| }t| d|d}|| |	  || d||jd$W W S W n3 ty' } ztd%|  W Y d }~nd }~w ty@ } ztd%|  W Y d }~nd }~ww d&}z| tj }g }|D ]'}|j jv ra|| qQ|D ]}|ru||jv ru||  nqcqQ|rd'd( |D }|d)d* | d+ 7 }| tj! }g }|D ][}d,} |j"#d-d&#d.d&#d/d&}!|r|r||!kr|j$|krd0} n|r|s||!krd0} | s|j%rt& fd1d2d3d( |j%'d4D D rd0} | r|| qtd5t(| d6 |rPg }"|D ]=}#|#j$ d7|#j) }$|#j*r'|#j+r'|$d8|#j* d7|#j+ 7 }$n|#j+r3|$d8|#j+ 7 }$|"d9|#j" d:|$ d;|#j  q|d<d* |" d+ 7 }| t, }%g }&|%D ]M}|j%scq[d=d( |j%'d4D }'d,} t& fd>d2|'D r~d0} | s|r|D ]sqt&fd?d2|'D rd0}  nq| r|&| q[td5t(|& d@ |&rg }(|&D ]5})dA}*t(|)j|*kr|)jd |* #d*d:dB n|)j#d*d:}+|(d9|)j- d;|+  tdC|)j-  q|dDd* |( d+ 7 }W n ty } ztdE|  W Y d }~nd }~ww  j| },|tjdtj|,dgd	g }-t.dF|-tj/t0dGdH}.|.j1}W n! ty[ } zdIt2| }tdJ|  W Y d }~nd }~ww t| d|d}|| |	  || d||jd$S )KNra   r  rb   user)r  senderr   botr&   rE   rolepartszGemini API not configuredzDEBUG: Analyzed Intent: r  r  r   z,DEBUG: Vector Search Logic Start for query: zDEBUG: Hybrid Search Query: ''r+   r   r   r   zDEBUG: [Hybrid] Closest ID: r   z	, Score: z.5fz (Threshold: > 0.01)g{Gz?z#DEBUG: [Hybrid] No matches returnedr   r   r   g      ?g      ?uz   

(※ 질문하신 내용 중 일부 키워드(예: 바울)에 대한 정보는 포함되지 않았을 수 있습니다.)ul   

⚠️ **주의: 질문하신 키워드 중 일부가 검색 결과에 없습니다.** (일치율: {:.0%}))r"  r   
message_idzBibleQA Check Error: r   c                 S   s&   g | ]}|j  d |j d |j qS )z | rU   r   r"   r"   r#   rt     s   & z send_message.<locals>.<listcomp>uJ  

[System Note]
以下の[bible塾辞書データ]を積極的に活用して回答してください。
**回答は必ず以下のフォーマットに従って作成してください：**

【説明】
(単語の意味や質問への回答を記述)

【背景】
(聖書的・歴史的背景や文脈を記述)

【関連聖句】
(関連する聖書の言葉を引用。章と節を明記すること)

【参考データ】
(回答に使用した[bible塾辞書データ]の内容をそのまま表示)
--------------------------------------------------
[bible塾辞書データ]
rC   z4
--------------------------------------------------
Fu   による福音書u   の福音書u	   福音書Tc                 3       | ]}| j v V  qd S rP   re   rr   r   r   r"   r#   	<genexpr>      zsend_message.<locals>.<genexpr>c                 S      g | ]}|r|  qS r"   rF   r,  r"   r"   r#   rt     r   r   zDEBUG: Found z relevant Breads:~[ z] u  

[System Note - Additional Context]
以下の[日ごとの糧]（ユーザーの過去の黙想記録）も参考にして、共感的に回答してください。
回答の最後には、以下のフォーマットで参照した内容を記載してください。
【参考データ（日ごとの糧）】
(回答に使用した[日ごとの糧]の内容を要約して表示。使用していない場合は「なし」と記載)
--------------------------------------------------
[日ごとの糧]
c                 S   r0  r"   r1  r,  r"   r"   r#   rt   !  r   c                 3   r*  rP   r+  r,  r-  r"   r#   r.  %  r/  c                 3   s     | ]}| v p |v V  qd S rP   r"   r,  )skr"   r#   r.  .  s    z relevant Sunday Messagesi@  z...z%DEBUG: Using Sunday Message context: uh  

[System Note - Sunday Message Context]
以下の[主日メッセージ]（過去の説教等の記録）も参考にして、回答を補強してください。
メッセージの内容と関連する質問であれば、積極的に引用してください。
回答の最後には、以下のフォーマットで参照した内容を記載してください。
【参考データ（主日メッセージ）】
(回答に使用した[主日メッセージ]のタイトルを表示。使用していない場合は「なし」と記載)
--------------------------------------------------
[主日メッセージ]
zRAG Error: rA   )system_instruction)r9   r'   r(   zError: zGemini Error: )3r@   r   rY   r   rZ   r   r   re   r[   r\   r  r   r  rQ   r"  r   r   ContentPartr   r/   r0   rM   r    r   rj   r   formatr]   r2   r   rV   r{   r   r  r   r  r   anyrH   r   r  r  r  r   r  r?   GenerateContentConfigSYSTEM_INSTRUCTIONrE   r4   )/r  r   rO   r   r  user_msghistory_msgsgemini_historymsgr&  intentsearch_booksearch_chaptersearch_keywordsr   hybrid_matchesmatch_foundmatchr   bot_contentr   bot_msgr<   context_textall_dict_itemsrelevant_dict_itemsrT   r   
dict_linesdaily_breadsrelevant_breadsr_   is_relevantdb_book_normbread_linesb	range_strsunday_messagesrelevant_messagesmsg_keywords	msg_linesr   limitsummaryfinal_messager'   r   r"   )r   r6  r#   send_message_  sZ  


"





*
$

8



r]  z /chat/messages/{message_id}/liker)  c              
   C   s2  | ttj| k }|r|jdkrtddd| ttj|jktj| k tjdktj	  }|s>tdddzF| t
jt
jj|jk }|rVddiW S t|j}t
j|j|j|d	}|| d
|_|  || t| t| ddiW S  ty } ztdt|dd }~ww )Nr#  r   zInvalid messagerb   r!  zUser question not foundre   zAlready savedr   r+   zSaved to BibleQAri   )r@   r   rY   r   rZ   r"  r   r  r   r   r2   r   r   r   r   r[   is_likedr\   r]   rj   sync_qa_itemr   r0   r4   )r)  rO   rJ  r>  r   r   new_qar<   r"   r"   r#   like_messagei  sB   

 






ra  c                 C   sh   | ttj| ktj|jk }|stddd| ttj	| k
  |
| |  ddiS )Nra   r  rb   re   rf   )r@   r   rY   r   r  r
  rZ   r   r   r  rg   r\   )r  rO   r   r  r"   r"   r#   delete_session  s   $
rb  r   c              
   C   s   t sdS z>t| d}| }W d   n1 sw   Y  d}tdtjdtjj|ddtjj|d	gd
gd}|j	r@|j	W S dW S  t
y\ } ztd|  W Y d}~dS d}~ww )z?
    Uses Gemini AI to extract text from a PDF file (OCR).
    r   rbNu   このPDFファイルに含まれるテキストを全て抽出して出力してください。要約ではなく、全文をそのままテキスト化してください。gemini-2.5-flash-liter!  application/pdf)r   	mime_typer$  r%  rB   zGemini OCR Error: )r/   r   readr?   r   r8  r9  
from_bytes	from_textrE   r0   r    )r   r   file_contentrK   r   r<   r"   r"   r#   extract_text_with_gemini  s.   
rk  rE   c              
   C   sz   t r| sdS zd| dd  d}td|d}|jr |j W S dW S  ty< } ztd|  W Y d}~dS d}~ww )	zD
    Extracts 10 important keywords from the text using Gemini.
    r   z
        Extract the 10 most important keywords or topics from the following text.
        Return ONLY a comma-separated string of keywords.
        Example: Keyword1, Keyword2, Keyword3
        
        Text:
        NiP  z	
        rd  rB   zKeyword Extraction Failed: )r/   r?   rE   rF   r0   r    )rE   rK   r   r<   r"   r"   r#   extract_keywords_with_gemini  s    
	rl  c              
   C   s~   z$|  td}| s"td |  td |   td W d S W d S  ty> } ztd|  W Y d }~d S d }~ww )Nz1SHOW COLUMNS FROM sunday_messages LIKE 'keywords'z4Adding 'keywords' column to sunday_messages table...z4ALTER TABLE sunday_messages ADD COLUMN keywords TEXTz%Column 'keywords' added successfully.zMigration Check Failed: executerE   fetchoner    r\   r0   rO   resultr<   r"   r"   r#   ensure_keywords_column_exists  s   rr  c              
   C   s   z+|  td}| s)td |  td |  td |   td W d S W d S  tyE } ztd|  W Y d }~d S d }~ww )Nz2SHOW COLUMNS FROM daily_bread LIKE 'user_username'z5Adding 'user_username' column to daily_bread table...z=ALTER TABLE daily_bread ADD COLUMN user_username VARCHAR(100)zHCREATE INDEX ix_daily_bread_user_username ON daily_bread (user_username)z*Column 'user_username' added successfully.z#DailyBread Migration Check Failed: rm  rp  r"   r"   r#   r    s   r  z/sunday_messages/uploadc                    s  | j  dstdddt| ttj  }| d| j  }t	j
td}t	j|dd t	j
||}t|d	}t| j| W d    n1 sPw   Y  d
}z(t|}tdt|  t| dk r~td t|}tdt|  W n= ty } z1td|  z
td t|}W n ty }	 ztd|	  W Y d }	~	nd }	~	ww W Y d }~nd }~ww d
}
|rtd t|}
td|
  t| j dd
|||
d}|| |  || |S )Nz.pdfr   zOnly PDF files are allowedrb   r   rV  Tr   r   r   zDEBUG: Extracted Text Length: 2   z+DEBUG: Text too short, trying Gemini OCR...z%DEBUG: Gemini Extracted Text Length: zPDF Extraction Failed: z,DEBUG: PDFMiner failed, trying Gemini OCR...zGemini Extraction Failed: zDEBUG: Extracting keywords...zDEBUG: Keywords: )r  r   r   r   )r   r   r   r   rr  r   datetimeutcnowr  ry   rz   r{   r|   r   r   r   r   r   r   r    r   rF   rk  r0   rl  r   r   r[   r\   r]   )r   rO   r  unique_filenamer   r   r   r   r<   gemini_er   new_messager"   r"   r#   upload_sunday_message  s^   


ry  z/sunday_messagesc                 C   s   |  ttj  S rP   )r@   r   r   r   r   rQ   rR   r"   r"   r#   get_sunday_messages7  s   rz  z/sunday_messages/download/{id}c                 C   sp   | ttj| k }|stdddtjt	d}tj||j
}tj|r2t|d|j
dS tddd)Nra   Message not foundrb   rV  re  r   zFile not found on server)r@   r   rY   r   rZ   r   ry   rz   r{   r|   r   r   r   r   rO   rA  r   r   r"   r"   r#   download_sunday_message;  s   r}  z/sunday_messages/{id}c                 C   sx   | ttj| k }|stdddtjt	d}tj||j
}tj|r/t| || |  ddiS )Nra   r{  rb   rV  re   rf   )r@   r   rY   r   rZ   r   ry   rz   r{   r|   r   r   r   rg   r\   r|  r"   r"   r#   delete_sunday_messageH  s   

r~  )Nr%   )vry   r   rt  pdfminer.high_levelr   typingr   fastapir   r   r   r   r   r	   r
   fastapi.responsesr   sqlalchemy.ormr   
sqlalchemyr   google.generativeaigenerativeair   googlegoogle.genair   databaser   r   r2   r   r   r   r   r   r   r   r   r   authr   schemasrj   routerrz   r{   dirnameabspath__file__r|   environr   r   r=  r$   r/   r7   r5   r?   r4   rM   DictionaryItemResponserS   postDictionaryItemCreater`   rg   rh   rm   r^   r   r   FolderRequestr   r   r   r   r   r   r   r   r   r   r   SimilarityCheckResponseSimilarityCheckRequestr   BibleQAResponser   r   r  DailyBreadResponseDailyBreadCreater  r  putr  r  r  ChatSessionModelr  CreateSessionRequestr  r   MessageRequestr]  ra  rb  rk  rl  rr  r  SundayMessageResponsery  rz  r}  r~  r"   r"   r"   r#   <module>   s    $,

 $
"-(:*&".
*("	,&"&
(&,  0& "; 