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
from app.models.report_db_module import save_daily_log, get_daily_log_from_db, get_today_daily_log, check_today_daily_log_exists, check_daily_note_for_day
from app.core.config import get_gemini_model, logger
from google.genai import types
from app.services.goalskill_classifier import classify_and_save
from app.models.goalskill_module import get_current_daily, create_result_row, update_result_condition_score, get_avg_condition_score, get_recent_condition_scores, get_condition_score_for_daily, get_day_started_datetime
from app.models.chat_log_module import save_chat_log as save_to_chat_messages
import json
import re

from app.services.ai_services import generate_diagnostic_chat

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.get("/current-daily/{session_id}")
async def get_current_daily_api(session_id: str):
    """
    현재 학습 일차 + 상태 플래그를 반환
    프론트에서 새로고침 시 어느 단계까지 완료했는지 판단용
    """
    from app.models.general_module import get_onboarding_completion_flags
    from app.models.curriculum_module import get_debug_journal

    daily = get_current_daily(session_id)
    a_part_status = get_a_part_status(session_id)

    # 온보딩 완료 플래그
    onboarding_flags = get_onboarding_completion_flags(session_id)

    # A'/B/C 파트 완료 플래그
    condition_done = get_condition_score_for_daily(session_id, daily) is not None if daily > 0 else False
    diary_done = check_daily_note_for_day(session_id, daily)  # 현재 Day의 일지 작성 여부
    journal_done = get_debug_journal(session_id, daily) is not None if daily > 0 else False

    # ★ 연속 학습 판별: 현재 day 가 시작된 시각으로부터 120분 이내면 연속으로 간주.
    # 점프와 무관 (저널 생성 = daily 증가 = result row 생성 이라 어떤 경우에도 신뢰 가능),
    # 자정 가로지르는 경우도 자동 처리됨.
    CONSECUTIVE_THRESHOLD = timedelta(minutes=120)
    is_consecutive = False
    if daily > 1 and not condition_done:
        current_day_started = get_day_started_datetime(session_id, daily)
        if current_day_started:
            # MySQL DEFAULT CURRENT_TIMESTAMP 는 서버 timezone 기준 저장
            # datetime.now() 도 같은 기준이므로 차이만 쓰면 timezone 무관
            elapsed = datetime.now() - current_day_started
            if elapsed < CONSECUTIVE_THRESHOLD:
                is_consecutive = True

    return {
        "daily": daily,
        "a_part_status": a_part_status,
        "studyplan_completed": onboarding_flags["studyplan_completed"],
        "summary_completed": onboarding_flags["summary_completed"],
        "condition_done": condition_done,
        "diary_done": diary_done,
        "is_consecutive": is_consecutive,
        "journal_done": journal_done
    }


@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:
            history_rows = get_history_from_db(request.session_id)
            # Goalskill 분류: Part A, User 메시지
            await classify_and_save(session_id=request.session_id, sender="M", part="A", text=request.message)
        else:
            save_daily_log(request.session_id, "user", request.message)
            history_rows = get_today_daily_log(request.session_id)
            # Goalskill 분류: Part A', User 메시지
            classify_result = await classify_and_save(session_id=request.session_id, sender="M", part="A", text=request.message)
            
        # 현재 시간 (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 request.theme in ["mbti", "spi", "it"]:
            existing_username = get_username(request.session_id)
            ai_result = await generate_diagnostic_chat(request, history_text, existing_username)
            answer = ai_result.get("answer", "エラー")
            return_to_hub = ai_result.get("return_to_hub", False)
            end_survey_panel = ai_result.get("end_survey_panel", False)
            
            await classify_and_save(session_id=request.session_id, sender="I", part="A", text=answer)
            return {
                "answer": answer, 
                "return_to_hub": return_to_hub, 
                "end_survey_panel": end_survey_panel, 
                "thinking_process": None
            }
        elif 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）に過去の名前が含まれていても無視してください。 ユーザーが今この瞬間に名前を言うまで待ってください。
- '再び'、'もう一度'、'再度'といった表現は絶対に使わないでください。 最初に名前を聞くように、自然に質問してください。
"""
            
            # onboarding_phase 취득 (프론트에서 전달)
            onboarding_phase = getattr(request, 'onboarding_phase', 'greeting')
            
            # ============================================================
            # ★ phase별 프롬프트 — 이상적 대화 흐름에 맞춘 설계
            # greeting → name → reason → explore → findgoal
            # ============================================================
            base_rules = f"""あなたはGoalSkillの学習パートナー「トブ」です。人間の相談員として振る舞ってください。
{username_instruction}
【絶対ルール】
- 命令禁止：「～してください」→「～してみない？」「～どう？」
- ★ ユーザーの返答に対して、過剰な共感や不自然な称賛（「凄いですね！」「素敵な名前ですね」等）は絶対に避けること。代わりに、**軽くて素直な相槌**や**短い感想**（例：「あ、なるほど」「珍しいですね！」など）を挟んでください。ただし文章の語尾に「笑」の字を使うのは不自然なので避けてください。
- ★ 質問ばかり連続させず、たまに「ここまで凄くスムーズですね」や「ちょっとだけ余談なんですけど」のような**短い繋ぎの言葉（ブリッジ）**を入れて、人間らしく会話のテンポを整えてください。
- 1回の応答は短く。自然な長さで。
- 必ずJSON形式で応答：{{"answer": "ここに応答文"}}
- 吹き出しを分ける場合は「|」で区切る（最大2個）
- すべて日本語で、温かい丁寧語で（です・ます調だが堅すぎない）。

【禁止事項】
- 毎回「〇〇さん、うん、ありがとうね！」と繰り返さない
- 「はい」への過剰な感謝禁止。自然に次の話に進む
- 「初めまして」を繰り返さない（最初の挨拶で既に言った）
- 自分を「AIアシスタント」と呼ばない。あなたは血の通った「トブ」です。
- 毎ターンのように発言に名前を入れると機械的で不自然になるため、文脈上強調したい時や必要な時だけ自然な頻度で名前を呼んでください。
- ★★ ただしユーザーを呼ぶ際は、必ず「〇〇さん」と「さん」付きで呼ぶこと（呼び捨て厳禁）。例: ✅「田中さん」 ❌「田中」
"""

            if onboarding_phase == 'greeting':
                # greeting phaseはフロントで統合済み（挨拶＋名前質問を一括表示）
                # このブランチに到達することはないが、互換性のため name にリダイレクト
                onboarding_phase = 'name'

            if onboarding_phase == 'name':
                system_prompt = f"""{base_rules}
【今の状況】
あなた（トブ）が名前を聞いて、ユーザーが返答しました。

【あなたがやること — この1回の応答で全部】
1. ユーザーが名前を教えてくれた場合：
   - テンションが高すぎる不自然な称賛はせず、**自然で等身大のリアクション**（「〇〇さんですね！よろしくお願いします！」など）で受け止める。
   - ★★ GoalSkillに来た理由やきっかけは絶対に聞かないでください。次のステップは別のシステムが担当します。
   - 文末は「！」などで終わらせて、相手が返事しなくても良い空気を作ってください。
   - ★ 名前をJSON応答の `username` フィールドに入れる。

2. ユーザーが疑問を持った、または教えるのを渋った場合：
   - オーバーな共感は避け、軽く同調する（例：「あ、なるほど。突然聞かれて、なぜだろうって思いますよね」など）。
   - その後、「本名を教えるのが少し負担でしたら、私があなたを呼べるように、ニックネームだけでも教えてもらえませんか？」と人間らしく優しく聞く（この場合 `username` は含めない）。
   - もしそれでも拒否し続ける場合は、「分かりました！それではこのまま進めますね」と状況を受け入れ、`username` を「ゲスト」として返してください。

例1（名前を教えてくれた）：{{"answer": "田中さんですね！よろしくお願いします！", "username": "田中"}}
例2（疑問を持った・渋った）：{{"answer": "あ、そうか。突然聞かれたら、なぜだろうって思いますよね！| 本名を教えるのが少し負担に感じる場合、ニックネームを教えていただけませんか？"}}
例3（完全に拒否された）：{{"answer": "分かりました、無理に言わなくて大丈夫ですよ！このまま進めましょう！", "username": "ゲスト"}}
"""

            # reason phaseは削除されました（name → findgoalへ直接遷移）

            elif onboarding_phase == 'selection':
                # 클라이언트에서 넘겨준 상태값 반영
                current_explaining_text = getattr(request, 'current_explaining', 'なし')
                remaining_diagnostics = getattr(request, 'remaining_diagnostics', [])
                remaining_tests_text = " / ".join(remaining_diagnostics) if remaining_diagnostics else "なし"
                pending_curriculum = getattr(request, 'pending_curriculum_prompt', False)
                
                # 직전에 커리큘럼 제안을 했는지 여부
                curriculum_context = ""
                if pending_curriculum:
                    curriculum_context = """
★★★ 重要な文脈 ★★★
直前にトブ（あなた）がユーザーに「学習計画を一緒に整えていきましょう」と提案しています。
そのため、ユーザーが「はい」「うん」「やる」「お願い」等と肯定した場合は、
必ず action を "start_curriculum" にしてください。診断テストの開始ではありません。
"""
                
                system_prompt = f"""{base_rules}
【今の状況】
ユーザーに診断テスト（MBTI性格診断・SPI適性検査・Pythonテスト）を案内しています。
現在説明中（提案中）のテスト: {current_explaining_text}
残りのテスト: {remaining_tests_text}
{curriculum_context}

【あなたがやること — ユーザーの意図を汲み取ってJSONで返すこと】
ユーザーの返答から次に何をするべきかを判定し、`action` と `answer` を出力してください。
文脈を正しく理解し、誤って肯定と判断しないように注意してください。例:「いや、カリキュラムを進める」は明確に「カリキュラムに進む（テストをやらない）」意思です。

1. アクション判定 (`action`):
   - ユーザーが特定のテストを指名して「やる」と言った場合: "start_mbti", "start_spi", または "start_python"
   - ユーザーが「チェックする」「診断を始める」「テストをする」等と、診断の開始に同意した場合: "open_selection_panel"
   - 現在提案中のテストに対して単に「やる」「はい」と同意した場合: "start_current"
   - 現在提案中のテストに対して「やらない」「スキップする」「パス」と拒否した場合: "skip_current"
   - 「もうテストはいい」「診断は受けない」「カリキュラムに進む」等と希望した場合: "start_curriculum"
   - ユーザーが特定のテストを指定して「それは何？」と聞いたり、興味を示してテストの説明をさせる場合: "explain_mbti" または "explain_spi" または "explain_python"
   - 「どれかやりたいが迷っている」「全体的なテストの説明をしてほしい」と聞いた場合: "explain_diagnostics"
   - 全く関係ない話をした場合: "converse"

2. 返答の生成 (`answer`):
   - actionが start_curriculum の場合: 回答(answer)は必ず「いいですね！では一緒に進めていきましょう」にしてください。（他の言葉は一切追加しないこと）
   - actionが start や skip, open_selection_panel の場合: フロントエンド側で画面遷移が行われるため、「分かりました！」等の短い相槌のみでOK。
   - actionが explain_mbti / explain_spi / explain_python の場合: ユーザーが詳しく聞いてきた場合のみ詳しく説明。そうでなければ1〜2文の簡潔な紹介（例：「MBTIは性格タイプを診断するテストです。やってみますか？」）で止めること。ユーザーが要求していない情報は絶対に追加しない。
   - actionが explain_diagnostics の場合: 全体的なテストについて簡単に案内し、「どれかやってみますか？」と聞く。
   - actionが converse の場合: 短くリアクションしてから、「ちなみに診断テストはどうされますか？」と繋げる。
   
出力JSONフォーマット:
{{
    "action": "start_mbti" | "start_spi" | "start_python" | "start_current" | "skip_current" | "start_curriculum" | "explain_mbti" | "explain_spi" | "explain_python" | "explain_diagnostics" | "open_selection_panel" | "converse",
    "answer": "AIの返答テキスト"
}}
"""

            elif onboarding_phase == 'summary':
                system_prompt = f"""{base_rules}
【今の状況】
ユーザーにカスタマイズされたプロフィールとカリキュラムの提案内容（Summary）を画面に表示し、「この情報をもとに、あなたに最適化されたカリキュラムを作成しましょうか？」と尋ねた後です。

【あなたがやること — この1回の応答で全部】
1. ユーザーがカリキュラムの生成や表示内容について質問してきた場合（例：「どうやって作るの？」「AIが作るの？」）：
   - システム的な堅い説明ではなく、「はい！今までお話ししてくれた情報をもとに、私（AI）が専用の学習コースを組み立てるんですよ」と自然に答えてあげてください。
   - 答えた後、必ず「準備ができたら『作って！』や『はい』と教えてくださいね！」と案内してください。
   - JSONは `{{"answer": "...", "status": "continue"}}` を返します。

2. ユーザーがカリキュラムの作成に同意した場合（例：「はい」「作って」「お願い」など、前向きな返答）：
   - JSONは `{{"answer": "承知いたしました！すぐに準備しますね", "status": "completed"}}` だけを返してください。これをトリガーにシステムが自動で画面を切り替えます。

3. もしユーザーが関係ない話や雑談をしてきたら、軽く相槌を打ってから「ちなみにカリキュラムの準備はどうしますか？」と話題を戻してください。
"""

            else:
                system_prompt = f"""{base_rules}
ユーザーの入力に自然に応答してください。"""

        else:
            # === A' パート: コンディションチェック → デイリーチェック誘導 ===
            
            # ★★★ 重要: 全ブランチで参照されるため最初に初期化 ★★★
            _force_daily_check = False

            # ★ context_return: 도중에 돌아온 유저 처리
            if request.context_return_from:
                client = get_gemini_model()
                existing_username = get_username(request.session_id)
                username_display = f"{existing_username}さん" if existing_username else "あなた"
                context_descriptions = {
                    "curriculum": "カリキュラム学習の途中で戻ってきたようです",
                    "daily_check": "デイリーチェックの途中で戻ってきたようです",
                    "all_done": "今日の学習はすべて完了している状態です"
                }
                context_desc = context_descriptions.get(request.context_return_from, "")
                
                system_prompt = f"""あなたは親しみやすいAIチューター「トブ」です。
ユーザー名: {username_display}

【状況】{context_desc}。ユーザーが何か理由があって戻ってきた、または誤って戻ってきた可能性があります。

【あなたがやること】
1. ユーザーの発言から意図を判断する
2. もし以下のいずれかの意図がある場合、**無条件で**すぐに `start_curriculum: true` にしてください：
   - 「中断した学習を再開したい」（戻りたい、続けたい、カリキュラムに戻る、다시 학습할래, 이어서 할래 等）
   - 「間違えてボタンを押した・誤って戻った」（間違えた、ボタン押し間違えた、잘못 눌렀어, 잘못 나왔어 等）
   - 「特に理由はない・何もない」（何もない、無い、없어, 아니, 아무것도 아냐 等）
   ※ この場合、質問を深掘りしたり、新しい目標を聞いたり、理由を尋ねたりすることは**絶対にやめてください**。「はい、分かりました！それでは学習スペースに戻りましょう」等と短く同意し、すぐに `start_curriculum: true` を設定してください。
3. もし「デイリーチェックしたい」等の明確な意図がある場合 → `start_daily_check: true` を設定してください。
4. もし完全に別の雑談や具体的な感情/相談がある場合のみ、普通に短く応答してください（どちらも false）。
5. 返答は日本語で自然に、1〜2文以内で短く返すこと。

ユーザーの発言: "{request.message}"

【JSON出力のみ】
{{"answer": "...", "start_daily_check": false, "start_curriculum": false}}"""
                
                response = client.models.generate_content(
                    model="gemini-2.5-flash",
                    contents=[types.Content(role="user", parts=[types.Part(text=system_prompt)])],
                    config=types.GenerateContentConfig(
                        response_mime_type="application/json",
                        temperature=0.7
                    )
                )
                
                try:
                    result = json.loads(response.text)
                    answer = result.get("answer", "")
                    start_daily_check = result.get("start_daily_check", False)
                    start_curriculum = result.get("start_curriculum", False)
                except json.JSONDecodeError:
                    answer = response.text.strip()
                    start_daily_check = False
                    start_curriculum = False
                
                save_daily_log(request.session_id, "user", request.message)
                save_daily_log(request.session_id, "bot", answer)
                await classify_and_save(session_id=request.session_id, sender="M", part="A", text=request.message)
                await classify_and_save(session_id=request.session_id, sender="I", part="A", text=answer)
                
                return {
                    "answer": answer,
                    "thinking_process": None,
                    "start_daily_check": start_daily_check,
                    "start_curriculum": start_curriculum
                }

            # 유저 이름 가져오기
            existing_username = get_username(request.session_id)
            username_display = f"{existing_username}さん" if existing_username else "あなた"

            # 시간대별 인사
            current_hour = now.hour
            if 5 <= current_hour < 11:
                greeting_word = "おはよう"
            elif 11 <= current_hour < 17:
                greeting_word = "こんにちは"
            else:
                greeting_word = "こんばんは"

            # 일지 작성 여부 확인
            has_written_diary_today = check_today_daily_log_exists(request.session_id)

            # 날씨 정보
            weather_note = ""
            if request.weather_condition:
                weather_note = f"- 今日の天気: {request.weather_condition}（会話中に自然に触れてOK）"

            # ★ __init__이 아닌 실제 유저 입력이고 diary 미작성 → 무조건 데일리체크 전환
            is_init = (request.message == "__init__")
            # ★ 커리큘럼/데일리체크 직접 명령어 감지
            msg_normalized = request.message.replace(' ', '').replace('\u3000', '')
            is_curriculum_cmd = not is_init and any(kw in msg_normalized for kw in ['학습시작', '커리큘럼시작', '학습개시', '커리큘럼개시', '学習開始', '学習を始め', 'カリキュラム開始', 'カリキュラムを始め'])
            is_explicit_daily_cmd = not is_init and any(kw in msg_normalized for kw in ['데일리체크시작', '데일리시작', '체크시작', 'デイリーチェック開始', 'デイリーチェックを始め', 'デイリー開始'])
            if not is_init and not has_written_diary_today and not is_curriculum_cmd and not is_explicit_daily_cmd:
                _force_daily_check = True

            # 대화 진행 단계 판단
            condition_flow_instruction = ""
            if is_curriculum_cmd:
                condition_flow_instruction = """
【カリキュラム開始コマンド検出】
- ユーザーが학습시작・커리큘럼시작などの明示的なコマンドを入力しました。
- 「了解！カリキュラムをすぐに始めましょう！🎓」のような短く前向きな日本語の返答をしてください。
- 必ず `"start_curriculum": true` と `"start_daily_check": false` を返してください。
"""
            elif is_explicit_daily_cmd:
                condition_flow_instruction = """
【デイリーチェック開始コマンド検出】
- ユーザーが데일리체크시작などの明示的なコマンドを入力しました。
- 「了解！さっそくデイリーチェックを始めましょう！📝」のような短く前向きな日本語の返答をしてください。
- 必ず `"start_daily_check": true` と `"start_curriculum": false` を返してください。
"""
            elif is_init:
                # 첫 메시지: 인사만 (1 버블)
                condition_flow_instruction = f"""
【初回メッセージ - 必ずこの形式で応答】
- 時間帯に合った短く明るい挨拶（"{greeting_word}、{username_display}！✨"）のみを1つの吹き出しで応答してください。
- コンディションについてはまだ聞かないでください。
- show_report_button: false
"""
            elif request.message == "__continue_learning__":
                # ★ 같은 날 연속 학습 — 응원 멘트
                condition_flow_instruction = f"""
【連続学習メッセージ】
- ユーザーが同日内に連続で学習を続けています。素晴らしい情熱です！
- 「連続で学習するなんて、{username_display}のやる気がすごい！🔥」のような短く明るい励ましを1つの吹き出しで返してください。
- コンディションは聞かないでください。デイリーチェックについても触れないでください。
- 必ず `"start_curriculum": false` と `"start_daily_check": false` を返してください。
- 出力は1〜2文で完結させてください。
- ★★ 区切り記号「|」や「|||」は絶対に使わないでください。
"""
            elif request.message == "__start_daily__":
                # 데일리체크 버튼 클릭 시 동적 컨디션 질문
                recent_scores = get_recent_condition_scores(request.session_id)
                if recent_scores:
                    last = recent_scores[0]
                    score = last["score"]
                    
                    if score <= 2:
                        condition_action = f"前回はとても体調が優れない様子でした。「前回はかなりキツそうだったけど、今は大丈夫？無理してない？」と、心から心配するような声かけを入れて、今日の調子を聞いてください。"
                    elif score <= 4:
                        condition_action = f"前回は少し疲れている様子でした。「前回はお疲れだったみたいだけど、少しは休めたかな？」と優しく気遣いながら、今日の調子を聞いてください。"
                    elif score <= 6:
                        condition_action = f"前回は普通のコンディションでした。「前回は落ち着いた感じだったね。今日の調子はどう？」と自然に聞いてください。"
                    elif score <= 8:
                        condition_action = f"前回は元気な様子でした。「前回はすごく元気そうだったね！今日もその調子でいけるかな？」と明るく声をかけてください。"
                    else:
                        condition_action = f"前回は絶好調でした。「前回はめちゃくちゃ絶好調だったね！今日もその勢いでいってみよう！」とテンション高く今日の調子を聞いてください。"
                    
                    past_condition_note = f"""
- {condition_action}
- ★ 警告: システムの内部スコア評価（「1/10」や「コンディションレベル」などの数値）は絶対にユーザーに言わないでください。人間が友達を気遣うような、ごく自然な言葉遣いのみを使用してください。
- ★ 重要: 必ず「前回は〇〇だったね」に近い言葉を明示的に含めて話しかけてください。「昨日」ではなく「前回」と表現してください。
"""
                else:
                    past_condition_note = """
- 過去のデータがないため、シンプルに「今日のコンディションはどうかな？😊」とだけ聞いてください。無駄な推測や前回の話はしないでください。
"""
                condition_flow_instruction = f"""
【デイリーチェック開始メッセージ】
- コンディションを尋ねる質問のみを1つの吹き出しで生成してください。
- ★★ 「デイリーチェックを始めよう」「始めようか」のような前置きは絶対に不要です。いきなりコンディションを聞いてください。
- ★★ 区切り記号「|」や「|||」は絶対に使わないでください。1つの文章で完結させてください。
{past_condition_note.strip()}
- show_report_button: false
"""
            elif has_written_diary_today:
                condition_flow_instruction = """
【デイリーチェック済み】
- ユーザーは既に今日のデイリーチェックを完了しています。
- コンディションへの共感 + 褒める + 学習頑張ってと励ます。
- start_daily_check: false
"""
            elif _force_daily_check:
                condition_flow_instruction = """
【デイリーチェック移行判断 - 必須】
- ユーザーのコンディションは確認済みです。
- ユーザーからの直近のメッセージを分析し、今日のデイリーチェック（学習前の記録）を「始める」ことに同意しているか判断してください。
- ★ ユーザーが「始める」「YES」「OK」「行く」「やる」など【開始に同意】している明確な意図がある場合：
  - その場に合った短い励ましの言葉を返し、必ず `"start_daily_check": true` を返してください。
  - ★★ 注意: 「前回の振り返りと今日のデイリーチェックを始めましょう」という定型文は使わないでください。会話の流れに合った自然な言葉を使ってください。
- ★ ユーザーが「いいえ」「やめ」「後で」など【拒否・保留】している、またはまだデイリーチェックについて質問に答えていない（今初めて振る）場合：
  - デイリーチェックへの同意をさりげなく促してください。ただし「前回の振り返りと今日のデイリーチェック」という決まり文句は使わず、文脈に合った自然な誘導をしてください。
  - 必ず `"start_daily_check": false` を返してください。
- 出力は必ず1〜2文で完結させてください。
"""
            else:
                condition_flow_instruction = """
【コンディション回答後 - デイリーチェックへ誘導】
- ユーザーのコンディション回答に共感してください。
  - ポジティブ（元気、良い）→ ユーザーの言葉を拾って軽く褒める
  - ネガティブ（疲れた、眠い）→ 「そっか」と共感 + 「少しだけやってみよう」と励ます
- 共感の後、今日の学習準備に自然につなげてください。
- `"start_daily_check": false` を返してください。
- **重要**: 長い雑談はしないでください。2文で完結させてください。
- ★★ 「前回の振り返りと今日のデイリーチェック」という定型文は使わず、会話の流れに合った自然な表現で誘導してください。
"""

            system_prompt = f"""
# Role
あなたはユーザーの親しい友人であり、学習メンターです。

# Current Status
- 現在時刻: {current_time_str}
- 今日の会話ターン数: {today_turn_count}
- ユーザー名: {username_display}

# A'パートの目的
ユーザーの今日のコンディションを確認し、デイリーチェック（学習準備）へスムーズに誘導すること。
**雑談を広げず、2〜3ターンで完結させてください。**

# 会話フロー
{condition_flow_instruction}

# トーン
- 親しみやすく温かい友達口調。絵文字を適度に使用。
- 「|」で吹き出しを分割（最大2〜3個）。
- 改行(\n)ではなく「|」を使用。
{weather_note}

# Motivation（コンディションが悪い場合）
- 「休みましょう」と安易に同意しない。
- 共感 → 「5分だけやってみよう」とBaby Stepを提案 → デイリーチェックへ誘導。

【重要】
- 応答は必ずJSON形式で返してください。
- フォーマット: {{"answer": "AIの回答...", "start_daily_check": true/false, "start_curriculum": false}}
"""


        client = get_gemini_model()
        
        # 시스템 프롬프트와 히스토리, 유저 메시지를 하나로 합치기
        # 히스토리를 포함시켜서 AI가 이전 대화 맥락(몇 번 대화했는지 등)을 알 수 있게 함
        # 단, status 0일 때는 히스토리에 이름이 있어도 사용하지 않도록 명시
        history_context = f"\n\n[Conversation History]:\n{history_text}\n\n"
        
        # __init__ 메시지일 경우 AI가 자연스럽게 첫 인사를 건네도록 시스템 메시지로 치환
        if request.message == "__init__":
            user_msg_for_prompt = "システム: 初回の挨拶とコンディション確認を生成してください。"
        else:
            user_msg_for_prompt = f"ユーザー: {request.message}"
            
        full_prompt = f"{system_prompt}{history_context}\n{user_msg_for_prompt}\nアシスタント:"
        
        # 항상 JSON 형식으로 응답 요청
        response = client.models.generate_content(
            model="gemini-2.5-flash",
            contents=[types.Content(role="user", parts=[types.Part(text=full_prompt)])],
            config=types.GenerateContentConfig(
                response_mime_type="application/json"
            )
        )
        
        try:
            result = json.loads(response.text)
            answer = result.get("answer", response.text.strip())
            logger.info(f"AI Response Parsed: {result}")
            
            # Part A (status == 0) 처리
            if status == 0:
                username = result.get("username")
                chat_status = result.get("status")  # 'completed' or 'continue'
                action = result.get("action")
                
                if username:
                    save_username(request.session_id, username)
                    await classify_and_save(session_id=request.session_id, sender="I", part="A", text=answer)
                    return {"answer": answer, "thinking_process": None, "show_findgoal_button": True, "username": username, "status": chat_status, "action": action}
                else:
                    await classify_and_save(session_id=request.session_id, sender="I", part="A", text=answer)
                    return {"answer": answer, "thinking_process": None, "status": chat_status, "action": action}
            
            # Part B (status != 0) 처리 — A' パート
            else:
                # ★ AI가 판단한 start_daily_check / start_curriculum 값을 신뢰
                start_daily_check = result.get("start_daily_check", False)
                start_curriculum = result.get("start_curriculum", False)

                save_daily_log(request.session_id, "bot", answer)
                # Goalskill 분류: Part A'(같은 A파트), AI 응답
                await classify_and_save(session_id=request.session_id, sender="I", part="A", text=answer)
                
                # A' パート終了 = デイリーチェック誘導時 → 48テーブルから平均集計してresultに保存
                if start_daily_check:
                    current_daily = get_current_daily(request.session_id)
                    if current_daily > 0:
                        avg_score = get_avg_condition_score(request.session_id)
                        if avg_score is not None:
                            update_result_condition_score(request.session_id, current_daily, avg_score)
                            logger.info(f"[A' 완료] condition_score={avg_score} → result(daily={current_daily})")
                
                return {
                    "answer": answer, 
                    "thinking_process": None, 
                    "start_daily_check": start_daily_check,
                    "start_curriculum": start_curriculum
                }
                
        except json.JSONDecodeError:
            # JSON 파싱 실패 시 일반 텍스트로 처리 및 불필요한 괄호/따옴표 제거
            raw_text = response.text.strip()
            raw_text = re.sub(r'^```json\s*', '', raw_text)
            raw_text = re.sub(r'^```\s*', '', raw_text)
            raw_text = re.sub(r'```$', '', raw_text).strip()
            
            if raw_text.startswith('{') and '"answer"' in raw_text:
                match = re.search(r'"answer"\s*:\s*"(.*)"\s*}?$', raw_text, re.DOTALL)
                if match:
                    answer = match.group(1).strip()
                else:
                    answer = raw_text.replace('{"answer":', '').strip(' "\'{}\n\r\t')
            else:
                answer = raw_text
            
            if status == 0:
                save_chat_log(request.session_id, "bot", answer)
                save_to_chat_messages(request.session_id, answer, "I", "general")
                # Goalskill 분류: Part A, AI 응답 (JSON 파싱 실패 시)
                await classify_and_save(session_id=request.session_id, sender="I", part="A", text=answer)
            else:
                save_daily_log(request.session_id, "bot", answer)
                save_to_chat_messages(request.session_id, answer, "I", "condition")
                # Goalskill 분류: Part A', AI 응답 (JSON 파싱 실패 시)
                await classify_and_save(session_id=request.session_id, sender="I", part="A", text=answer)
            return {"answer": answer, "thinking_process": None}

    except Exception as e:
        logger.exception(f"[chat API ERROR] {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))

@router.get("/username/{session_id}")
async def get_username_api(session_id: str):
    username = get_username(session_id)
    return {"username": username}