"""
询问笔录策略服务
基于 1+4+6 架构的核心业务逻辑实现
"""

import os
import time
import json
import tempfile
from typing import Dict, List, Optional, Any
from pathlib import Path
from fastapi import HTTPException

PROMPTS_BASE_DIR = Path(__file__).parent.parent / "prompts" / "inquiry_strategy"


class InquiryStrategyService:
    
    def __init__(self):
        self.prompts_dir = PROMPTS_BASE_DIR
    
    async def get_or_create_strategy(self, case_id: str, user_id: int, db) -> dict:
        """获取已有策略或返回空数据（含智能推荐）"""
        conn, cur = db
        
        await cur.execute(
            "SELECT * FROM inquiry_strategies WHERE case_id = %s ORDER BY created_at DESC LIMIT 1",
            (case_id,)
        )
        result = await cur.fetchone()
        
        if result:
            strategy = dict(result)
            
            # 解析JSON字段
            if strategy.get('attachment_ids'):
                try:
                    strategy['attachment_ids'] = json.loads(strategy['attachment_ids'])
                except:
                    strategy['attachment_ids'] = []
                    
            if strategy.get('token_usage'):
                try:
                    strategy['token_usage'] = json.loads(strategy['token_usage'])
                except:
                    strategy['token_usage'] = {}
                    
            if strategy.get('strategy_config'):
                try:
                    strategy['strategy_config'] = json.loads(strategy['strategy_config'])
                except:
                    strategy['strategy_config'] = {}
            
            return {
                "success": True,
                "data": strategy
            }
        
        # 无历史策略，返回空数据 + 智能推荐
        try:
            case_info = await self._get_case_info(case_id, db)
            recommendation = self._generate_recommendation(case_info)
            
            return {
                "success": True,
                "data": None,
                "recommendation": recommendation
            }
        except HTTPException:
            raise
        except Exception as e:
            # 如果获取案件信息失败，返回默认推荐
            return {
                "success": True,
                "data": None,
                "recommendation": {
                    "industry": {"recommended": "market_regulation", "confidence": 0, "reason": "默认推荐"},
                    "caseType": {"recommended": "general", "confidence": 0, "reason": "默认一般常规案"}
                }
            }
    
    async def _get_case_info(self, case_id: str, db) -> dict:
        """获取案件基本信息"""
        conn, cur = db
        
        await cur.execute(
            """SELECT id, title, case_number, cause, party_name, party_type, 
                      description, illegal_fact_summary, legal_basis, 
                      involved_amount, status
               FROM cases WHERE id = %s""",
            (case_id,)
        )
        result = await cur.fetchone()
        
        if not result:
            raise HTTPException(status_code=404, detail="案件不存在")
        
        return dict(result)
    
    def _generate_recommendation(self, case_info: dict) -> dict:
        """根据案由生成智能推荐"""
        cause = case_info.get('cause', '') or ''
        description = case_info.get('description', '') or ''
        combined_text = f"{cause} {description}"
        
        # 行业关键词匹配规则
        industry_rules = {
            'market_regulation': ['食品', '药品', '价格', '广告', '商标', '特种设备', '质量', '计量', '无证经营'],
            'agriculture': ['农资', '种子', '农药', '化肥', '禁渔', '禁猎', '耕地', '养殖'],
            'culture_tourism': ['网吧', 'KTV', '旅行社', '演艺', '出版', '文物', '娱乐场所'],
            'commerce': ['成品油', '再生资源', '预付卡', '商贸', '拍卖']
        }
        
        best_industry = {'recommended': 'market_regulation', 'confidence': 0, 'reason': '默认推荐市场监管'}
        for industry, keywords in industry_rules.items():
            match_count = sum(1 for kw in keywords if kw in combined_text)
            confidence = min(match_count / len(keywords), 0.99) if keywords else 0
            if confidence > best_industry['confidence']:
                best_industry = {
                    'recommended': industry,
                    'confidence': confidence,
                    'reason': f"案由包含{industry}相关关键词"
                }
        
        # 案情类型匹配规则
        case_type_rules = {
            'minor': ['轻微', '首次', '立即整改', '主动消除', '危害小'],
            'intentional': ['故意', '明知', '屡教不改', '拒不改正', '抗拒检查', '逃避监管'],
            'negligent': ['不知情', '误操作', '被误导', '疏忽', '管理漏洞'],
            'multiple': ['团伙', '多人', '共同', '串通', '合谋', '法人+员工'],
            'complex': ['大额', '链条', '上下游', '涉案金额', '数量巨大', '长期', '系统性']
        }
        
        best_case_type = {'recommended': 'general', 'confidence': 0, 'reason': '默认一般常规案'}
        for ctype, keywords in case_type_rules.items():
            match_count = sum(1 for kw in keywords if kw in combined_text)
            confidence = min(match_count / len(keywords), 0.99) if keywords else 0
            if confidence > best_case_type['confidence']:
                best_case_type = {
                    'recommended': ctype,
                    'confidence': confidence,
                    'reason': f"匹配{ctype}特征"
                }
        
        return {
            "industry": best_industry,
            "caseType": best_case_type
        }
    
    async def generate_strategy(
        self,
        case_id: str,
        user_id: int,
        industry_category: str,
        industry_subcategory: str,
        case_type: str,
        supplementary_content: str,
        attachment_ids: list,
        is_auto_recommended: bool = False,
        db=None
    ) -> dict:
        """生成询问笔录策略的主方法"""
        
        start_time = time.time()
        
        # 1. 获取案件信息
        case_info = await self._get_case_info(case_id, db)
        
        # 2. 构建输入上下文
        context = await self._build_context(
            case_info=case_info,
            supplementary_content=supplementary_content,
            attachment_ids=attachment_ids,
            db=db
        )
        
        # 3. 组装策略配置（用于追溯）
        strategy_config = {
            "base_strategies": [
                "identity_lock", "timeline_closed_loop", "four_elements",
                "peripheral_breakthrough", "full_chain_tracing",
                "subjective_mentality", "non_induced_statement"
            ],
            "industry_module": f"{industry_category}.{industry_subcategory or 'general'}",
            "case_type_adapter": case_type
        }
        
        # 4. 组装完整Prompt
        full_prompt = await self._assemble_prompt(
            industry_category=industry_category,
            industry_subcategory=industry_subcategory or '',
            case_type=case_type,
            context=context,
            db=db
        )
        
        # 5. 调用AI模型
        result = await self._call_ai_model(full_prompt, db)
        
        total_time = time.time() - start_time
        
        # 6. 保存到数据库
        strategy_id = await self._save_new_strategy(
            case_id=case_id,
            user_id=user_id,
            config={
                'industry_category': industry_category,
                'industry_subcategory': industry_subcategory or '',
                'case_type': case_type,
                'is_auto_recommended': 1 if is_auto_recommended else 0,
                'attachment_ids': attachment_ids,
                'strategy_config': strategy_config
            },
            context={
                'case_description': case_info.get('description', ''),
                'supplementary_content': supplementary_content
            },
            result=result,
            generation_time=round(total_time, 2),
            db=db
        )
        
        # 7. 返回响应
        return {
            'success': True,
            'data': {
                'strategyId': strategy_id,
                'strategyContent': result['content'],
                'generationTime': round(total_time, 2),
                'tokenUsage': result.get('token_usage', {}),
                'aiModelUsed': result.get('model', ''),
                'strategyConfig': strategy_config
            }
        }
    
    async def _build_context(self, case_info: dict, supplementary_content: str, attachment_ids: list, db) -> str:
        """构建AI输入上下文"""
        sections = []
        
        # 1. 基本案情
        sections.append("### 案件基本信息")
        sections.append(f"- **案件标题**: {case_info.get('title', '')}")
        sections.append(f"- **案号**: {case_info.get('case_number', '')}")
        sections.append(f"- **案由**: {case_info.get('cause', '')}")
        sections.append(f"- **当事人**: {case_info.get('party_name', '')}")
        sections.append(f"- **当事人类型**: {case_info.get('party_type', '')}")
        sections.append(f"\n### 案情描述")
        sections.append(case_info.get('description', '未提供详细描述'))
        
        if case_info.get('illegal_fact_summary'):
            sections.append(f"\n### 违法事实摘要")
            sections.append(case_info['illegal_fact_summary'])
        
        if case_info.get('legal_basis'):
            sections.append(f"\n### 可能涉及的法律依据")
            sections.append(case_info['legal_basis'])
        
        if case_info.get('involved_amount'):
            sections.append(f"\n### 涉案金额")
            sections.append(f"约 {case_info['involved_amount']} 元")
        
        # 2. 执法人员补充信息
        if supplementary_content:
            sections.append(f"\n### 执法人员补充信息与重点核实方向")
            sections.append(supplementary_content)
        
        # 3. 附件信息摘要（简化版）
        if attachment_ids:
            sections.append(f"\n### 已收集的证据材料")
            sections.append(f"已上传 {len(attachment_ids)} 个附件文件")
        
        return '\n'.join(sections)
    
    async def _assemble_prompt(
        self,
        industry_category: str,
        industry_subcategory: str,
        case_type: str,
        context: str,
        db=None
    ) -> str:
        """
        组装完整的Prompt（1+4+6架构的核心实现）
        """
        parts = []
        
        # Part 1: 基础Prompt框架
        base_prompt = await self._load_prompt_file('base_prompt.txt')
        parts.append(base_prompt)
        
        # Part 2: 7大底层策略（固定不变）
        parts.append("\n\n## 七大底层询问策略（必须全部执行）\n")
        strategy_files = [
            '01_identity_lock.txt', '02_timeline.txt', '03_four_elements.txt',
            '04_peripheral.txt', '05_chain_tracing.txt',
            '06_subjective.txt', '07_non_induced.txt'
        ]
        for sf in strategy_files:
            content = await self._load_prompt_file(f'strategies/{sf}')
            parts.append(content)
        
        # Part 3: 行业专属模块
        industry_file = f'industries/{industry_category}.txt'
        industry_module = await self._load_prompt_file(industry_file)
        if industry_subcategory:
            industry_module = industry_module.replace(
                '{{SUBCATEGORY_FOCUS}}',
                f'**本案件重点关注：{industry_subcategory}方向**'
            )
        parts.append(f"\n\n## 行业专属问询模块：{self._get_industry_label(industry_category)}\n")
        parts.append(industry_module)
        
        # Part 4: 案情类型适配
        case_type_file = f'case_types/{case_type}.txt'
        case_type_adapter = await self._load_prompt_file(case_type_file)
        parts.append(f"\n\n## 案情类型适配：{self._get_case_type_label(case_type)}\n")
        parts.append(case_type_adapter)
        
        # Part 5: 案件上下文
        parts.append(f"\n\n## 本案件信息\n")
        parts.append(context)
        
        return '\n'.join(parts)
    
    async def _load_prompt_file(self, relative_path: str) -> str:
        """加载Prompt文件"""
        file_path = self.prompts_dir / relative_path
        
        if not file_path.exists():
            # 返回占位内容，避免报错
            return f"[提示: Prompt文件 {relative_path} 暂未配置，请在后续完善]\n"
        
        return file_path.read_text(encoding='utf-8')
    
    async def _call_ai_model(self, prompt: str, db) -> dict:
        """调用AI模型生成策略"""
        start_time = time.time()
        
        try:
            # 尝试使用model_resolver
            try:
                from ..core.model_resolver import resolve_model_for_scene
                
                model_config = await resolve_model_for_scene('inquiry_strategy', db)
                
                import httpx
                async with httpx.AsyncClient(timeout=180.0) as client:
                    response = await client.post(
                        f"{model_config['api_base']}/chat/completions",
                        headers={
                            "Authorization": f"Bearer {model_config['api_key']}",
                            "Content-Type": "application/json"
                        },
                        json={
                            "model": model_config['model_name'],
                            "messages": [
                                {"role": "system", "content": "你是一位专业的执法询问策略专家。请根据提供的框架和案件信息，生成结构化的询问笔录策略提纲。"},
                                {"role": "user", "content": prompt}
                            ],
                            "temperature": 0.5,
                            "max_tokens": 8000,
                            "top_p": 0.9
                        }
                    )
                    
                    result = response.json()
                    generation_time = time.time() - start_time
                    
                    return {
                        'content': result['choices'][0]['message']['content'],
                        'model': model_config['model_name'],
                        'generation_time': round(generation_time, 2),
                        'token_usage': result.get('usage', {}),
                        'prompt': prompt[:500] + '...' if len(prompt) > 500 else prompt
                    }
            except Exception as e:
                print(f"[inquiry_strategy] AI调用失败，使用备用方案: {str(e)}")
                
                # 备用方案：返回模板化内容
                return self._generate_fallback_content(prompt, start_time)
                
        except Exception as e:
            raise HTTPException(status_code=500, detail=f"AI生成失败: {str(e)}")
    
    def _generate_fallback_content(self, prompt: str, start_time: float) -> dict:
        """当AI不可用时生成备用内容"""
        generation_time = time.time() - start_time
        
        fallback_content = """# 询问笔录策略提纲

> ⚠️ 注意：当前使用的是备用模板模式。如需获得更精准的策略建议，请确保AI模型服务正常运行。

---

## 第一部分：主体身份锁定【策略①】

**Q1: 请先确认您的姓名、身份证号码、联系电话及现住址？**

> **预期回答要点**：
> - 核对身份信息的准确性和一致性
> - 确认联系方式的有效性
>
> **取证目标**：固定违法主体的基本身份信息

**Q2: 您在涉案单位的具体职务是什么？担任该职务多长时间？**

> **预期回答要点**：
> - 明确职务名称和在组织架构中的位置
> - 了解任职时长和职责范围

---

## 第二部分：时间线闭环【策略②】

**Q3: 请按时间顺序描述相关行为的开始时间、过程细节和停止时间？**

> **预期回答要点**：
> - 完整的时间线梳理
> - 关键时间节点的具体行为

---

## 第三部分：法定四要件全覆盖【策略③】

**Q4: 您是否知晓相关法律法规的规定？**

> **预期回答要点**：
> - 法规知晓度判断
> - 区分故意违法还是过失不知情

---

*（后续部分需要AI模型支持才能完整生成）*
"""
        
        return {
            'content': fallback_content,
            'model': 'fallback_template',
            'generation_time': round(generation_time, 2),
            'token_usage': {'prompt': len(prompt), 'completion': len(fallback_content), 'total': len(prompt) + len(fallback_content)},
            'prompt': prompt[:500] + '...'
        }
    
    async def _save_new_strategy(self, case_id, user_id, config, context, result, generation_time, db):
        """保存新生成的策略到数据库"""
        conn, cur = db
        
        await cur.execute("""
            INSERT INTO inquiry_strategies (
                case_id, user_id, industry_category, industry_subcategory,
                case_type, is_auto_recommended, case_description,
                supplementary_content, attachment_ids, strategy_content,
                strategy_version, generation_prompt, ai_model_used,
                generation_time, token_usage, strategy_config, status
            ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, 'generated')
        """, (
            case_id, user_id,
            config['industry_category'], config.get('industry_subcategory'),
            config['case_type'], config.get('is_auto_recommended', 0),
            context.get('case_description', ''),
            context.get('supplementary_content', ''),
            json.dumps(config.get('attachment_ids', []), ensure_ascii=False),
            result['content'],
            1,
            result.get('prompt', ''),
            result.get('model', ''),
            generation_time,
            json.dumps(result.get('token_usage', {}), ensure_ascii=False),
            json.dumps(config.get('strategy_config', {}), ensure_ascii=False)
        ))
        
        strategy_id = cur.lastrowid
        await conn.commit()
        return strategy_id
    
    async def save_strategy(self, strategy_id: int, data: dict, db):
        """保存策略内容"""
        conn, cur = db
        
        await cur.execute("""
            UPDATE inquiry_strategies 
            SET strategy_content = %s, 
                status = 'edited',
                updated_at = NOW()
            WHERE id = %s
        """, (data['strategy_content'], strategy_id))
        
        await conn.commit()
        return {"success": True, "message": "保存成功"}
    
    async def export_strategy(self, strategy_id: int, format: str, db) -> str:
        """导出策略为Word或PDF"""
        conn, cur = db
        
        await cur.execute("SELECT * FROM inquiry_strategies WHERE id = %s", (strategy_id,))
        result = await cur.fetchone()
        
        if not result:
            raise FileNotFoundError("策略不存在")
        
        strategy = dict(result)
        
        output_path = tempfile.mktemp(suffix=f'.{format}')
        
        if format == 'word':
            await self._export_to_word(strategy, output_path)
        elif format == 'pdf':
            await self._export_to_pdf(strategy, output_path)
        
        return output_path
    
    async def _export_to_word(self, strategy: dict, output_path: str):
        """导出为Word文档"""
        from docx import Document
        from docx.shared import Inches, Pt
        
        doc = Document()
        
        # 设置页面边距
        for section in doc.sections:
            section.top_margin = Inches(1)
            section.bottom_margin = Inches(1)
            section.left_margin = Inches(1.25)
            section.right_margin = Inches(1.25)
        
        # 添加标题
        title = doc.add_heading('询问笔录策略提纲', 0)
        title.alignment = 1  # 居中
        
        # 添加元信息
        doc.add_paragraph(f"行业：{self._get_industry_label(strategy['industry_category'])}")
        doc.add_paragraph(f"案情类型：{self._get_case_type_label(strategy['case_type'])}")
        doc.add_paragraph(f"生成时间：{strategy['updated_at']}")
        doc.add_paragraph('─' * 50)
        
        # 解析HTML内容并添加到文档（简化版）
        content = strategy.get('strategy_content', '')
        
        # 简单的HTML标签清理和分段
        lines = content.replace('<br/>', '\n').replace('<br>', '\n').replace('</p>', '\n').split('\n')
        
        for line in lines:
            line = line.strip()
            if not line:
                continue
            
            # 清理HTML标签
            clean_line = ''
            in_tag = False
            for char in line:
                if char == '<':
                    in_tag = True
                elif char == '>':
                    in_tag = False
                elif not in_tag:
                    clean_line += char
            
            if clean_line.startswith('#'):
                level = 0
                for c in clean_line:
                    if c == '#':
                        level += 1
                    else:
                        break
                text = clean_line[level:].strip()
                if text:
                    doc.add_heading(text, level=min(level, 2))
            elif clean_line.startswith('>'):
                text = clean_line[1:].strip()
                if text:
                    p = doc.add_paragraph(text)
                    p.paragraph_format.left_indent = Inches(0.5)
            elif clean_line.startswith('**') and clean_line.endswith('**'):
                text = clean_line[2:-2]
                p = doc.add_paragraph()
                run = p.add_run(text)
                run.bold = True
            else:
                if clean_line:
                    doc.add_paragraph(clean_line)
        
        doc.save(output_path)
    
    async def _export_to_pdf(self, strategy: dict, output_path: str):
        """导出为PDF"""
        full_html = f"""
        <!DOCTYPE html>
        <html lang="zh-CN">
        <head>
            <meta charset="utf-8">
            <style>
                @page {{
                    size: A4;
                    margin: 2cm;
                    @bottom-center {{
                        content: "第 " counter(page) " 页";
                        font-size: 9pt;
                        color: #888;
                    }}
                }}
                body {{
                    font-family: SimSun, serif;
                    font-size: 11pt;
                    line-height: 1.8;
                }}
                h1 {{ text-align: center; font-size: 16pt; margin-bottom: 16pt; border-bottom: 2px solid #333; padding-bottom: 8pt; }}
                h2 {{ font-size: 13pt; margin-top: 18pt; color: #1a1a1a; border-bottom: 1px solid #666; padding-bottom: 4pt; }}
                strong {{ color: #0066cc; }}
                blockquote {{ background: #f5f5f5; border-left: 4px solid #0066cc; padding: 8pt 12pt; margin: 8pt 0; }}
                .meta-info {{ background: #e8f4fd; padding: 10pt; margin-bottom: 16pt; border-radius: 4pt; font-size: 10pt; }}
            </style>
        </head>
        <body>
            <div class="meta-info">
                <strong>行业：</strong>{self._get_industry_label(strategy['industry_category'])} | 
                <strong>案情：</strong>{self._get_case_type_label(strategy['case_type'])}<br/>
                <strong>生成时间：</strong>{strategy['updated_at']}
            </div>
            {strategy.get('strategy_content', '')}
        </body>
        </html>
        """
        
        try:
            from weasyprint import HTML
            HTML(string=full_html).write_pdf(output_path)
        except ImportError:
            # weasyprint未安装时，保存为HTML作为备选
            with open(output_path.replace('.pdf', '.html'), 'w', encoding='utf-8') as f:
                f.write(full_html)
            raise Exception("PDF导出功能需要安装weasyprint库")
    
    def _get_industry_label(self, value: str) -> str:
        labels = {
            'market_regulation': '市场监管',
            'agriculture': '农业农村',
            'culture_tourism': '文化旅游',
            'commerce': '商务',
            'other': '其他'
        }
        return labels.get(value, value)
    
    def _get_case_type_label(self, value: str) -> str:
        labels = {
            'minor': '轻微简易违法案',
            'general': '一般常规违法案',
            'intentional': '主观故意明知故犯案',
            'negligent': '过失不知情违法案',
            'multiple': '多人/企业团伙涉案案',
            'complex': '大额复杂链条案'
        }
        return labels.get(value, value)
