from datetime import datetime, timezone, timedelta
from fastapi import APIRouter, HTTPException
from app.schemas.schemas import ChatRequest, LogRequest
from app.models.general_module import save_chat_log, get_history_from_db, get_a_part_status, save_username, get_username, save_daily_log, get_daily_log_from_db, check_today_daily_log_exists
from app.core.config import get_gemini_model
from google.genai import types
import json

router = APIRouter(
    prefix="/goal-skill-t/api",
    tags=["General"]
)



@router.get("/status/a-part/{session_id}")
async def get_a_part_status_api(session_id: str):
    """
    프런트에서 A/B 파트 분기용으로 호출
    """
    status = get_a_part_status(session_id)
    return {"status": status}


@router.post("/chat")
async def chat_basic(request: ChatRequest):
    try:
        # 1) A파트 상태 확인
        status = get_a_part_status(request.session_id)

        # 로그 저장 분기 및 히스토리 조회 분기
        history_rows = []
        if status == 0:
            save_chat_log(request.session_id, "user", request.message)
            history_rows = get_history_from_db(request.session_id)
        else:
            save_daily_log(request.session_id, "user", request.message)
            history_rows = get_daily_log_from_db(request.session_id)
            
        # 현재 시간 (JST)
        JST = timezone(timedelta(hours=9))
        now = datetime.now(JST)
        current_date = now.date()
        current_time_str = now.strftime("%Y-%m-%d %H:%M")    
        
        # 히스토리 텍스트 변환 및 '오늘' 대화 턴 수 계산
        history_text = ""
        last_message_date = None
        last_message_datetime = None
        today_turn_count = 0  # 오늘 나눈 대화 횟수 (Bot + User)
        
        # 히스토리 텍스트 변환
        for row in history_rows:
            sender = row.get('sender', 'unknown')
            msg = row.get('message', '')
            created_at = row.get('created_at', '')
            
            row_dt = None
            if created_at:
                if isinstance(created_at, datetime):
                    row_dt = created_at
                    # DB 시간이 naive(타임존 정보 없음)라면 JST로 가정하거나 변환 필요
                    # (여기서는 단순 계산을 위해 값 그대로 사용)
                else:
                    # 문자열일 경우 파싱 시도 (필요 시 구현)
                    pass

            if row_dt:
                # row_dt가 타임존 정보가 없는(naive) 경우 UTC로 가정하고 JST로 변환
                if row_dt.tzinfo is None:
                    # UTC로 설정 후 -> JST로 변환
                    row_dt = row_dt.replace(tzinfo=timezone.utc).astimezone(JST)
                else:
                    # 이미 타임존이 있다면 JST로만 변환
                    row_dt = row_dt.astimezone(JST)

                created_at_str = row_dt.strftime("%Y-%m-%d %H:%M")
                history_text += f"[{created_at_str}] {sender}: {msg}\n"
                
                last_message_date = row_dt.date()
                last_message_datetime = row_dt # [추가] 마지막 메시지 시간 저장

                if row_dt.date() == current_date:
                    today_turn_count += 1
            else:
                history_text += f"{sender}: {msg}\n"

        # 2) 상태에 따라 다른 프롬프트 사용
        if status == 0:
            # 현재 저장된 username 확인
            existing_username = get_username(request.session_id)
            
            # 히스토리에 이름이 있는지 확인 (AI가 히스토리에서 이름을 추측하지 않도록)
            history_has_name = False
            if history_text and existing_username:
                # 히스토리에 저장된 username이 있는지 확인
                if existing_username in history_text:
                    history_has_name = True
            elif not existing_username:
                # username이 없는데 히스토리에 이름 같은 단어가 있는지 간단히 체크
                # (완벽하지 않지만, 최소한 히스토리에서 이름을 추측하지 않도록 경고)
                pass
            
            # username 관련 지시사항
            username_instruction = ""
            if existing_username:
                username_instruction = f"""
【既知のユーザー情報】
- 既に登録されているユーザー名: {existing_username}
- このユーザー名を使用して応答してください。
- 会話履歴（History）に名前が含まれていても、上記の登録されたユーザー名のみを使用してください。
"""
            else:
                username_instruction = f"""
【ユーザー名について - 重要】
- ユーザーの名前はまだ特定されていません（データベースに登録されていません）。
- 会話履歴に名前が含まれていても、それを推測したり仮定する根拠として使用しないでください。
- 絶対に名前を推測したり仮定したりしないでください。
- ユーザーが明示的に名前を言うまで「○○さん」のような呼称は使用しないでください。
- 名前を尋ねるときは、自然に「名前を教えてください」と聞いてください。
- 会話履歴（History）に過去の名前が含まれていても無視してください。 ユーザーが今この瞬間に名前を言うまで待ってください。
- '再び'、'もう一度'、'再度'といった表現は絶対に使わないでください。 最初に名前を聞くように、自然に質問してください。
"""
            
            system_prompt = f"""
【GOALSKILLについて】
- あなたはGOALSKILLのオンボーディングコーチです。
- **注意**: 以下のGOALSKILLの特徴説明は、Aパート未完了の初回利用者には**一切言及しないでください**。名前を聞은 후에만 간략하게 언급하세요。

【Aパートが未完了の場合 - 初回利用者】
- ユーザーはGOALSKILLに初めて訪れました。
- **重要**: ユーザーが挨拶（例："こんにちは"、"初めまして"、"hi"など）をする場合、GOALSKILLの特徴や詳細な説明は一切せず、簡単に自己紹介だけをしてください。
- その後すぐにユーザーの名前を尋ねてください。
- '再び'や'もう一度'のような表現は絶対に使わないでください。 初めて名前を尋ねる場合にのみ該当します。
- 名前を聞いた後、なぜ「GOAL探し」が重要なのかを簡単に説明し、ボタンを案内してください。
* 説明は簡潔に（長すぎると読みづらいので）:「○○さん、ありがとうございます。 目標が明確になると、学習を続ける動機が生まれます。 目標を見つけるために「GOAL探し」ボタンを押してみてください。 "
* 単に「ボタンを押してください」と言うだけでなく、なぜ必要なのかを簡潔に説明してください。

{username_instruction}

【応答例 - 必ずこの形式に従うこと】
- ユーザーが挨拶した場合（例：「hi」「こんにちは」）: "こんにちは！お会いできて嬉しいです。GOALSKILLのAIです。お名前を教えていただけますか？"
  * **禁止**: GOALSKILLの特徴、目的、機能などの長い説明は一切しないでください。
  * **必須**: 挨拶 + 簡潔な自己紹介 + 名前を尋ねる（3文以内）
- 名前 回答後: "○○さん、ありがとうございます。目標が明確になれば、学習を続けるモチベーションが生まれます。目標を見つけるために「GOAL探し」ボタンを押してみてください。"
  * **必須**: 簡潔に（3文以内）

すべて日本語で、温かい口調でお話しください。

【重要な注意事項】
- ユーザーが名前を入力すると、JSON形式で名前も返してください。
- 例: {{"answer": "田中さん、ありがとうございます。 「GOAL検索」ボタンを押してください。 ", "username": "田中"}}
- 名前が含まれていない場合はusernameフィールドを省略してください。
- ユーザーが名前を言う前に、絶対に名前を推測하거나仮定しないでください。
"""
        else:
            # === Part B (수정된 로직) ===
            
            # 1. 시간 차이 계산 (Hours)
            hours_diff = 0
            if last_message_datetime:
                try:
                    # now와 last_message_datetime의 차이를 시간 단위로 계산
                    # (만약 타임존 오류가 나면 .replace(tzinfo=None) 등을 고려해야 함)
                    diff = now - last_message_datetime
                    hours_diff = diff.total_seconds() / 3600
                except:
                    hours_diff = 0
            
            # 2. 리셋 여부 판단
            # Case A: 날짜가 바뀜 (어제 대화 후 오늘 처음)
            is_new_day = False
            if last_message_date and last_message_date < current_date:
                is_new_day = True
                
            # Case B: 같은 날이지만 2시간 이상 대화가 끊김 (잠시 휴식 후 복귀)
            is_long_gap = False
            if not is_new_day and hours_diff >= 2.0:
                is_long_gap = True
            
            # 3. 일지 작성 여부 확인 (DB 모듈에 함수 필요)
            # 이미 오늘 일지를 썼다면 -> true
            has_written_diary_today = check_today_daily_log_exists(request.session_id)

            # 4. 날씨 정보 처리
            weather_instruction = ""
            if request.weather_condition:
                weather_instruction = f"- 現在の天気: {request.weather_condition}\n- 会話の中で自然に天気や気温に触れてください（例：「今日は{request.weather_condition}ですね」）。"

            # 5. 시간대별 인사
            current_hour = now.hour
            greeting_instruction = ""
            if 5 <= current_hour < 11:
                greeting_instruction = "「おはようございます」"
            elif 11 <= current_hour < 17:
                greeting_instruction = "「こんにちは」"
            else:
                greeting_instruction = "「こんばんは」"

            # 5. 대화 진행 상황에 따른 지침 (Context Control)
            context_instruction = ""
            
            if is_new_day:
            # [완전 리셋] 날짜 변경 -> 새로운 하루 인사
                context_instruction = f"""
【状況: 新しい一日】
- 日付が変わりました。
- 以前の会話の内容（昨日のことなど）を引きずらず、新しい気持ちで挨拶してください。
- 挨拶: {greeting_instruction} から始めてください。
- {weather_instruction}
"""
            elif is_long_gap:
            # [부분 리셋] 같은 날, 오랜만 -> "수고했어 / 어서와" 느낌
                context_instruction = f"""
【状況: しばらく時間が空きました】
- 今日、数時間ぶりに会話が再開されました（{int(hours_diff)}時間ぶり）。
- 直前の会話の内容（数時間前の話題）を無理に続ける必要はありません。
- ユーザーが戻ってきたことを歓迎し、今の時間帯に合わせた挨拶や労いの言葉をかけてください。
- 「さっきは〜と言ってましたが」のように過去の発言を掘り返さないでください。
- 挨拶: {greeting_instruction}、または「お疲れ様です」など。
- {weather_instruction}
"""
            else:
                # 같은 날 대화가 이어지는 경우
                context_instruction = f"""
【状況: 同日の会話継続】
- 今日の会話が続いています。以前の会話の流れ（文脈）を維持してください。
- 天気の話題については、ユーザーが自ら触れない限り、こちらから重ねて質問しないでください。話の流れ（文脈）を維持してください。
"""

            # 6. 오늘의 목표 시작 유도 로직 (Nudge Logic)
            cta_instruction = ""
            if today_turn_count >= 6: # 대화가 충분히 진행되었을 때
                cta_instruction = """
- **重要: 今日の目標（Today Goal）への誘導**
- アイスブレイクが十分に温まりました。会話の最後に自然に画面下部のボタンを押して、「今日の目標」の確認とスタートを促してください。
- **誘導の文脈**: 
  1. 「さて、そろそろ今日の目標を確認して、業務をスタートしましょうか！」
  2. これから一緒に頑張りましょう、と伝えます。
- 例: "そろそろ業務開始の時間ですね！今日の目標を確認して、一緒に頑張りましょう。下のボタン（今日の目標）からスタートできますよ！🚀"
"""
            else: # 아직 대화 초반
                cta_instruction = """
- **重要: まだ誘導しない**
- **基本方針**: まだ会話の序盤です。基本的には無理に誘導せず、ユーザーとの会話を広げてください。
- **【重要例外 - 即時誘導トリガー】**: 
  ただし、**ユーザーが「さあ始めよう」「今日の目標は」「仕事する」といった前向きな意思を示した場合**は、
  **現在のターン数に関係なく、即座に**ユーザーを褒めてから、下のボタン（今日の目標）を押すよう誘導してください。
"""

            system_prompt = f"""
# Role
あなたは営業職のユーザーをサポートする親しいAIアシスタントです。

# Current Status
- 現在時刻: {current_time_str}
- 今日の会話ターン数: {today_turn_count} (目安: 3~4ターン後に今日の目標へ誘導)

# Instructions
1. **Reset & Weather**: 
   {context_instruction}

2. **Conversation Flow**:
   - ユーザーのすべての発言に対して、優しく、時にはユーモラスに反応してください。
   - どんな入力が来ても会話を途切れさせないでください。

3. **Call to Action (今日の目標)**:
   {cta_instruction}

4. **Tone**:
   - 親しみやすく、温かい（友達口調）。絵文字を使用してください。
   - 意味のまとまりごとに2〜3文を1つの吹き出しにまとめてください。（「|」で区切る）

【重要】
- 応答は必ずJSON形式で返してください。
- フォーマット: {{"answer": "AIの回答...", "show_today_goal_button": true/false}}
- `show_today_goal_button`は、あなたが「今日の目標」を促した時、あるいはユーザーが仕事モードに入った時にのみ `true` にしてください。それ以外は `false` です。
"""


        client = get_gemini_model()
        
        # 시스템 프롬프트와 히스토리, 유저 메시지를 하나로 합치기
        # 히스토리를 포함시켜서 AI가 이전 대화 맥락(몇 번 대화했는지 등)을 알 수 있게 함
        # 단, status 0일 때는 히스토리에 이름이 있어도 사용하지 않도록 명시
        history_context = f"\n\n[Conversation History]:\n{history_text}\n\n"
        full_prompt = f"{system_prompt}{history_context}ユーザー: {request.message}\nアシスタント:"
        
        # 항상 JSON 형식으로 응답 요청
        response = client.models.generate_content(
            model="gemini-2.5-flash",
            contents=[types.Content(role="user", parts=[types.Part(text=full_prompt)])],
            config={
                "response_mime_type": "application/json"
            }
        )
        
        try:
            result = json.loads(response.text)
            answer = result.get("answer", response.text.strip())
            
            # Part A (status == 0) 처리
            if status == 0:
                username = result.get("username")
                if username:
                    save_username(request.session_id, username)
                    save_chat_log(request.session_id, "bot", answer)
                    return {"answer": answer, "thinking_process": None, "show_findgoal_button": True}
                else:
                    save_chat_log(request.session_id, "bot", answer)
                    return {"answer": answer, "thinking_process": None}
            
            # Part B (status != 0) 처리
            else:
                # show_report_button 대신 show_today_goal_button으로 받기
                show_today_goal_button = result.get("show_today_goal_button", False)
                save_daily_log(request.session_id, "bot", answer)
                return {
                    "answer": answer, 
                    "thinking_process": None, 
                    # 프론트엔드에 새 변수 전달
                    "show_today_goal_button": show_today_goal_button 
                }
                
        except json.JSONDecodeError:
            # JSON 파싱 실패 시 일반 텍스트로 처리
            answer = response.text.strip()
            if status == 0:
                save_chat_log(request.session_id, "bot", answer)
            else:
                save_daily_log(request.session_id, "bot", answer)
            return {"answer": answer, "thinking_process": None}

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))



# 2. 히스토리 불러오기 (mode 파라미터 제거)
@router.get("/history/{session_id}")
async def get_history(session_id: str):  # mode 제거
    try:
        rows = get_history_from_db(session_id)  # mode 제거
        return {"history": rows}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


# 3. 프론트엔드 로그 저장 (mode 파라미터 제거)
@router.post("/log")
async def log_message(req: LogRequest):
    try:
        save_chat_log(req.session_id, req.sender, req.message)  # req.mode 제거
        return {"status": "ok"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))