from fastapi.middleware.cors import CORSMiddleware
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from fastapi.responses import JSONResponse
import traceback
import os
import mysql.connector
from openai import AsyncOpenAI

# FastAPI 앱
app = FastAPI()

# CORS 설정
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# OpenAI 클라이언트
# 주의: 실제 배포 시에는 API 키를 코드에 직접 적지 말고 환경 변수 파일(.env)을 사용하세요.
client = AsyncOpenAI(
    api_key=os.getenv("OPENAI_API_KEY", "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")
)

# --- DB 연결 함수 ---
def get_db_connection():
    return mysql.connector.connect(
        host="localhost",
        user="GOALSkill",         # 본인 DB 아이디
        password="GOALSkill_99!@",# 본인 DB 비밀번호
        database="INPUT_DB"
    )

# --- [수정 1] 데이터 모델 정리 (중복 제거 및 누락 추가) ---

# 1. 채팅 요청용 모델 (session_id 포함 필수!)
class ChatRequest(BaseModel):
    session_id: str   
    message: str
    thinking_level: str = "OFF"

# 2. 로그 저장용 모델 (누락되었던 것 추가)
class LogRequest(BaseModel):
    session_id: str
    mode: str
    sender: str
    message: str

# 3. 일지 생성용 모델
class JournalRequest(BaseModel):
    answers: list[str]


# --- 로그 저장 헬퍼 함수 ---
def save_chat_log(session_id, mode, sender, message):
    try:
        conn = get_db_connection()
        cursor = conn.cursor()
        sql = "INSERT INTO chat_history (session_id, mode, sender, message) VALUES (%s, %s, %s, %s)"
        cursor.execute(sql, (session_id, mode, sender, message))
        conn.commit()
        cursor.close()
        conn.close()
    except Exception as e:
        print(f"DB Save Error: {e}")


# --- API 엔드포인트 ---

# 1. 히스토리 불러오기
@app.get("/goal-skill-t/api/history/{mode}/{session_id}")
async def get_history(mode: str, session_id: str):
    try:
        conn = get_db_connection()
        cursor = conn.cursor(dictionary=True)
        sql = "SELECT sender, message FROM chat_history WHERE session_id = %s AND mode = %s ORDER BY id ASC"
        cursor.execute(sql, (session_id, mode))
        rows = cursor.fetchall()
        cursor.close()
        conn.close()
        return {"history": rows}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# 2. 프론트엔드 로그 저장 (일지 모드 질문 등)
@app.post("/goal-skill-t/api/log")
async def log_message(req: LogRequest):
    save_chat_log(req.session_id, req.mode, req.sender, req.message)
    return {"status": "ok"}


# --- [수정 2] 함수 이름 구분 (chat_basic, chat_mbti 등) ---

# 3. 일반 채팅
@app.post("/goal-skill-t/api/chat")
async def chat_basic(request: ChatRequest):
    try:
        # 유저 메시지 저장
        save_chat_log(request.session_id, "chat", "user", request.message)

        response = await client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {"role": "system", "content": "당신은 사용자의 목표 달성과 스킬 성장을 돕는 코치입니다."},
                {"role": "user", "content": request.message},
            ],
            temperature=0.7,
        )

        answer = response.choices[0].message.content
        
        # 봇 메시지 저장
        save_chat_log(request.session_id, "chat", "bot", answer)

        return {
            "answer": answer,
            "thinking_process": None
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

# 4. MBTI 채팅
@app.post("/goal-skill-t/api/MBTI")
async def chat_mbti(request: ChatRequest):
    try:
        save_chat_log(request.session_id, "MBTI", "user", request.message)

        response = await client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {"role": "system", "content": "당신은 사용자의 MBTI를 검사하는 선생님입니다."},
                {"role": "user", "content": request.message},
            ],
            temperature=0.7,
        )

        answer = response.choices[0].message.content
        
        save_chat_log(request.session_id, "MBTI", "bot", answer)

        return {
            "answer": answer,
            "thinking_process": None
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
    
# 5. 파이썬 채팅
@app.post("/goal-skill-t/api/Python")
async def chat_python(request: ChatRequest):
    try:
        save_chat_log(request.session_id, "Python", "user", request.message)

        response = await client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {"role": "system", "content": "당신은 사용자의 일본 코딩 사이트 Paiza에 B랭크를 취득하기 위한 선생님입니다."},
                {"role": "user", "content": request.message},
            ],
            temperature=0.7,
        )

        answer = response.choices[0].message.content
        
        save_chat_log(request.session_id, "Python", "bot", answer)

        return {
            "answer": answer,
            "thinking_process": None
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
    
# 6. 일지 작성 도우미 (대화용)
@app.post("/goal-skill-t/api/Report")
async def chat_report(request: ChatRequest):
    try:
        # 일지 모드는 프론트엔드(chat.js)가 주도하므로 이 API는 많이 안 쓰일 수 있지만,
        # 만약 대화가 넘어온다면 저장합니다.
        save_chat_log(request.session_id, "Report", "user", request.message)

        response = await client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {"role": "system", "content": "당신은 사용자의 오늘 하루 어떤 것을 했는지 일지 작성을 도와주는 역할입니다."},
                {"role": "user", "content": request.message},
            ],
            temperature=0.7,
        )

        answer = response.choices[0].message.content
        save_chat_log(request.session_id, "Report", "bot", answer)

        return {
            "answer": answer,
            "thinking_process": None
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
    

# 7. 일지 최종 생성
@app.post("/goal-skill-t/api/GenerateJournal")
async def generate_journal(request: JournalRequest):
    try:
        if len(request.answers) < 4:
            raise HTTPException(status_code=400, detail="답변이 충분하지 않습니다.")
            
        q1, q2, q3, q4 = request.answers[0], request.answers[1], request.answers[2], request.answers[3]

        prompt = f"""
        사용자의 학습 답변을 바탕으로 전문적이고 깔끔한 '오늘의 학습 일지'를 작성해주세요.
        
        [사용자 답변]
        1. 배운 것: {q1}
        2. 학습 방법: {q2}
        3. 어려웠던 점: {q3}
        4. 해결 방법: {q4}
        
        [출력 형식]
        # 📅 오늘의 학습 일지
        
        ## 💡 핵심 배움
        (내용 요약)
        
        ## 🛠️ 학습 과정 및 트러블 슈팅
        (내용 요약)
        
        ## 🚀 내일의 다짐
        (격려의 한마디)
        """

        response = await client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[{"role": "system", "content": "당신은 전문적인 에디터입니다."}, 
                      {"role": "user", "content": prompt}],
            temperature=0.7,
        )

        final_report = response.choices[0].message.content

        # DB에 저장
        try:
            conn = get_db_connection()
            cursor = conn.cursor()
            sql = """INSERT INTO learning_logs (what_learned, how_learned, difficulty, solution, final_report) 
                     VALUES (%s, %s, %s, %s, %s)"""
            cursor.execute(sql, (q1, q2, q3, q4, final_report))
            conn.commit()
            cursor.close()
            conn.close()
        except Exception as db_err:
            print(f"DB Save Error: {db_err}") 

        return {
            "answer": final_report,
            "thinking_process": "DB Saved & Generated"
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))