#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
AI 工作流导入/导出
"""
import copy
import logging
from typing import Any, Dict, List, Optional, Set

from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from ai_platform.models import AIWorkflow

logger = logging.getLogger(__name__)


class WorkflowImportExportException(Exception):
    """工作流导入导出异常"""
    pass


def _collect_subflow_codes_from_definition(definition: Dict[str, Any]) -> Set[str]:
    codes: Set[str] = set()
    for node in definition.get("nodes") or []:
        data = node.get("data") or {}
        code = data.get("subflow_code")
        if code:
            codes.add(code)
    return codes


def _collect_subflow_ids_from_definition(definition: Dict[str, Any]) -> Set[str]:
    ids: Set[str] = set()
    for node in definition.get("nodes") or []:
        data = node.get("data") or {}
        sid = data.get("subflow_id")
        if sid:
            ids.add(sid)
    return ids


def _definition_export_subflow_ids_to_codes(
    definition: Dict[str, Any],
    id_to_code: Dict[str, str],
) -> Dict[str, Any]:
    """导出时将子流程节点 subflow_id 转为 subflow_code"""
    result = copy.deepcopy(definition or {})
    for node in result.get("nodes") or []:
        data = node.get("data")
        if not isinstance(data, dict):
            continue
        sid = data.get("subflow_id")
        if sid and sid in id_to_code:
            data["subflow_code"] = id_to_code[sid]
            data.pop("subflow_id", None)
    return result


def _definition_import_subflow_codes_to_ids(
    definition: Dict[str, Any],
    code_to_id: Dict[str, str],
) -> tuple[Dict[str, Any], List[str]]:
    """导入时将 subflow_code 解析为 subflow_id"""
    result = copy.deepcopy(definition or {})
    unresolved: List[str] = []
    for node in result.get("nodes") or []:
        data = node.get("data")
        if not isinstance(data, dict):
            continue
        code = data.pop("subflow_code", None)
        if not code:
            continue
        wf_id = code_to_id.get(code)
        if wf_id:
            data["subflow_id"] = wf_id
        else:
            unresolved.append(code)
    return result, unresolved


async def export_config(db: AsyncSession, workflow_id: str) -> Dict[str, Any]:
    """导出工作流配置（草稿 definition，子流程引用使用 code）"""
    result = await db.execute(
        select(AIWorkflow).where(
            AIWorkflow.id == workflow_id,
            AIWorkflow.is_deleted == False,
        )
    )
    workflow = result.scalar_one_or_none()
    if not workflow:
        raise WorkflowImportExportException("工作流不存在")

    definition = copy.deepcopy(workflow.definition or {})
    subflow_ids = _collect_subflow_ids_from_definition(definition)

    id_to_code: Dict[str, str] = {}
    if subflow_ids:
        rows = await db.execute(
            select(AIWorkflow.id, AIWorkflow.code).where(
                AIWorkflow.id.in_(subflow_ids),
                AIWorkflow.is_deleted == False,
            )
        )
        id_to_code = {row.id: row.code for row in rows}

    definition = _definition_export_subflow_ids_to_codes(definition, id_to_code)

    return {
        "name": workflow.name,
        "code": workflow.code,
        "workflow_type": workflow.workflow_type or "general",
        "description": workflow.description or "",
        "is_global": workflow.is_global or False,
        "definition": definition,
        "input_variables": workflow.input_variables or [],
        "output_variables": workflow.output_variables or [],
    }


async def check_import(db: AsyncSession, code: str) -> Dict[str, Any]:
    """导入预检查：编码是否冲突"""
    code_exists = False
    if code:
        result = await db.execute(
            select(AIWorkflow).where(
                AIWorkflow.code == code,
                AIWorkflow.is_deleted == False,
            )
        )
        code_exists = result.scalar_one_or_none() is not None

    return {
        "code_exists": code_exists,
        "can_import": not code_exists,
    }


async def import_config(db: AsyncSession, data: Dict[str, Any]) -> AIWorkflow:
    """导入工作流配置"""
    required_fields = ["name", "code"]
    for field in required_fields:
        if not data.get(field):
            raise WorkflowImportExportException(f"缺少必要字段: {field}")

    exists = await db.execute(
        select(AIWorkflow).where(
            AIWorkflow.code == data["code"],
            AIWorkflow.is_deleted == False,
        )
    )
    if exists.scalar_one_or_none():
        raise WorkflowImportExportException(f"工作流编码已存在: {data['code']}")

    definition = copy.deepcopy(data.get("definition") or {})
    subflow_codes = _collect_subflow_codes_from_definition(definition)

    code_to_id: Dict[str, str] = {}
    if subflow_codes:
        rows = await db.execute(
            select(AIWorkflow.id, AIWorkflow.code).where(
                AIWorkflow.code.in_(subflow_codes),
                AIWorkflow.is_deleted == False,
            )
        )
        code_to_id = {row.code: row.id for row in rows}

    definition, unresolved = _definition_import_subflow_codes_to_ids(
        definition, code_to_id
    )
    if unresolved:
        logger.warning(
            "导入工作流时部分子流程未找到，已跳过引用: %s",
            ", ".join(unresolved),
        )

    workflow = AIWorkflow(
        application_id=data.get("application_id"),
        is_global=data.get("is_global", False),
        name=data["name"],
        code=data["code"],
        workflow_type=data.get("workflow_type", "general"),
        description=data.get("description", ""),
        definition=definition,
        input_variables=data.get("input_variables") or [],
        output_variables=data.get("output_variables") or [],
        status="draft",
        version=1,
        published_version=None,
        published_at=None,
        published_definition=None,
    )
    db.add(workflow)
    await db.flush()
    await db.refresh(workflow)

    logger.info("工作流导入成功: %s", workflow.code)
    return workflow
