"""SPU/SKU 数据库查询 + 底图/模特图资源查找（产品图生成流水线的数据层）。

数据关系（已核实 spu_sku.db）：
  - SPU.code = 款号（如 DG004）
  - SKU.code = "款号-颜色编码"（如 DG004-BL01），SKU.color = 中文色名（黑/灰/...）
  - basemap 目录 = basemap/<款号>/<SKU.code>/xxx.jpg
  - material_library/<品类>/ 存放模特图
  - SKU.img_url_2~5 = CDN 图 URL（底图/细节/模特图，仅作参考字段）
"""
import sqlite3
from pathlib import Path
from typing import Any, Dict, List, Optional

# 支持的图片格式：模特图/底图均按此识别（png/jpg 等常见格式全覆盖；AVIF/GIF/TIFF 亦支持）
IMG_EXTS = {".jpg", ".jpeg", ".png", ".webp", ".bmp", ".avif", ".gif", ".tiff", ".tif"}


def _connect(db_path) -> sqlite3.Connection:
    conn = sqlite3.connect(str(db_path))
    conn.row_factory = sqlite3.Row
    return conn


def list_spus(db_path, country: Optional[str] = None) -> List[Dict[str, Any]]:
    """全部 SPU（可选按国家过滤）。"""
    conn = _connect(db_path)
    sql = "SELECT id, code, style, material, printing_type, target_audience, pattern, country, mark FROM SPU"
    params: list = []
    if country:
        sql += " WHERE country = ?"
        params.append(country)
    sql += " ORDER BY code"
    rows = conn.execute(sql, params).fetchall()
    conn.close()
    return [dict(r) for r in rows]


def list_colors(db_path, spu_code: str) -> List[Dict[str, Any]]:
    """款号 → 颜色列表（SKU.code 去重，附中文色名、CDN 底图 URL、最低价）。"""
    conn = _connect(db_path)
    rows = conn.execute(
        """SELECT s.code AS sku_code, s.color, s.img_url_2 AS img_url, MIN(s.price) AS price
           FROM SKU s JOIN SPU p ON s.spu_id = p.id
           WHERE p.code = ?
           GROUP BY s.code, s.color ORDER BY s.code""", (spu_code,)).fetchall()
    conn.close()
    return [dict(r) for r in rows]


def find_basemap(basemap_root, spu_code: str, sku_code: str) -> Optional[Path]:
    """basemap/<款号>/<SKU.code>/ 下第一张图片；无返回 None。"""
    d = Path(basemap_root) / spu_code / sku_code
    if not d.exists():
        return None
    for f in sorted(d.iterdir()):
        if f.is_file() and f.suffix.lower() in IMG_EXTS:
            return f
    return None


def list_model_images(material_root, category: str = "T-shirt") -> List[Path]:
    """material_library/<品类>/ 下所有图片；无返回空列表。"""
    d = Path(material_root) / category
    if not d.exists():
        return []
    return [f for f in sorted(d.iterdir()) if f.is_file() and f.suffix.lower() in IMG_EXTS]


def find_first_model_folder(material_root, preferred: Optional[str] = None):
    """material_library 下「第一个有图片的子目录」及其图片列表。

    - preferred（如 config 的 model_category）优先：该目录有图就直接用；
    - 否则按子目录名排序，取第一个有图的目录；
    - 全空返回 (None, [])。
    返回 (dir_name or None, images: List[Path])。
    """
    root = Path(material_root)
    if not root.exists():
        return None, []
    candidates = []
    if preferred:
        d = root / preferred
        if d.is_dir():
            candidates.append(d)
    candidates += [d for d in sorted(root.iterdir()) if d.is_dir()]
    seen = set()
    for d in candidates:
        if d in seen:
            continue
        seen.add(d)
        imgs = [f for f in sorted(d.iterdir()) if f.is_file() and f.suffix.lower() in IMG_EXTS]
        if imgs:
            return d.name, imgs
    return None, []


def first_available_sku(db_path, basemap_root, spu_code: str) -> Optional[str]:
    """返回该款号下第一个「本地有底图」的 SKU.code；无则 None。"""
    for c in list_colors(db_path, spu_code):
        if find_basemap(basemap_root, spu_code, c["sku_code"]) is not None:
            return c["sku_code"]
    return None
