"""Skill 基础类 - SkillConfig, IntentConfig, QualityGateConfig, Skill"""

from __future__ import annotations

import logging
from dataclasses import dataclass, field
from typing import Any

from agentkit.core.config_driven import AgentConfig
from agentkit.core.exceptions import ConfigValidationError
from agentkit.skills.schema import CapabilityTag, DependencyDecl
from agentkit.tools.base import Tool

logger = logging.getLogger(__name__)


@dataclass
class EvolutionConfig:
    """Evolution configuration"""

    enabled: bool = False
    reflect_on_failure: bool = True  # Whether to reflect on failed tasks
    auto_apply: bool = False  # Whether to auto-apply optimizations (without AB test)
    min_quality_threshold: float = 0.5  # Minimum quality score to trigger optimization
    reflector_type: str = "auto"  # "llm" / "rule" / "auto"
    auxiliary_model: str | None = None  # Model name for LLM reflection
    optimizer_type: str = "auto"  # "llm" / "bootstrap" / "auto"
    strategy_tuning_enabled: bool = False  # Whether to enable strategy tuning
    ab_test_min_samples: int = 10  # Minimum samples for A/B test significance


@dataclass
class IntentConfig:
    """意图配置"""

    keywords: list[str] = field(default_factory=list)
    description: str = ""
    examples: list[str] = field(default_factory=list)


@dataclass
class QualityGateConfig:
    """质量门控配置"""

    required_fields: list[str] = field(default_factory=list)
    min_word_count: int = 0
    max_retries: int = 0
    custom_validator: str | None = None


class SkillConfig(AgentConfig):
    """扩展 AgentConfig，新增 intent、quality_gate、execution_mode 等 v2 字段

    完全向后兼容：旧 YAML 无 intent/quality_gate/execution_mode 字段时自动填充默认值。
    """

    VALID_EXECUTION_MODES = {"react", "direct", "custom", "rewoo", "plan_exec", "reflexion"}

    def __init__(
        self,
        name: str,
        agent_type: str,
        version: str = "1.0.0",
        description: str = "",
        task_mode: str = "llm_generate",
        supported_tasks: list[str] | None = None,
        max_concurrency: int = 1,
        input_schema: dict[str, Any] | None = None,
        output_schema: dict[str, Any] | None = None,
        prompt: dict[str, str] | None = None,
        llm: dict[str, Any] | None = None,
        tools: list[str] | None = None,
        memory: dict[str, Any] | None = None,
        custom_handler: str | None = None,
        # v2 新增字段
        intent: dict[str, Any] | None = None,
        quality_gate: dict[str, Any] | None = None,
        execution_mode: str = "react",
        max_steps: int = 5,
        evolution: dict[str, Any] | None = None,
        # v3 新增字段：SKILL.md 支持
        skill_md_path: str | None = None,
        disclosure_level: int = 0,
        # v4 新增字段：依赖声明、能力标签
        dependencies: list[dict[str, Any] | DependencyDecl] | None = None,
        capabilities: list[str | dict[str, Any] | CapabilityTag] | None = None,
        # v5 新增字段：对齐守卫
        alignment: dict[str, Any] | None = None,
    ):
        super().__init__(
            name=name,
            agent_type=agent_type,
            version=version,
            description=description,
            task_mode=task_mode,
            supported_tasks=supported_tasks,
            max_concurrency=max_concurrency,
            input_schema=input_schema,
            output_schema=output_schema,
            prompt=prompt,
            llm=llm,
            tools=tools,
            memory=memory,
            custom_handler=custom_handler,
        )
        self.intent = IntentConfig(**(intent or {}))
        self.quality_gate = QualityGateConfig(**(quality_gate or {}))
        self.execution_mode = execution_mode
        self.max_steps = max_steps
        self.evolution = EvolutionConfig(**(evolution or {}))
        self.skill_md_path = skill_md_path
        self.disclosure_level = disclosure_level
        # v4: 解析依赖和能力标签
        self.dependencies = self._parse_dependencies(dependencies or [])
        self.capabilities = self._parse_capabilities(capabilities or [])
        # v5: 对齐守卫配置
        from agentkit.quality.alignment import AlignmentConfig
        self.alignment = AlignmentConfig(**(alignment or {}))
        self._validate_v2()

    def _validate_v2(self) -> None:
        """校验 v2 新增字段"""
        if self.execution_mode not in self.VALID_EXECUTION_MODES:
            raise ConfigValidationError(
                agent_name=self.name,
                key="execution_mode",
                reason=(
                    f"Invalid execution_mode '{self.execution_mode}', "
                    f"must be one of {self.VALID_EXECUTION_MODES}"
                ),
            )

    @staticmethod
    def _parse_dependencies(
        raw: list[dict[str, Any] | DependencyDecl],
    ) -> list[DependencyDecl]:
        """解析依赖声明列表，支持 dict 或 DependencyDecl 实例"""
        result: list[DependencyDecl] = []
        for item in raw:
            if isinstance(item, DependencyDecl):
                result.append(item)
            elif isinstance(item, dict):
                result.append(DependencyDecl(**item))
            else:
                logger.warning(f"Skipping invalid dependency declaration: {item}")
        return result

    @staticmethod
    def _parse_capabilities(
        raw: list[str | dict[str, Any] | CapabilityTag],
    ) -> list[CapabilityTag]:
        """解析能力标签列表，支持 str / dict / CapabilityTag 实例"""
        result: list[CapabilityTag] = []
        for item in raw:
            if isinstance(item, CapabilityTag):
                result.append(item)
            elif isinstance(item, str):
                result.append(CapabilityTag(tag=item))
            elif isinstance(item, dict):
                result.append(CapabilityTag(**item))
            else:
                logger.warning(f"Skipping invalid capability declaration: {item}")
        return result

    @classmethod
    def from_dict(cls, data: dict[str, Any]) -> "SkillConfig":
        """从字典创建配置"""
        return cls(
            name=data["name"],
            agent_type=data["agent_type"],
            version=data.get("version", "1.0.0"),
            description=data.get("description", ""),
            task_mode=data.get("task_mode", "llm_generate"),
            supported_tasks=data.get("supported_tasks"),
            max_concurrency=data.get("max_concurrency", 1),
            input_schema=data.get("input_schema"),
            output_schema=data.get("output_schema"),
            prompt=data.get("prompt"),
            llm=data.get("llm"),
            tools=data.get("tools"),
            memory=data.get("memory"),
            custom_handler=data.get("custom_handler"),
            intent=data.get("intent"),
            quality_gate=data.get("quality_gate"),
            execution_mode=data.get("execution_mode", "react"),
            max_steps=data.get("max_steps", 5),
            evolution=data.get("evolution"),
            skill_md_path=data.get("skill_md_path"),
            disclosure_level=data.get("disclosure_level", 0),
            dependencies=data.get("dependencies"),
            capabilities=data.get("capabilities"),
            alignment=data.get("alignment"),
        )

    @classmethod
    def from_yaml(cls, path: str) -> "SkillConfig":
        """从 YAML 文件加载配置"""
        import yaml

        with open(path, "r", encoding="utf-8") as f:
            data = yaml.safe_load(f)
        if not isinstance(data, dict):
            raise ConfigValidationError(
                agent_name="unknown",
                key="config",
                reason=f"YAML config must be a mapping, got {type(data)}",
            )
        return cls.from_dict(data)

    def to_dict(self) -> dict[str, Any]:
        """序列化为字典，包含 v2 字段"""
        d = super().to_dict()
        d["intent"] = {
            "keywords": self.intent.keywords,
            "description": self.intent.description,
            "examples": self.intent.examples,
        }
        d["quality_gate"] = {
            "required_fields": self.quality_gate.required_fields,
            "min_word_count": self.quality_gate.min_word_count,
            "max_retries": self.quality_gate.max_retries,
            "custom_validator": self.quality_gate.custom_validator,
        }
        d["execution_mode"] = self.execution_mode
        d["max_steps"] = self.max_steps
        d["evolution"] = {
            "enabled": self.evolution.enabled,
            "reflect_on_failure": self.evolution.reflect_on_failure,
            "auto_apply": self.evolution.auto_apply,
            "min_quality_threshold": self.evolution.min_quality_threshold,
            "reflector_type": self.evolution.reflector_type,
            "auxiliary_model": self.evolution.auxiliary_model,
            "optimizer_type": self.evolution.optimizer_type,
            "strategy_tuning_enabled": self.evolution.strategy_tuning_enabled,
            "ab_test_min_samples": self.evolution.ab_test_min_samples,
        }
        d["skill_md_path"] = self.skill_md_path
        d["disclosure_level"] = self.disclosure_level
        # v4: 序列化依赖和能力标签
        d["dependencies"] = [
            {
                "name": dep.name,
                "version_constraint": dep.version_constraint,
                "type": dep.type,
                "required": dep.required,
            }
            for dep in self.dependencies
        ]
        d["capabilities"] = [
            {"tag": cap.tag, "description": cap.description}
            for cap in self.capabilities
        ]
        # v5: 对齐守卫
        d["alignment"] = {
            "constraints": self.alignment.constraints,
            "cascade_max_interactions": self.alignment.cascade_max_interactions,
            "cascade_max_depth": self.alignment.cascade_max_depth,
            "audit_enabled": self.alignment.audit_enabled,
            "audit_model": self.alignment.audit_model,
        }
        return d


class Skill:
    """Skill 封装 SkillConfig + 绑定 Tools

    一个 Skill 代表一个可执行的技能，包含配置和绑定的工具。
    """

    def __init__(self, config: SkillConfig, tools: list[Tool] | None = None):
        self._config = config
        self._tools: list[Tool] = tools or []

    @property
    def name(self) -> str:
        return self._config.name

    @property
    def version(self) -> str:
        return self._config.version

    @property
    def config(self) -> SkillConfig:
        return self._config

    @property
    def tools(self) -> list[Tool]:
        return self._tools

    @property
    def capabilities(self) -> list:
        """返回 Skill 的能力标签列表"""
        return self._config.capabilities

    @property
    def dependencies(self) -> list:
        """返回 Skill 的依赖声明列表"""
        return self._config.dependencies

    def bind_tool(self, tool: Tool) -> None:
        """绑定工具到 Skill"""
        self._tools.append(tool)

    def unbind_tool(self, tool_name: str) -> None:
        """解绑工具"""
        self._tools = [t for t in self._tools if t.name != tool_name]

    def to_dict(self) -> dict:
        """序列化为字典"""
        return {
            "config": self._config.to_dict(),
            "tools": [t.to_dict() for t in self._tools],
        }
