"""
API入口 - 优化集成版（最终版本）
整合了4个核心优化模块：
1. GiftFilterV2 - 增强禁忌过滤
2. BlessingGeneratorV2 - 个性化祝福语
3. DialogManager - 对话式决策支持
4. InputValidator - 增强数据验证
"""
from typing import List, Dict, Optional, Tuple
from .recommender import Recommender
from .parser import InputParser
from .reason import ReasonGenerator
from .blessing_v2 import BlessingGeneratorV2
from .filter_v2 import GiftFilterV2
from .dialog_manager import DialogManager
from .output_formatter import OutputFormatter
from .preference import get_preference
from .validation import InputValidator, validate_gift_request, sanitize_user_input
from .security import security, protect_sql_input, protect_html_content

class GiftAdvisor:
    """礼物推荐助手 - 最终版"""

    def __init__(self, user_id: str = "default", enhanced: bool = True):
        # 核心模块
        self.recommender = Recommender()
        self.parser = InputParser()
        self.reason_gen = ReasonGenerator()
        self.formatter = OutputFormatter()
        self.preference = get_preference()
        
        # 新模块
        self.enhanced = enhanced
        if enhanced:
            self.blessing_gen = BlessingGeneratorV2()
            self.filter_v2 = GiftFilterV2()
            self.dialog = DialogManager()
        else:
            from .blessing import BlessingGenerator
            from .filter import GiftFilter
            self.blessing_gen = BlessingGenerator()
            self.filter_v2 = GiftFilter()
            self.dialog = None
        
        # 验证模块
        self.validator = InputValidator()
        # 安全模块
        self.security = security
        
        # 用户状态
        self.user_id = user_id
        self.conversation_state = "initial" if enhanced else "direct"

    def recommend(
        self,
        relation: Optional[str] = None,
        occasion: Optional[str] = None,
        budget_min: Optional[int] = None,
        budget_max: Optional[int] = None,
        limit: int = 5
    ) -> Dict:
        """推荐礼物 - 智能验证版本"""
        # 智能数据验证：只有在有参数时才验证
        input_data = {}
        
        if relation:
            # 验证关系
            valid_rel, rel_errors = self._validate_relation(relation)
            if not valid_rel:
                return {
                    "success": False,
                    "type": "validation_error",
                    "message": "关系参数验证失败",
                    "errors": rel_errors,
                    "data": {}
                }
            input_data["relation"] = relation
        
        if occasion:
            # 验证场合
            valid_occ, occ_errors = self._validate_occasion(occasion)
            if not valid_occ:
                return {
                    "success": False,
                    "type": "validation_error",
                    "message": "场合参数验证失败",
                    "errors": occ_errors,
                    "data": {}
                }
            input_data["occasion"] = occasion
        
        if budget_min is not None:
            # 验证预算最小值
            if budget_min < 0:
                return {
                    "success": False,
                    "type": "validation_error",
                    "message": "预算参数验证失败",
                    "errors": ["预算最小值不能为负数"],
                    "data": {}
                }
            input_data["budget_min"] = budget_min
        
        if budget_max is not None:
            # 验证预算最大值
            if budget_max <= 0:
                return {
                    "success": False,
                    "type": "validation_error",
                    "message": "预算参数验证失败",
                    "errors": ["预算最大值必须大于0"],
                    "data": {}
                }
            input_data["budget_max"] = budget_max
        
        # 验证预算范围合理性
        if budget_min is not None and budget_max is not None:
            if budget_min > budget_max:
                return {
                    "success": False,
                    "type": "validation_error",
                    "message": "预算参数验证失败",
                    "errors": ["最低预算不能大于最高预算"],
                    "data": {}
                }
        
        # 获取推荐
        gifts = self.recommender.recommend(
            relation=relation,
            occasion=occasion,
            budget_min=budget_min,
            budget_max=budget_max,
            limit=limit * 2
        )
        
        # 禁忌过滤
        filtered_gifts = gifts
        taboo_report = {"summary": "✅ 无禁忌礼物"}
        
        if self.enhanced:
            filtered_gifts, taboo_report = self.filter_v2.filter(
                gifts=gifts,
                relation=relation
            )
        
        if len(filtered_gifts) < limit:
            filtered_gifts = gifts[:limit]
        
        filtered_gifts = filtered_gifts[:limit]
        
        # 生成结果
        recommendations = []
        for gift in filtered_gifts:
            reason = self.reason_gen.generate(gift, relation, occasion)
            score = self._calculate_score(gift, budget_max)
            
            recommendations.append({
                "name": gift.get("name"),
                "price": gift.get("price"),
                "reason": reason,
                "score": score,
            })
        
        recommendations.sort(key=lambda x: x["score"], reverse=True)
        
        # 祝福语
        if self.enhanced and recommendations:
            top_gift = recommendations[0]["name"]
            blessing = self.blessing_gen.generate(
                occasion=occasion,
                relation=relation,
                gift_name=top_gift,
                style="标准版"
            )
            blessing_options = self.blessing_gen.generate_multiple_options(
                occasion=occasion,
                relation=relation,
                gift_name=top_gift,
                count=3
            )
        else:
            blessing = "祝你开心每一天！"
            blessing_options = []
        
        return {
            "success": True,
            "query": {
                "relation": relation,
                "occasion": occasion,
                "budget": f"{budget_min or '?'}-{budget_max or '?'}元",
            },
            "recommendations": recommendations,
            "blessing": blessing,
            "blessing_options": blessing_options,
            "taboo_report": taboo_report,
            "count": len(recommendations),
        }

    def parse_and_recommend(self, text: str, limit: int = 5) -> Dict:
        """解析自然语言并推荐 - 增强安全验证版本"""
        # 安全防护：清理输入，防止SQL注入和XSS
        safe_text = protect_sql_input(text)
        safe_text = protect_html_content(safe_text)
        
        # 文本验证
        valid, errors = self.validator.validate_natural_language(safe_text)
        if not valid:
            # 记录安全事件
            self.security.log_security_event("INPUT_VALIDATION_FAILED", self.user_id, 
                                           f"输入验证失败: {errors}")
            return {
                "success": False,
                "type": "validation_error",
                "message": "输入文本验证失败",
                "errors": errors,
                "data": {}
            }
        
        # 检测"换一个"
        change_keywords = ["换一个", "再来一个", "还有吗"]
        if any(kw in text for kw in change_keywords):
            last_query = self.preference.get_last_query(self.user_id)
            if last_query:
                return self._handle_change_request()
        
        # 智能判断是否进入对话模式
        should_enter_dialog = False
        
        if self.enhanced:
            # 判断标准：
            # 1. 文本较短（< 30字符）
            # 2. 没有明显的关键信息（如预算、场合、关系）
            # 3. 看起来像是对话的开始
            
            text_lower = text.lower()
            
            # 检查是否包含完整信息的关键词
            has_budget_keywords = any(kw in text_lower for kw in ["预算", "块钱", "元", "价格", "价钱"])
            has_occasion_keywords = any(kw in text_lower for kw in ["生日", "情人节", "节日", "纪念日", "母亲节", "父亲节"])
            has_relation_keywords = any(kw in text_lower for kw in ["妈妈", "爸爸", "女友", "男友", "朋友", "同事", "领导", "客户", "老师", "长辈", "孩子"])
            
            # 如果包含完整信息，优先解析
            if has_relation_keywords and has_occasion_keywords:
                # 有明确的关系和场合，直接解析
                should_enter_dialog = False
            elif len(text) < 20 and not has_budget_keywords:
                # 短文本且没有预算信息，可能是对话开始
                should_enter_dialog = True
            elif "?" in text or "？" in text:
                # 包含问号，可能是提问
                should_enter_dialog = True
            else:
                # 其他情况，尝试解析
                should_enter_dialog = False
        
        if should_enter_dialog:
            dialog_result = self.process_message(text)
            
            # 统一对话模式的返回结构
            if dialog_result.get("type") == "question":
                # 对话中，返回问题
                return {
                    "success": True,
                    "type": "question",
                    "message": dialog_result.get("message", ""),
                    "needs_clarification": True,
                    "clarification_questions": [dialog_result.get("message", "请提供更多信息")],
                    "data": {
                        "conversation_state": self.conversation_state,
                        "user_preferences": self._get_user_preferences_summary()
                    }
                }
            else:
                # 对话完成，返回推荐
                return dialog_result
        
        # 解析自然语言
        parsed = self.parser.parse(text)
        
        if parsed.get("needs_clarification"):
            return {
                "success": False,
                "type": "clarification_needed",
                "needs_clarification": True,
                "missing_fields": parsed.get("missing_fields", []),
                "clarification_questions": self.parser.get_clarification_questions(
                    parsed.get("missing_fields", [])
                ),
                "parsed": parsed,
                "data": {
                    "parsed_info": parsed
                }
            }
        
        # 保存查询
        self.preference.set_last_query(parsed, self.user_id)
        self.preference.clear_shown_gifts(self.user_id)
        
        # 推荐
        result = self.recommend(
            relation=parsed.get("relation"),
            occasion=parsed.get("occasion"),
            budget_min=parsed.get("budget_min"),
            budget_max=parsed.get("budget_max"),
            limit=limit
        )
        
        # 统一推荐结果的返回结构
        result["type"] = "recommendation"
        result["data"] = {
            "recommendations": result.get("recommendations", []),
            "query": result.get("query", {}),
            "taboo_report": result.get("taboo_report", {})
        }
        
        # 记录
        for gift in result.get("recommendations", []):
            self.preference.add_shown_gift(gift["name"], self.user_id)
        
        return result

    def process_message(self, user_input: str) -> Dict:
        """对话处理 - 返回统一结构"""
        if not self.enhanced or not self.dialog:
            return {
                "success": False,
                "type": "error",
                "message": "对话功能未启用",
                "data": {}
            }
        
        response, dialog_state = self.dialog.process_message(user_input)
        
        # 更新状态
        self.conversation_state = dialog_state["state"]
        
        # 生成响应
        if dialog_state["state"] == "ready_to_recommend":
            # 生成推荐
            recommendation = self._generate_recommendation(dialog_state["preferences"])
            # 确保推荐结果有统一结构
            recommendation["type"] = "recommendation"
            recommendation["message"] = "为您生成以下推荐："
            recommendation["data"] = {
                "recommendations": recommendation.get("recommendations", []),
                "query": recommendation.get("query", {}),
                "taboo_report": recommendation.get("taboo_report", {}),
                "conversation_state": self.conversation_state
            }
            return recommendation
        elif dialog_state["state"] == "waiting_feedback" and "推荐" in response:
            # 在等待反馈状态中可能已经有推荐
            recommendation = self._generate_recommendation(dialog_state["preferences"])
            recommendation["type"] = "recommendation_with_feedback"
            recommendation["message"] = response
            recommendation["data"] = {
                "recommendations": recommendation.get("recommendations", []),
                "query": recommendation.get("query", {}),
                "taboo_report": recommendation.get("taboo_report", {}),
                "conversation_state": self.conversation_state,
                "feedback_needed": True
            }
            return recommendation
        else:
            # 继续对话
            return {
                "success": True,
                "type": "question",
                "message": response,
                "data": {
                    "conversation_state": self.conversation_state,
                    "user_preferences": dialog_state.get("preferences", {})
                }
            }

    def _handle_change_request(self) -> Dict:
        """处理换一个请求"""
        last_query = self.preference.get_last_query(self.user_id)
        if not last_query:
            return {
                "success": False,
                "message": "没有之前的查询记录"
            }
        
        # 已展示的礼物
        shown_gifts = self.preference.get_shown_gifts(self.user_id)
        
        # 获取更多推荐
        all_gifts = self.recommender.recommend(
            relation=last_query.get("relation"),
            occasion=last_query.get("occasion"),
            budget_min=last_query.get("budget_min"),
            budget_max=last_query.get("budget_max"),
            limit=20
        )
        
        # 过滤
        new_gifts = [g for g in all_gifts if g["name"] not in shown_gifts]
        if not new_gifts:
            self.preference.clear_shown_gifts(self.user_id)
            new_gifts = all_gifts
        
        # 禁忌过滤
        if self.enhanced:
            new_gifts, _ = self.filter_v2.filter(
                gifts=new_gifts,
                relation=last_query.get("relation")
            )
        
        # 生成推荐
        recommendations = []
        for gift in new_gifts[:5]:
            reason = self.reason_gen.generate(gift, last_query.get("relation"))
            score = self._calculate_score(gift, last_query.get("budget_max"))
            recommendations.append({
                "name": gift.get("name"),
                "price": gift.get("price"),
                "reason": reason,
                "score": score,
            })
            self.preference.add_shown_gift(gift["name"], self.user_id)
        
        # 祝福语
        if self.enhanced:
            blessing = self.blessing_gen.generate(
                occasion=last_query.get("occasion"),
                relation=last_query.get("relation")
            )
        else:
            blessing = "祝你开心！"
        
        return {
            "success": True,
            "query": {
                "relation": last_query.get("relation"),
                "occasion": last_query.get("occasion"),
                "budget": f"{last_query.get('budget_min') or 0}-{last_query.get('budget_max') or '不限'}",
            },
            "recommendations": recommendations,
            "blessing": blessing,
            "count": len(recommendations),
        }

    def _generate_recommendation(self, preferences: Dict) -> Dict:
        """生成推荐"""
        relation = preferences.get("relation")
        occasion = preferences.get("occasion")
        budget_min = preferences.get("budget_min")
        budget_max = preferences.get("budget_max")
        
        return self.recommend(
            relation=relation,
            occasion=occasion,
            budget_min=budget_min,
            budget_max=budget_max
        )

    def _calculate_score(self, gift: Dict, budget_max: Optional[int] = None) -> int:
        """计算分数"""
        score = 80
        
        price = gift.get("price", 0)
        if budget_max:
            ratio = price / budget_max
            if 0.3 <= ratio <= 0.7:
                score += 10
        
        if gift.get("reason"):
            score += 5
        
        return min(score, 100)

    def explain_taboo(self, gift_name: str, relation: str = None) -> Dict:
        """解释禁忌"""
        if not self.enhanced:
            return {"success": False, "message": "增强功能未启用"}
        
        explanation = self.filter_v2.explain_taboo(gift_name, relation)
        alternatives = self.filter_v2.get_safe_alternatives(gift_name)
        
        return {
            "success": True,
            "gift_name": gift_name,
            "explanation": explanation,
            "alternatives": alternatives,
            "has_taboo": "暂无发现禁忌" not in explanation
        }

    def get_blessing_options(
        self,
        occasion: str,
        relation: str = None,
        gift_name: str = None,
        count: int = 3
    ) -> Dict:
        """获取祝福语选项"""
        if not self.enhanced:
            return {"success": False, "message": "增强功能未启用"}
        
        options = self.blessing_gen.generate_multiple_options(
            occasion=occasion,
            relation=relation,
            gift_name=gift_name,
            count=count
        )
        
        return {
            "success": True,
            "occasion": occasion,
            "relation": relation,
            "gift_name": gift_name,
            "options": options
        }

    def _validate_relation(self, relation: str) -> Tuple[bool, List[str]]:
        """验证关系参数"""
        errors = []
        
        allowed_relations = ["妈妈", "爸爸", "女友", "男友", "朋友", "同事", "领导", "客户", "老师", "长辈", "孩子"]
        
        if relation not in allowed_relations:
            errors.append(f"关系参数 '{relation}' 不在允许范围内")
        
        return len(errors) == 0, errors

    def _validate_occasion(self, occasion: str) -> Tuple[bool, List[str]]:
        """验证场合参数"""
        errors = []
        
        allowed_occasions = ["生日", "情人节", "纪念日", "母亲节", "父亲节", "节日", "乔迁", "结婚", "道歉", "感谢"]
        
        if occasion not in allowed_occasions:
            errors.append(f"场合参数 '{occasion}' 不在允许范围内")
        
        return len(errors) == 0, errors

    def _get_user_preferences_summary(self) -> Dict:
        """获取用户偏好摘要"""
        if not self.dialog:
            return {}
        
        summary = {}
        # 这里可以添加更多摘要信息
        return summary

    def reset_conversation(self):
        """重置对话"""
        if self.dialog:
            self.dialog.reset_conversation()
        
        self.conversation_state = "initial"
        
        return {
            "success": True,
            "type": "conversation_reset",
            "message": "对话已重置"
        }


# 便捷函数
def recommend_gift(
    relation: str = None,
    occasion: str = None,
    budget_min: int = None,
    budget_max: int = None,
    enhanced: bool = True
) -> Dict:
    """便捷推荐"""
    advisor = GiftAdvisor(enhanced=enhanced)
    return advisor.recommend(relation, occasion, budget_min, budget_max)

def parse_and_recommend(text: str, enhanced: bool = True) -> Dict:
    """便捷解析推荐"""
    advisor = GiftAdvisor(enhanced=enhanced)
    return advisor.parse_and_recommend(text)

def explain_gift_taboo(gift_name: str, relation: str = None) -> Dict:
    """便捷解释禁忌"""
    advisor = GiftAdvisor(enhanced=True)
    return advisor.explain_taboo(gift_name, relation)

def get_blessing_options(
    occasion: str,
    relation: str = None,
    gift_name: str = None,
    count: int = 3
) -> Dict:
    """便捷获取祝福语"""
    advisor = GiftAdvisor(enhanced=True)
    return advisor.get_blessing_options(occasion, relation, gift_name, count)

def start_conversation(user_id: str = "default") -> GiftAdvisor:
    """
    开始对话式推荐
    
    示例:
        advisor = start_conversation("user123")
        result1 = advisor.process_message("我想给妈妈选生日礼物")
        result2 = advisor.process_message("预算500元")
    """
    return GiftAdvisor(user_id=user_id, enhanced=True)


# 测试
if __name__ == "__main__":
    print("=== 测试API ===")
    
    # 推荐测试
    result1 = recommend_gift("妈妈", "生日", 200, 1000)
    print(f"1. 妈妈生日推荐: {result1['count']}个")
    if result1["recommendations"]:
        print("Top 3:")
        for i, rec in enumerate(result1["recommendations"][:3], 1):
            print(f"  {i}. {rec['name']} ({rec['price']}元) - {rec['reason'][:20]}...")
    
    # 禁忌解释
    result2 = explain_gift_taboo("精美时钟", "长辈")
    print(f"\n2. 禁忌解释:")
    print(f"   {result2['explanation'][:60]}...")
    
    # 祝福语选项
    result3 = get_blessing_options("情人节", "女友", "巧克力")
    print(f"\n3. 祝福语选项:")
    for option in result3["options"]:
        print(f"   • {option[:40]}...")
    
    print("\n✅ 测试完成！")