# # 항상 킬 수 있도록 조작합니다. 0시~6시, 18시~24시 작동하고 토,일은 무조건 작동합니다.
#
#
#
# # yonex_daegu_seogu_ai_chatbot.py
# from flask import Flask, request, jsonify
# from openai import OpenAI
# import json
# from datetime import datetime, time
# from zoneinfo import ZoneInfo
#
# app = Flask(__name__)
#
# # ---------------------------
# # ✅ OpenAI API 키 하드코딩
# # ---------------------------
# client = OpenAI(api_key="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")
#
# # ---------------------------
# # 설정값
# # ---------------------------
# MAX_MESSAGE_LENGTH = 100        # 사용자 질문 길이 제한
# MAX_USER_QUERIES = 10           # 사용자별 버킷당 최대 질문 횟수
# RATE_LIMIT_WINDOW_HOURS = 6     # 6 또는 3 (KST 고정 버킷)
#
# # 사용자별 버킷 상태 저장: { user_id: {"bucket_start": datetime(KST), "count": int} }
# user_limits = {}
#
# # ---------------------------
# # 시간/운영 정책
# # - 월~금: 00:00~06:00, 18:00~24:00만 챗봇 동작
# # - 토/일: 24시간 동작
# # - 운영시간 외에는 "아무 메시지도 보내지 않음"(204)
# # ---------------------------
# def is_allowed_now_kst() -> bool:
#     now = datetime.now(ZoneInfo("Asia/Seoul"))
#     wd = now.weekday()  # 월=0 ... 일=6
#     t = now.time()
#
#     if wd in (5, 6):  # 토, 일
#         return True
#
#     # 평일 허용 구간
#     return ((time(0, 0, 0) <= t < time(6, 0, 0)) or
#             (time(18, 0, 0) <= t <= time(23, 59, 59)))
#
# def current_bucket_start(now: datetime, window_hours: int) -> datetime:
#     """KST 기준 고정 버킷 시작시각(예: 6시간 -> 00/06/12/18 정각)을 반환"""
#     kst = now.astimezone(ZoneInfo("Asia/Seoul"))
#     start_hour = (kst.hour // window_hours) * window_hours
#     return kst.replace(hour=start_hour, minute=0, second=0, microsecond=0)
#
# def increase_and_check_quota(user_id: str) -> int:
#     """
#     현재 버킷 기준으로 사용자 카운트를 +1하고 반환.
#     버킷이 바뀌면 자동 리셋 후 +1.
#     """
#     now = datetime.now(ZoneInfo("Asia/Seoul"))
#     bucket = current_bucket_start(now, RATE_LIMIT_WINDOW_HOURS)
#
#     rec = user_limits.get(user_id)
#     if not rec or rec["bucket_start"] != bucket:
#         user_limits[user_id] = {"bucket_start": bucket, "count": 0}
#
#     user_limits[user_id]["count"] += 1
#     return user_limits[user_id]["count"]
#
# # ---------------------------
# # 라우팅
# # ---------------------------
# @app.route('/webhook', methods=['POST'])
# def webhook():
#     data = request.json or {}
#     user_message = data.get('textContent', {}).get('text', '') or ''
#     user_id = data.get('user', '') or ''
#     input_type = data.get('textContent', {}).get('inputType', '') or ''
#
#     # 네이버 톡톡/상담 플랫폼에서 지정한 이벤트 외 무시
#     if input_type != "typing":
#         return ('', 204)
#
#     # 1) 운영시간 체크: 운영시간 외에는 "절대" 말풍선 전송 금지
#     if not is_allowed_now_kst():
#         return ('', 204)  # No Content -> 사용자 화면에 아무것도 안 뜸
#
#     # 2) 메시지 길이 제한
#     if len(user_message) > MAX_MESSAGE_LENGTH:
#         return jsonify({
#             "event": "send",
#             "textContent": {
#                 "text": "(챗봇) 질문이 너무 깁니다^^ 100자 이내로 짧게 다시 질문해주세요~"
#             }
#         })
#
#     # 3) 시간 버킷 기반 질의 제한 (자동 리셋)
#     current_count = increase_and_check_quota(user_id)
#     if current_count > MAX_USER_QUERIES:
#         return jsonify({
#             "event": "send",
#             "textContent": {
#                 "text": "(챗봇) 질의 초과 / 9시~17시 영업시간 답변드리겠습니다."
#             }
#         })
#
#     # 4) 시스템 프롬프트
#     system_prompt = """
#     당신은 친절한 고객 상담 챗봇.
#     정서적으로 친절하게 답함.
#     규칙:
#     - 답변 앞에 "(챗봇)"를 붙힘.
#     - 답변은 100자 이내로 제한.
#     - 배송문의:
#         각 상품페이지를 보시면 확인이 가능합니다^^
#         "오늘출발제품"이 아니면 영업일 기준 2~4일 소요됩니다^^
#     - 매장문의:
#         매장주소: 대구광역시 서구 북비산로 283-2번지
#         매장엽업시간: 평일오전10시~18시, 토요일10시~13시 (공휴일, 일요일 전부 휴무)
#         (당사는 매장과 물류센터 위치가 달라서 매장에 모든 제품을 구비하고 있지않음)
#         (온라인 담당 CS센터 직통번호: 010-4982-2469)
#     - 교환 및 반품 문의:
#         네이버를 통해서 교환 및 반품 접수를 해주시면 됩니다^^ 원하시는 사이즈나 색상이 있는 경우 교환 신청 하실 때, 꼭 메모해주세요^^
#         반품이나 교환은 일단 저희가 제품이 회수되는대로 제품을 확인하고 처리가 되니, 영업일 기준 신청하시고 보통 2~3일인데 최대 5일정도 생각해주셔야합니다^^
#         혹시 구매확정처리를 하셨다면, 현재 봇상담으로는 불가합니다ㅠ 저희가 평일 cs담당님이 계신시간 다시 연락드리겠습니다.
#         단순교환의 경우 왕복배송비가 발생합니다ㅠ
#         불량교환의 경우 왕복배송비가 발생하지 않습니다! 그런데 저희가 회수 후 불량이 아닌 경우는 왕복배송비가 청구 될수있습니다.
#     - 배송, 매장 문의를 제외한 모든 상담은 현재 불가하여, 다음과 같이 답한다.:
#         현재는 배송안내를 제외한 상담은 불가합니다. 다른 상담은 오전9시~17시 가능합니다.
#     - 개인정보, 제품과 무관한 질문, 심리테스트 요청 등은 차단.
#
#     JSON 형식 답변:
#     {
#         "block": true 또는 false,
#         "response": "답변내용(한글 100자 이내)"
#     }
#     """.strip()
#
#     # 5) 모델 호출
#     completion = client.chat.completions.create(
#         model="gpt-4o-mini",
#         response_format={"type": "json_object"},
#         messages=[
#             {"role": "system", "content": system_prompt},
#             {"role": "user", "content": user_message}
#         ]
#     )
#
#     reply_json = completion.choices[0].message.content.strip()
#     try:
#         reply_dict = json.loads(reply_json)
#     except json.JSONDecodeError:
#         reply_dict = {"block": False, "response": "(챗봇) 잠시 후 다시 시도해주세요."}
#
#     if reply_dict.get('block'):
#         reply_text = "(챗봇) 현재는 배송안내 외 다른 상담은 불가합니다. 다른 상담은 오전9시~17시 가능합니다."
#     else:
#         reply_text = reply_dict.get('response', "(챗봇) 잠시 후 다시 시도해주세요.")
#
#     return jsonify({
#         "event": "send",
#         "textContent": {"text": reply_text}
#     })
#
# # 헬스체크(선택)
# @app.route('/', methods=['GET'])
# def root():
#     return ('', 204)
#
# if __name__ == '__main__':
#     app.run(host='0.0.0.0', port=5000, debug=False)













# # 항상 킬 수 있도록 조작합니다. 0시~6시, 18시~24시 작동하고 토,일은 무조건 작동합니다.
# # 119 db에서 프롬프트 데이터를 조회하여 처리합니다.
# yonex_daegu_seogu_ai_chatbot.py
from flask import Flask, request, jsonify
from openai import OpenAI
import json
from datetime import datetime, time
from zoneinfo import ZoneInfo
import pymysql

app = Flask(__name__)

# ---------------------------
# ✅ OpenAI API 키 하드코딩 (운영환경 유출 주의!)
# ---------------------------
client = OpenAI(api_key="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")

# ---------------------------
# ✅ MySQL 접속 설정 (119서버 versatile DB)
# ---------------------------
DB_CONFIG = {
    "host": "119.205.233.11",       # 119서버 IP/호스트로 교체
    "user": "changgi",  # 계정명으로 교체
    "password": "vkdnjgus13",       # 비밀번호로 교체
    "database": "versatile",
    "charset": "utf8mb4",
    "cursorclass": pymysql.cursors.DictCursor
}

# ---------------------------
# 전역 변수: system_prompt (앱 시작 시 한 번만 로드)
# ---------------------------
SYSTEM_PROMPT = ""

def load_system_prompt_once() -> str:
    """앱 시작 시 DB에서 id=6인 프롬프트 한 번만 로드"""
    try:
        conn = pymysql.connect(**DB_CONFIG)
        try:
            with conn.cursor() as cur:
                cur.execute("SELECT prompt_text FROM ai_prompt_table WHERE id=%s", (6,))
                row = cur.fetchone()
                if row and row.get("prompt_text"):
                    print("[INFO] system_prompt loaded from DB (id=6)")
                    return row["prompt_text"]
        finally:
            conn.close()
    except Exception as e:
        print(f"[WARN] load_system_prompt_once error: {e}")

    # 폴백 프롬프트
    return (
        "당신은 친절한 고객 상담 챗봇.\n"
        "규칙:\n"
        "- 답변 앞에 '(챗봇)'를 붙임.\n"
        "- 답변은 100자 이내.\n"
        "- 배송/매장/교환·반품 문의 가이드를 간결하게 제공.\n"
        "- 개인정보, 무관 질문 차단.\n"
        "JSON:\n"
        "{ \"block\": true|false, \"response\": \"한글 100자 이내\" }"
    )

# ---------------------------
# 레이트리밋 관련 설정
# ---------------------------
MAX_MESSAGE_LENGTH = 100
MAX_USER_QUERIES = 10
RATE_LIMIT_WINDOW_HOURS = 6

user_limits = {}

def is_allowed_now_kst() -> bool:
    now = datetime.now(ZoneInfo("Asia/Seoul"))
    wd = now.weekday()  # 월=0 ... 일=6
    t = now.time()
    if wd in (5, 6):  # 토/일
        return True
    return ((time(0, 0, 0) <= t < time(6, 0, 0)) or
            (time(18, 0, 0) <= t <= time(23, 59, 59)))

def current_bucket_start(now: datetime, window_hours: int) -> datetime:
    kst = now.astimezone(ZoneInfo("Asia/Seoul"))
    start_hour = (kst.hour // window_hours) * window_hours
    return kst.replace(hour=start_hour, minute=0, second=0, microsecond=0)

def increase_and_check_quota(user_id: str) -> int:
    now = datetime.now(ZoneInfo("Asia/Seoul"))
    bucket = current_bucket_start(now, RATE_LIMIT_WINDOW_HOURS)
    rec = user_limits.get(user_id)
    if not rec or rec["bucket_start"] != bucket:
        user_limits[user_id] = {"bucket_start": bucket, "count": 0}
    user_limits[user_id]["count"] += 1
    return user_limits[user_id]["count"]

# ---------------------------
# 라우팅
# ---------------------------
@app.route('/webhook', methods=['POST'])
def webhook():
    data = request.json or {}
    user_message = data.get('textContent', {}).get('text', '') or ''
    user_id = data.get('user', '') or ''
    input_type = data.get('textContent', {}).get('inputType', '') or ''

    if input_type != "typing":
        return ('', 204)

    if not is_allowed_now_kst():
        return ('', 204)

    if len(user_message) > MAX_MESSAGE_LENGTH:
        return jsonify({
            "event": "send",
            "textContent": {"text": "(챗봇) 질문이 너무 깁니다^^ 100자 이내로 짧게 다시 질문해주세요~"}
        })

    current_count = increase_and_check_quota(user_id)
    if current_count > MAX_USER_QUERIES:
        return jsonify({
            "event": "send",
            "textContent": {"text": "(챗봇) 질의 초과 / 9시~17시 영업시간 답변드리겠습니다."}
        })

    # ✅ DB에서 한 번 로드된 SYSTEM_PROMPT 사용
    completion = client.chat.completions.create(
        model="gpt-4o-mini",
        response_format={"type": "json_object"},
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message}
        ]
    )

    reply_json = completion.choices[0].message.content.strip()
    try:
        reply_dict = json.loads(reply_json)
    except json.JSONDecodeError:
        reply_dict = {"block": False, "response": "(챗봇) 잠시 후 다시 시도해주세요."}

    if reply_dict.get('block'):
        reply_text = "(챗봇) 현재는 배송안내 외 다른 상담은 불가합니다. 다른 상담은 오전9시~17시 가능합니다."
    else:
        reply_text = reply_dict.get('response', "(챗봇) 잠시 후 다시 시도해주세요.")

    return jsonify({"event": "send", "textContent": {"text": reply_text}})

@app.route('/', methods=['GET'])
def root():
    return ('', 204)

if __name__ == '__main__':
    # 시작 시 1회 프롬프트 로드
    SYSTEM_PROMPT = load_system_prompt_once()
    print("[INFO] Loaded SYSTEM_PROMPT:")
    print(SYSTEM_PROMPT[:200], "..." if len(SYSTEM_PROMPT) > 200 else "")

    app.run(host='0.0.0.0', port=5000, debug=False)
