"""
定时AI经营简报 — 管理会计OS
每天凌晨自动生成经营分析报告，推送至企微
在 daily_sync.py 之后运行
"""
import sys
import os
import json
import logging
from datetime import datetime

sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from dotenv import load_dotenv
load_dotenv('/root/cma-management/backend/.env')

from app.database import get_session_local
from app.models import KPIDefinition, KPIValue, KPIAlert, ActionPlan
import httpx

logger = logging.getLogger("cma.ai_brief")


async def call_deepseek(prompt: str, system_prompt: str = None) -> str:
    """调用DeepSeek API生成分析内容"""
    api_key = os.getenv("DEEPSEEK_API_KEY", "")
    api_url = "https://api.deepseek.com/v1/chat/completions"
    
    if not system_prompt:
        system_prompt = "你是一名CMA管理会计师，擅长用数据驱动的方式分析企业经营状况，给出专业的财务分析和管理建议。回答要简洁、专业、有数据支撑。"
    
    if not api_key:
        logger.warning("DEEPSEEK_API_KEY 未配置，跳过AI调用")
        return "（AI简报暂不可用：API Key未配置）"
    
    async with httpx.AsyncClient(timeout=60) as client:
        resp = await client.post(
            api_url,
            headers={"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"},
            json={
                "model": "deepseek-chat",
                "messages": [
                    {"role": "system", "content": system_prompt},
                    {"role": "user", "content": prompt}
                ],
                "stream": False,
                "temperature": 0.3,
            }
        )
        data = resp.json()
        if resp.status_code != 200:
            logger.error(f"DeepSeek API错误: {resp.status_code} {data}")
            return ""
        return data.get("choices", [{}])[0].get("message", {}).get("content", "")


def generate_brief(db_session) -> dict:
    """生成经营简报"""
    period = datetime.now().strftime("%Y-%m")
    
    kpis = db_session.query(KPIDefinition).filter(KPIDefinition.status == "active").all()
    kpi_lines = []
    for k in kpis:
        latest = db_session.query(KPIValue).filter(
            KPIValue.kpi_id == k.id,
        ).order_by(KPIValue.period.desc()).first()
        
        prev_month = f"{int(period[:4])}-{int(period[5:7])-1:02d}" if int(period[5:7]) > 1 else f"{int(period[:4])-1}-12"
        prev = db_session.query(KPIValue).filter(
            KPIValue.kpi_id == k.id, KPIValue.period == prev_month
        ).first()
        
        alert = db_session.query(KPIAlert).filter(
            KPIAlert.kpi_id == k.id, KPIAlert.status == "pending"
        ).first()
        
        if latest and latest.actual_value is not None:
            line = f"- {k.kpi_name}({k.kpi_code}): {latest.actual_value}{k.unit or ''}"
            if k.target_value:
                line += f" | 目标: {k.target_value}"
            if prev and prev.actual_value:
                diff = latest.actual_value - prev.actual_value
                direction = "↑" if diff > 0 else "↓"
                line += f" | 环比: {direction}{abs(diff):.1f}"
            if alert:
                line += f" | ⚠️ {alert.alert_level}预警"
            kpi_lines.append(line)
    
    plans = db_session.query(ActionPlan).order_by(ActionPlan.created_at.desc()).all()
    plan_lines = []
    for p in plans:
        plan_lines.append(f"- {p.title} | 负责人: {p.assignee} | 状态: {p.status} | 进度: {p.progress}%")
    
    kpi_text = "\n".join(kpi_lines) if kpi_lines else "暂无KPI数据"
    plan_text = "\n".join(plan_lines) if plan_lines else "暂无行动计划"
    
    red_count = db_session.query(KPIAlert).filter(
        KPIAlert.status == "pending", KPIAlert.alert_level == "red"
    ).count()
    yellow_count = db_session.query(KPIAlert).filter(
        KPIAlert.status == "pending", KPIAlert.alert_level == "yellow"
    ).count()
    
    today_str = datetime.now().strftime('%Y-%m-%d')
    prompt = f"""请为管理层生成一份今日经营简报（日期：{today_str}）。

## 本月KPI数据
{kpi_text}

## 待处理预警
- 红色(紧急): {red_count}条
- 黄色(预警): {yellow_count}条

## 正在执行的改善行动
{plan_text}

请按以下结构生成简报（不超过800字）：
1. 📊 **经营概览**：一句话总结本月经营状况
2. 🔍 **关键发现**：最重要的3个发现（数据驱动）
3. ⚠️ **预警聚焦**：最需要关注的预警及其影响
4. ✅ **行动进展**：改善计划执行情况
5. 💡 **今日建议**：今天最应该做的1-2件事"""
    
    try:
        import asyncio
        analysis = asyncio.run(call_deepseek(prompt))
    except Exception as e:
        logger.error(f"AI简报生成异常: {e}")
        analysis = f"简报生成异常: {str(e)}"
    
    return {
        "period": period,
        "brief": analysis,
        "kpi_count": len(kpi_lines),
        "red_alerts": red_count,
        "yellow_alerts": yellow_count,
        "plan_count": len(plan_lines),
    }


def push_brief(brief: dict):
    """将简报推送到企微"""
    from app.utils.notifier import send_wecom_app
    
    db = get_session_local()()
    try:
        from app.models import NotificationChannel
        channels = db.query(NotificationChannel).filter(
            NotificationChannel.enabled == True,
            NotificationChannel.channel_type == "wecom_app",
        ).all()
        
        pushed = 0
        for ch in channels:
            config = ch.config or {}
            result = send_wecom_app(
                corp_id=config.get("corp_id", ""),
                corp_secret=config.get("corp_secret", ""),
                agent_id=config.get("agent_id", ""),
                touser=config.get("touser", "@all"),
                title=f"📋 {brief['period']} 经营简报",
                content=brief["brief"],
                alert_level="green",
            )
            if result.get("success"):
                pushed += 1
                logger.info(f"简报推送成功: {ch.name}")
            else:
                logger.warning(f"简报推送失败: {result.get('message')}")
        
        return pushed
    finally:
        db.close()


def run_brief():
    """主入口：生成简报并推送"""
    logger.info("开始生成AI经营简报...")
    db = get_session_local()()
    try:
        brief = generate_brief(db)
        logger.info(f"简报生成完成: {brief['period']}, KPI数={brief['kpi_count']}, 预警={brief['red_alerts']}红/{brief['yellow_alerts']}黄")
        
        if brief["brief"] and len(brief["brief"]) > 50:
            pushed = push_brief(brief)
            logger.info(f"推送完成: {pushed} 个渠道")
        else:
            logger.warning("简报内容不足50字，跳过推送")
        
        return brief
    finally:
        db.close()


if __name__ == "__main__":
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
    )
    result = run_brief()
    print(json.dumps(result, ensure_ascii=False, indent=2))
