"""
AI 기반 제품 자동 카테고리 태깅
"""

import sys
import os

# UTF-8 인코딩 강제 (Windows 한글 깨짐 방지)
if sys.platform == 'win32':
    import io
    sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
    sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8')

import sqlite3
import json
from openai import OpenAI
from dotenv import load_dotenv

# .env 파일 로드
load_dotenv()

# OpenAI 클라이언트 초기화
client = OpenAI(api_key=os.getenv('OPENAI_API_KEY'))

def get_uncategorized_products():
    """카테고리가 없는 제품 조회"""
    db_path = os.path.join(os.path.dirname(__file__), 'db', 'mileage.db')
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()

    try:
        # 카테고리가 없는 제품 조회
        cursor.execute("""
            SELECT p.barcode, p.product_name
            FROM product_master p
            LEFT JOIN product_category_mapping m ON p.barcode = m.barcode
            WHERE m.barcode IS NULL
            ORDER BY p.product_name
        """)

        products = cursor.fetchall()
        return [(barcode, name) for barcode, name in products]

    finally:
        conn.close()


def get_available_categories():
    """사용 가능한 카테고리 목록 조회"""
    db_path = os.path.join(os.path.dirname(__file__), 'db', 'mileage.db')
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()

    try:
        cursor.execute("SELECT category_name, description FROM product_categories ORDER BY category_name")
        categories = cursor.fetchall()
        return categories

    finally:
        conn.close()


def ai_categorize_product(product_name, available_categories):
    """OpenAI API로 제품 카테고리 분류"""

    # 카테고리 목록 포맷팅
    category_list = "\n".join([f"- {cat[0]}: {cat[1] or '(설명 없음)'}" for cat in available_categories])

    prompt = f"""당신은 약국 제품 분류 전문가입니다.

제품명: {product_name}

아래 카테고리 목록에서 이 제품에 가장 적합한 카테고리를 1~3개 선택하고, 각 카테고리의 관련도 점수(0.0~1.0)를 매겨주세요.

사용 가능한 카테고리:
{category_list}

응답은 반드시 아래 JSON 형식으로만 작성해주세요:
{{
    "categories": [
        {{"name": "카테고리명", "score": 1.0, "reason": "선택 이유"}},
        {{"name": "카테고리명", "score": 0.8, "reason": "선택 이유"}}
    ]
}}

주의사항:
1. 가장 관련 있는 카테고리 1~3개만 선택
2. score는 0.0~1.0 범위 (주 카테고리는 1.0, 부 카테고리는 0.5~0.9)
3. 카테고리명은 위 목록에 있는 것만 사용
4. JSON 형식 외 다른 텍스트 추가하지 말 것"""

    try:
        response = client.chat.completions.create(
            model="gpt-4o-mini",
            messages=[
                {"role": "system", "content": "당신은 의약품 분류 전문가입니다. 항상 JSON 형식으로만 응답하세요."},
                {"role": "user", "content": prompt}
            ],
            temperature=0.3,
            max_tokens=500
        )

        result_text = response.choices[0].message.content.strip()

        # JSON 파싱
        result = json.loads(result_text)
        return result['categories']

    except json.JSONDecodeError as e:
        print(f"[ERROR] JSON 파싱 실패: {e}")
        print(f"응답: {result_text}")
        return []
    except Exception as e:
        print(f"[ERROR] AI 분류 실패: {e}")
        return []


def update_product_categories(barcode, categories):
    """제품 카테고리 매핑 업데이트"""
    db_path = os.path.join(os.path.dirname(__file__), 'db', 'mileage.db')
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()

    try:
        for cat in categories:
            # 카테고리가 존재하는지 확인
            cursor.execute(
                "SELECT category_name FROM product_categories WHERE category_name = ?",
                (cat['name'],)
            )

            if cursor.fetchone():
                cursor.execute("""
                    INSERT OR REPLACE INTO product_category_mapping
                    (barcode, category_name, relevance_score)
                    VALUES (?, ?, ?)
                """, (barcode, cat['name'], cat['score']))

        conn.commit()
        return True

    except Exception as e:
        print(f"[ERROR] DB 업데이트 실패: {e}")
        conn.rollback()
        return False

    finally:
        conn.close()


def main():
    """메인 실행"""
    print("="*80)
    print("AI 기반 제품 자동 카테고리 태깅")
    print("="*80)

    # 1. 카테고리가 없는 제품 조회
    print("\n1단계: 카테고리 없는 제품 조회 중...")
    uncategorized = get_uncategorized_products()

    if not uncategorized:
        print("[OK] 모든 제품이 이미 카테고리가 있습니다!")
        return

    print(f"[OK] {len(uncategorized)}개 제품 발견\n")

    # 2. 사용 가능한 카테고리 조회
    print("2단계: 사용 가능한 카테고리 조회 중...")
    categories = get_available_categories()
    print(f"[OK] {len(categories)}개 카테고리 사용 가능\n")

    # 3. 각 제품 AI 태깅
    print("3단계: AI 기반 제품 분류 시작...\n")
    print("-"*80)

    success_count = 0
    fail_count = 0

    for idx, (barcode, product_name) in enumerate(uncategorized, 1):
        print(f"\n[{idx}/{len(uncategorized)}] {product_name}")

        # AI로 카테고리 분류
        suggested_categories = ai_categorize_product(product_name, categories)

        if not suggested_categories:
            print(f"  [SKIP] AI 분류 실패")
            fail_count += 1
            continue

        # 카테고리 출력
        for cat in suggested_categories:
            print(f"  ├─ {cat['name']} (관련도: {cat['score']:.1f}) - {cat.get('reason', '')}")

        # DB 업데이트
        if update_product_categories(barcode, suggested_categories):
            print(f"  └─ [OK] 카테고리 매핑 완료")
            success_count += 1
        else:
            print(f"  └─ [ERROR] DB 업데이트 실패")
            fail_count += 1

    # 4. 결과 요약
    print("\n" + "="*80)
    print("AI 태깅 완료")
    print("="*80)
    print(f"성공: {success_count}개")
    print(f"실패: {fail_count}개")
    print("="*80)

    # 5. 최종 통계
    db_path = os.path.join(os.path.dirname(__file__), 'db', 'mileage.db')
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()

    try:
        cursor.execute("SELECT COUNT(*) FROM product_master")
        total = cursor.fetchone()[0]

        cursor.execute("SELECT COUNT(DISTINCT barcode) FROM product_category_mapping")
        categorized = cursor.fetchone()[0]

        print(f"\n최종 통계:")
        print(f"  전체 제품:          {total}개")
        print(f"  카테고리 있는 제품:  {categorized}개")
        print(f"  카테고리 없는 제품:  {total - categorized}개")

    finally:
        conn.close()


if __name__ == '__main__':
    main()
