# -*- coding: utf-8 -*-
"""
AI 裁片识别接口
功能：识别裁片部位、分析颜色花样、验证套图结果
"""

from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel
from typing import Optional
import json, logging
from app.core.config import settings
from app.core.security import get_current_user
from app.db import get_db
from sqlalchemy.orm import Session
from app.models.user import User
from app.api.v1.ai_llm import (
    call_vision_messages,
    get_runtime_ai_config,
    verify_pattern_result,
    has_ai_config,
)

log = logging.getLogger(__name__)
if not log.handlers:
    log.setLevel(logging.INFO)
    log.propagate = False
    _h = logging.StreamHandler()
    _h.setFormatter(
        logging.Formatter("[%(asctime)s][%(name)s][%(levelname)s] %(message)s")
    )
    log.addHandler(_h)

router = APIRouter()

# ==================== 数据模型 ====================


class IdentifyPiecesRequest(BaseModel):
    canvas_base64: str
    garment_base64: Optional[str] = None
    layers_info: str
    vision_model: Optional[str] = None


class VerifyResultRequest(BaseModel):
    garment_base64: str
    canvas_base64: str
    prompt: Optional[str] = None
    vision_model: Optional[str] = None


# ==================== 裁片识别接口 ====================


@router.post("/ai/identify-pieces")
async def identify_pieces(
    data: IdentifyPiecesRequest,
    current_username: str = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    """用视觉模型识别裁片部位 + 分析成衣各部位的颜色花样"""
    user = db.query(User).filter(User.username == current_username).first()
    runtime_ai_config = get_runtime_ai_config(user)
    effective_vision_model = (
        data.vision_model
        or (user.ai_vision_model if user else None)
        or settings.AI_VISION_MODEL
    )
    if not has_ai_config(runtime_ai_config):
        raise HTTPException(400, "请先在 API 配置页填写转发 Key，或联系管理员配置默认 AI_API_KEY")

    try:
        result = _identify_garment_pieces(
            data.canvas_base64,
            data.layers_info,
            data.garment_base64,
            vision_model=effective_vision_model,
            runtime_ai_config=runtime_ai_config,
        )
        return {"code": 200, "data": result}
    except Exception as e:
        log.error(f"裁片识别失败: {e}", exc_info=True)
        raise HTTPException(500, f"裁片识别失败: {str(e)}")


@router.post("/ai/verify-result")
async def verify_result(
    data: VerifyResultRequest,
    current_username: str = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    """对比原始成衣和套图结果，给出验证反馈"""
    user = db.query(User).filter(User.username == current_username).first()
    runtime_ai_config = get_runtime_ai_config(user)
    effective_vision_model = (
        data.vision_model
        or (user.ai_vision_model if user else None)
        or settings.AI_VISION_MODEL
    )
    if not has_ai_config(runtime_ai_config):
        raise HTTPException(400, "请先在 API 配置页填写转发 Key，或联系管理员配置默认 AI_API_KEY")

    try:
        feedback = verify_pattern_result(
            data.garment_base64,
            data.canvas_base64,
            data.prompt,
            vision_model=effective_vision_model,
            runtime_config=runtime_ai_config,
        )
        return {"code": 200, "data": {"feedback": feedback}}
    except Exception as e:
        log.error(f"验证失败: {e}", exc_info=True)
        raise HTTPException(500, f"验证失败: {str(e)}")


# ==================== 核心识别逻辑 ====================


def _identify_garment_pieces(
    canvas_b64: str,
    layers_info: str,
    garment_b64: str = None,
    vision_model: str = None,
    runtime_ai_config=None,
) -> dict:
    """用视觉模型分析画布+成衣，识别裁片部位并判断颜色/花样"""
    use_model = vision_model or settings.AI_VISION_MODEL

    log.info(f"{'=' * 60}")
    log.info(f"[IdentifyPieces] 调用视觉模型识别裁片 + 分析花样")
    log.info(f"[IdentifyPieces] 模型: {use_model}")
    log.info(
        f"[IdentifyPieces] 画布: {len(canvas_b64) // 1024}KB, 成衣: {len(garment_b64) // 1024 if garment_b64 else 0}KB"
    )
    log.info(f"[IdentifyPieces] 图层:\n{layers_info[:500]}")

    layer_names = []
    for line in layers_info.strip().split("\n"):
        name = line.split("(")[0].strip()
        if name:
            layer_names.append(name)

    ex1 = layer_names[0] if len(layer_names) > 0 else "图层名1"
    ex2 = layer_names[1] if len(layer_names) > 1 else "图层名2"
    ex3 = layer_names[2] if len(layer_names) > 2 else "图层名3"

    if garment_b64:
        prompt = f"""你需要完成三个任务：

**任务1：识别裁片部位**
Image 2 是 PS 文档中的裁片轮廓图。以下是图层信息：
{layers_info}

请根据形状、大小识别每个**图层组**是什么服装部位（前片、后片、袖子、领口等）。
⚠️ mapping 的 key 必须是上面图层信息中的**实际图层组名称**（如 "{ex1}"、"{ex2}" 等），不要自己编名字！

**任务2：判断花型覆盖模式 pattern_mode**
Image 1 是成衣照片。请判断花型属于哪种模式：
- "all_over"：所有裁片来自同一块面料（碎花/格子/渐变等整体花型覆盖全身）
- "placement"：各裁片独立处理（有的印花有的纯色，如卡通卫衣）
- "color_block"：全部纯色拼接

如果是 all_over，还需提供 fabric_info：
- fabric_type: 面料印花类型
- pattern_direction: 花型方向
- pattern_elements: 花型元素描述
- color_transition: 色彩过渡描述
- density: 花型密度描述

**任务3：分析每个裁片**
- type: solid / fill_pattern / theme_pattern / mixed_pattern / all_over
- solid 和 theme_pattern 必须给 color（hex值）
- 如果某个裁片在照片中**看不到**（如后片），设置 visible: false 并推理
- 左右对称片标记 symmetric_pairs

用 JSON 回答（key 用实际图层名）：
```json
{{
  "pattern_mode": "all_over",
  "fabric_info": {{
    "fabric_type": "数码印花",
    "pattern_direction": "上下渐变",
    "pattern_elements": "白色百合花朵 + 灰白格纹底",
    "color_transition": "从黑色渐变到灰白色",
    "density": "上部花朵密集大朵，下部稀疏小朵"
  }},
  "mapping": {{
    "{ex1}": "左袖",
    "{ex2}": "前片"
  }},
  "analysis": [
    {{"layer": "{ex1}", "piece": "左袖", "type": "all_over", "visible": true, "description": "黑底白花渐变"}},
    {{"layer": "{ex2}", "piece": "前片", "type": "all_over", "visible": true, "description": "上半黑底大花+下半灰白格纹"}},
    {{"layer": "{ex3}", "piece": "后片", "type": "all_over", "visible": false, "inferred_from": "{ex2}", "inference_reason": "全身花型面料，后片花型与前片相同", "confidence": "high"}}
  ],
  "symmetric_pairs": [["{ex1}", "对称片名"]],
  "base_color": "#000000"
}}
```

⚠️ 重要：
- mapping 和 analysis 中的 layer 必须用**实际图层组名称**
- 看不到的部位设 visible: false 并说明推理依据
- 左右对称的片标记 symmetric_pairs
只返回 JSON，不要其他文字。"""
    else:
        prompt = f"""这是一张 PS 文档裁片截图。图层信息：
{layers_info}

识别每个图层组的服装部位，mapping 的 key 必须用**实际图层名**：
```json
{{"mapping": {{"{ex1}": "前片", "{ex2}": "后片"}}}}
```
只返回 JSON。"""

    log.info(f"[IdentifyPieces] 使用豆包视觉: {use_model}")
    images = []
    if garment_b64:
        images.append(garment_b64)
    images.append(canvas_b64)
    content = call_vision_messages(
        prompt,
        images,
        model_override=use_model,
        runtime_config=runtime_ai_config,
    )
    log.info(f"[IdentifyPieces] 视觉模型回复: {content[:500]}")

    try:
        clean = content.strip()
        if "```" in clean:
            clean = clean.split("```")[1]
            if clean.startswith("json"):
                clean = clean[4:]
            clean = clean.strip()
        parsed = json.loads(clean)

        if "mapping" in parsed:
            return parsed
        else:
            return {"mapping": parsed}
    except json.JSONDecodeError:
        log.warning(f"[IdentifyPieces] JSON 解析失败")
        return {"mapping": {}, "raw_response": content}
