"""
batch-tags.py  —  Sinh lại TOÀN BỘ tags cho tất cả sản phẩm (KHÔNG CẦN AI)
─────────────────────────────────────────────────────────────
Chạy:  cd backend && python worker/scripts/batch-tags.py

Logic:
  1. StarRocks → lấy master_color → mapping cứng → Color Tags (1-3)
  2. product_line → mapping cứng 58 dòng hàng → Occasion Tags (1-4) + Season Tag (1)
  3. Merge → ghi vào cột tags trong SQLite

Không cần AI. Không cần DS2API. Chạy < 10 giây.
"""

import json
import logging
import os
import sys
import time

import pymysql
from pymysql.cursors import DictCursor

sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", ".."))
from common.pool_wrapper import get_pooled_connection_compat

logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s", datefmt="%H:%M:%S")
log = logging.getLogger("batch-tags")

# ═══════════════════════════════════════════════════════════
# CONFIG
# ═══════════════════════════════════════════════════════════
SR_HOST, SR_PORT = "172.16.2.100", 9030
SR_USER, SR_PASSWORD, SR_DB = "anhvh", "v0WYGeyLRCckXotT", "shared_source"
SR_TABLE = "shared_source.magento_product_dimension_with_text_embedding"
PG_TABLE = "dashboard_canifa.ultra_descriptions"

# ═══════════════════════════════════════════════════════════
# 10 TAGS CHUẨN
# ═══════════════════════════════════════════════════════════
_ALL  = ["Đi làm công sở", "Đi chơi / dạo phố", "Ở nhà / mặc ngủ", "Du lịch"]
_S_ALL    = "Cả 2 mùa (Mùa xuân/ mùa thu)"
_S_SUMMER = "Mùa hè"
_S_WINTER = "Mùa đông"

# ═══════════════════════════════════════════════════════════
# BƯỚC 1: COLOR MAPPING (StarRocks → deterministic)
# ═══════════════════════════════════════════════════════════
_NEUTRAL = ["trắng","white","đen","black","xám","gray","grey","be","beige","nâu","brown","kem","cream","ivory"]
_LIGHT   = ["vàng","yellow","gold","hồng","pink","magenta","xanh da trời","light blue","sky blue"]
_DARK    = ["đỏ","red","cam","orange","xanh lá","green","xanh jeans","jeans","xanh than","aqua","navy","dark blue"]
_BOTH    = ["tím","purple"]

def classify_color(mc: str) -> set[str]:
    c = mc.lower().strip()
    tags = set()
    if any(k in c for k in _NEUTRAL): tags.add("Trung tính")
    if any(k in c for k in _LIGHT):   tags.add("Sáng")
    if any(k in c for k in _DARK):    tags.add("Đậm")
    if any(k in c for k in _BOTH):    tags.add("Sáng"); tags.add("Đậm")
    return tags or {"Trung tính"}

def fetch_colors() -> dict[str, set[str]]:
    log.info("🔌 Kết nối StarRocks %s:%s ...", SR_HOST, SR_PORT)
    conn = pymysql.connect(host=SR_HOST, port=SR_PORT, user=SR_USER, password=SR_PASSWORD,
                           database=SR_DB, charset="utf8mb4", cursorclass=DictCursor,
                           connect_timeout=15, read_timeout=60)
    with conn.cursor() as cur:
        cur.execute(f"SELECT magento_ref_code, master_color FROM {SR_TABLE} WHERE magento_ref_code IS NOT NULL AND master_color IS NOT NULL AND master_color != ''")
        rows = cur.fetchall()
    conn.close()
    log.info("✅ StarRocks: %d dòng SKU-màu", len(rows))
    cmap: dict[str, set[str]] = {}
    for r in rows:
        code = r["magento_ref_code"]
        if code not in cmap: cmap[code] = set()
        cmap[code].update(classify_color(r["master_color"] or ""))
    log.info("📊 %d sản phẩm có color data", len(cmap))
    return cmap

# ═══════════════════════════════════════════════════════════
# BƯỚC 2: MAPPING CỨNG 58 DÒNG HÀNG → (occasions, season)
# ═══════════════════════════════════════════════════════════
# Triết lý: ƯU TIÊN THỪA hơn THIẾU

_W = ["Đi làm công sở", "Đi chơi / dạo phố", "Du lịch"]           # Work + Play + Travel
_P = ["Đi chơi / dạo phố", "Du lịch"]                              # Play + Travel
_H = ["Ở nhà / mặc ngủ"]                                           # Home only
_PH = ["Đi chơi / dạo phố", "Ở nhà / mặc ngủ", "Du lịch"]         # Play + Home + Travel

PRODUCT_LINE_MAP: dict[str, tuple[list[str], str]] = {
    # ── Đồ lót / Tất / Phụ kiện cá nhân → MẶC MỌI NƠI, CẢ NĂM ──
    "Quần lót":             (_ALL, _S_ALL),
    "Quần lót tam giác":    (_ALL, _S_ALL),
    "Quần lót đùi":         (_ALL, _S_ALL),
    "Áo lót":               (_ALL, _S_ALL),
    "Áo Body":              (_ALL, _S_ALL),
    "Quần Body":            (_ALL, _S_ALL),
    "Tất":                  (_ALL, _S_ALL),
    "Khẩu trang":           (_ALL, _S_ALL),
    "Khăn mặt":             (_ALL, _S_ALL),
    "Khăn tắm":             (["Ở nhà / mặc ngủ", "Du lịch"], _S_ALL),
    # ── Đồ nhà / Đồ ngủ ──
    "Bộ mặc nhà":           (_H, _S_ALL),
    "Pyjama":               (_H, _S_ALL),
    "Áo mặc nhà":           (_H, _S_ALL),
    "Quần mặc nhà":         (_H, _S_ALL),
    "Quần leggings mặc nhà":(_H, _S_ALL),
    "Chăn cá nhân":         (_H, _S_WINTER),
    # ── Đồ giữ nhiệt → mặc lót bên trong mọi nơi ──
    "Áo giữ nhiệt":        (_ALL, _S_WINTER),
    "Quần giữ nhiệt":      (_ALL, _S_WINTER),
    # ── Áo thường ngày ──
    "Áo phông":             (_PH, _S_ALL),
    "Áo Polo":              (_W, _S_ALL),
    "Áo Sơ mi":             (_W, _S_ALL),
    "Áo kiểu":              (_W, _S_ALL),
    "Áo ba lỗ":             (_PH, _S_SUMMER),
    "Áo hai dây":           (_PH, _S_SUMMER),
    # ── Quần thường ngày ──
    "Quần jean":            (_W, _S_ALL),
    "Quần Khaki":           (_W, _S_ALL),
    "Quần dài":             (_W, _S_ALL),
    "Quần soóc":            (_P, _S_SUMMER),
    "Quần culottes":        (_W, _S_SUMMER),
    "Quần nỉ":              (["Đi chơi / dạo phố", "Ở nhà / mặc ngủ", "Du lịch"], _S_WINTER),
    "Quần leggings":        (_PH, _S_ALL),
    # ── Váy ──
    "Chân váy":             (_W, _S_ALL),
    "Váy liền":             (_W, _S_ALL),
    "Quần váy":             (_W, _S_ALL),
    # ── Bộ / Set ──
    "Bộ quần áo":           (_P, _S_ALL),
    "Bộ thể thao":          (_P, _S_ALL),
    # ── Khoác — Cả 2 mùa ──
    "Áo khoác":             (_W, _S_ALL),
    "Áo khoác gió":         (_W, _S_ALL),
    "Áo khoác dáng ngắn":   (_W, _S_ALL),
    "Áo khoác sợi":         (_W, _S_ALL),
    "Cardigan":              (_W, _S_ALL),
    # ── Khoác — Mùa đông ──
    "Áo khoác chần bông":      (_W, _S_WINTER),
    "Áo khoác gilet chần bông":(_W, _S_WINTER),
    "Áo khoác dạ":             (_W, _S_WINTER),
    "Áo khoác lông vũ":        (_W, _S_WINTER),
    "Áo khoác nỉ có mũ":       (_P, _S_WINTER),
    "Áo khoác nỉ không mũ":    (_W, _S_WINTER),
    # ── Khoác — Mùa hè ──
    "Áo khoác chống nắng":     (_P, _S_SUMMER),
    "Găng tay chống nắng":     (_P, _S_SUMMER),
    # ── Len / Nỉ ──
    "Áo len":               (_W, _S_WINTER),
    "Áo len gilet":          (_W, _S_WINTER),
    "Áo nỉ":                (_W, _S_WINTER),
    "Áo nỉ có mũ":          (_P, _S_WINTER),
    "Blazer":                (["Đi làm công sở", "Đi chơi / dạo phố"], _S_ALL),
    # ── Phụ kiện ──
    "Mũ":                   (_P, _S_ALL),
    "Mũ thể thao":          (_P, _S_ALL),
    "Túi xách":             (_W, _S_ALL),
    "Khăn":                 (_W, _S_WINTER),
    "Khăn lau đầu":         (["Ở nhà / mặc ngủ", "Du lịch"], _S_ALL),
    # ── Bổ sung từ run lần 1 ──
    "Quần tất":             (_ALL, _S_WINTER),
    "Áo bra active":        (_ALL, _S_ALL),
    "Áo khoác gilet":       (_W, _S_ALL),
}

def lookup_occasion_season(product_line: str) -> tuple[list[str], str]:
    result = PRODUCT_LINE_MAP.get(product_line)
    if result:
        return result
    # Fallback: tìm case-insensitive
    pl_lower = product_line.lower().strip()
    for key, val in PRODUCT_LINE_MAP.items():
        if key.lower() == pl_lower:
            return val
    # Không tìm thấy → default an toàn
    return (["Đi chơi / dạo phố", "Du lịch"], _S_ALL)

# ═══════════════════════════════════════════════════════════
# BƯỚC 3: MAIN — CHẠY BATCH
# ═══════════════════════════════════════════════════════════

def main():
    log.info("=" * 60)
    log.info("🚀 BATCH TAGS GENERATOR (100%% Deterministic — No AI)")
    log.info("   StarRocks Color + 58 Product Line Hard Map")
    log.info("=" * 60)

    # 1. Colors từ StarRocks
    try:
        color_map = fetch_colors()
    except Exception as e:
        log.error("❌ StarRocks lỗi: %s", e)
        sys.exit(1)

    # 2. Đọc sản phẩm từ SQLite
    log.info("📂 Đọc sản phẩm từ SQLite...")
    conn = get_pooled_connection_compat()
    cur = conn.cursor()
    cur.execute(f"SELECT internal_ref_code, product_name, product_line FROM {PG_TABLE} ORDER BY internal_ref_code")
    rows = cur.fetchall()
    cur.close()
    total = len(rows)
    log.info("📦 %d sản phẩm", total)

    # 3. Sinh tags + ghi DB
    success = errors = unmapped = 0
    unmapped_lines = set()
    t_start = time.time()

    for i, row in enumerate(rows):
        code, name, product_line = row[0], row[1] or "", row[2] or ""

        # Color
        color_tags = sorted(color_map.get(code, {"Trung tính"}))

        # Occasion + Season
        occasion_tags, season_tag = lookup_occasion_season(product_line)

        if product_line and product_line not in PRODUCT_LINE_MAP:
            # Case-insensitive cũng không match
            found = any(k.lower() == product_line.lower().strip() for k in PRODUCT_LINE_MAP)
            if not found:
                unmapped += 1
                unmapped_lines.add(product_line)

        # Merge
        final_tags = color_tags + occasion_tags + [season_tag]

        # Ghi DB
        try:
            c = conn.cursor()
            c.execute(
                f"UPDATE {PG_TABLE} SET tags = ?, updated_at = datetime('now') WHERE internal_ref_code = ?",
                (json.dumps(final_tags, ensure_ascii=False), code),
            )
            conn.commit()
            c.close()
            success += 1
        except Exception as e:
            try: conn.rollback()
            except: pass
            errors += 1
            log.error("  ❌ %s: %s", code, e)

        # Progress mỗi 50
        if (i + 1) % 50 == 0:
            elapsed = time.time() - t_start
            log.info("  📊 %d/%d (%.0f%%) | ✅ %d | ❌ %d | %.1f sp/s",
                     i + 1, total, (i + 1) / total * 100, success, errors, (i + 1) / elapsed)

    elapsed = time.time() - t_start
    log.info("")
    log.info("=" * 60)
    log.info("🎉 HOÀN THÀNH!")
    log.info("=" * 60)
    log.info("   📦 Tổng         : %d", total)
    log.info("   ✅ Thành công   : %d", success)
    log.info("   ❌ Lỗi         : %d", errors)
    log.info("   ⚠️  Unmapped PL  : %d", unmapped)
    log.info("   ⏱️  Thời gian   : %.1fs", elapsed)

    if unmapped_lines:
        log.warning("   ⚠️  Dòng hàng chưa map (dùng default):")
        for pl in sorted(unmapped_lines):
            log.warning("      → '%s'", pl)

    conn.close()


if __name__ == "__main__":
    main()
