"""
CMA管理报表中心 — 管理会计OS
非传统财务报表，聚焦管理决策分析

报表:
  1. 管理利润表 — 收入→变动成本→边际贡献→固定成本→息税前利润
  2. 预算执行报告 — 各KPI预算vs实际vs差异率
  3. KPI趋势报告 — 选定KPI的历史趋势
  4. 四维度绩效评分卡 — BSC健康度雷达图
"""
from fastapi import APIRouter, Depends, Query, HTTPException
from sqlalchemy.orm import Session
from sqlalchemy import func
from typing import Optional
from datetime import datetime, date
from app.database import get_db
from app.auth_middleware import require_role, require_auth
from app.models import KPIDefinition, KPIValue, BudgetPlan, StrategicMap, KPIAlert, User
from app.utils.deviation_engine import calc_period_deviation, calc_period_diff
import logging

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

router = APIRouter(prefix="/api/cma/reports", tags=["管理报表"],
    dependencies=[Depends(require_role("ceo", "finance", "business"))],
)


# ============================================================
# 报表1: 管理利润表
# ============================================================

@router.get("/profit-summary")
def get_profit_summary(
    period: str = Query(None, description="格式 YYYY-MM"),
    db: Session = Depends(get_db),
):
    """管理利润表 — 收入→变动成本→边际贡献→固定成本→息税前利润"""
    if period is None:
        period = datetime.now().strftime("%Y-%m")

    # 从KPI数据中获取各利润要素
    def get_val(code: str):
        kpi = db.query(KPIDefinition).filter(KPIDefinition.kpi_code == code).first()
        if not kpi:
            return None
        v = db.query(KPIValue).filter(
            KPIValue.kpi_id == kpi.id, KPIValue.period == period
        ).order_by(KPIValue.id.desc()).first()
        return v.actual_value if v else None

    revenue = get_val("F_REVENUE")
    gross_profit_rate = get_val("F_PROFIT_RATE")
    net_profit_rate = get_val("F_NET_PROFIT_RATE")
    cost_ratio = get_val("F_COST_RATIO")

    # 计算利润要素
    # 营收已知，用毛利率算毛利，用成本率算成本
    gross_profit = round(revenue * (gross_profit_rate / 100), 2) if revenue and gross_profit_rate else None
    total_cost = round(revenue * (cost_ratio / 100), 2) if revenue and cost_ratio else None
    net_profit = round(revenue * (net_profit_rate / 100), 2) if revenue and net_profit_rate else None

    # 边际贡献 ≈ 毛利（简化模型）
    contribution_margin = gross_profit
    # 固定成本 ≈ 总成本 - 变动成本（假设变动成本=营收*50%）
    variable_cost = round(revenue * 0.50, 2) if revenue else None
    fixed_cost = round(total_cost - variable_cost, 2) if total_cost and variable_cost else None

    # 找上期做环比
    prev_year, prev_month = period.split("-")
    py, pm = int(prev_year), int(prev_month)
    pm -= 1
    if pm <= 0:
        pm += 12
        py -= 1
    prev_period = f"{py}-{pm:02d}"

    def get_prev_val(code: str):
        kpi = db.query(KPIDefinition).filter(KPIDefinition.kpi_code == code).first()
        if not kpi: return None
        v = db.query(KPIValue).filter(
            KPIValue.kpi_id == kpi.id, KPIValue.period == prev_period
        ).order_by(KPIValue.id.desc()).first()
        return v.actual_value if v else None

    prev_revenue = get_prev_val("F_REVENUE")
    prev_gross_profit_rate = get_prev_val("F_PROFIT_RATE")
    prev_net_profit_rate = get_prev_val("F_NET_PROFIT_RATE")
    prev_cost_ratio = get_prev_val("F_COST_RATIO")
    prev_gross_profit = round(prev_revenue * (prev_gross_profit_rate / 100), 2) if prev_revenue and prev_gross_profit_rate else None
    prev_total_cost = round(prev_revenue * (prev_cost_ratio / 100), 2) if prev_revenue and prev_cost_ratio else None
    prev_net_profit = round(prev_revenue * (prev_net_profit_rate / 100), 2) if prev_revenue and prev_net_profit_rate else None
    prev_contribution_margin = prev_gross_profit
    prev_variable_cost = round(prev_revenue * 0.50, 2) if prev_revenue else None
    prev_fixed_cost = round(prev_total_cost - prev_variable_cost, 2) if prev_total_cost and prev_variable_cost else None

    def calc_chg(cur, prev):
        if cur is not None and prev is not None and prev != 0:
            return round((cur - prev) / prev * 100, 2)
        return None

    items = [
        {
            "name": "营业收入",
            "value": revenue,
            "prev_value": prev_revenue,
            "change_rate": calc_chg(revenue, prev_revenue),
            "ratio": 100.0,
        },
        {
            "name": "减：变动成本",
            "value": variable_cost,
            "prev_value": prev_variable_cost,
            "change_rate": calc_chg(variable_cost, prev_variable_cost),
            "ratio": round(variable_cost / revenue * 100, 2) if variable_cost and revenue else None,
        },
        {
            "name": "＝ 边际贡献",
            "value": contribution_margin,
            "prev_value": prev_contribution_margin,
            "change_rate": calc_chg(contribution_margin, prev_contribution_margin),
            "ratio": round(contribution_margin / revenue * 100, 2) if contribution_margin and revenue else None,
            "is_subtotal": True,
        },
        {
            "name": "减：固定成本",
            "value": fixed_cost,
            "prev_value": prev_fixed_cost,
            "change_rate": calc_chg(fixed_cost, prev_fixed_cost),
            "ratio": round(fixed_cost / revenue * 100, 2) if fixed_cost and revenue else None,
        },
        {
            "name": "＝ 息税前利润",
            "value": net_profit,
            "prev_value": prev_net_profit,
            "change_rate": calc_chg(net_profit, prev_net_profit),
            "ratio": round(net_profit / revenue * 100, 2) if net_profit and revenue else None,
            "is_total": True,
        },
    ]

    return {
        "period": period,
        "prev_period": prev_period,
        "items": items,
    }


# ============================================================
# 报表2: 预算执行报告
# ============================================================

@router.get("/budget-execution")
def get_budget_execution(
    period: str = Query(None, description="格式 YYYY-MM"),
    dimension: Optional[str] = Query(None),
    alert_level: Optional[str] = Query(None),
    db: Session = Depends(get_db),
):
    """预算执行报告 — 各KPI预算vs实际vs差异率"""
    if period is None:
        period = datetime.now().strftime("%Y-%m")

    query = db.query(KPIDefinition).filter(KPIDefinition.status == "active")
    if dimension:
        query = query.filter(KPIDefinition.dimension == dimension)
    kpis = query.order_by(KPIDefinition.dimension, KPIDefinition.kpi_code).all()

    items = []
    summary = {"total": 0, "with_budget": 0, "over_budget": 0, "normal": 0, "under_budget": 0}

    for kpi in kpis:
        dev = calc_period_deviation(db, kpi.id, period)
        if dev.get("actual_value") is None and dev.get("budget_value") is None:
            continue  # 跳过完全无数据的KPI
        summary["total"] += 1
        if dev.get("deviation_rate") is not None:
            rate = dev["deviation_rate"]
            level = "red" if abs(rate) > 20 else "yellow" if abs(rate) > 10 else "normal"
            if level == "red":
                summary["over_budget"] += 1 if rate > 0 else 0
                summary["under_budget"] += 1 if rate < 0 else 0
            else:
                summary["normal"] += 1
        else:
            level = "gray"
            summary["normal"] += 1

        if dev.get("budget_value") is not None:
            summary["with_budget"] += 1

        items.append({
            "kpi_id": kpi.id,
            "kpi_code": kpi.kpi_code,
            "kpi_name": kpi.kpi_name,
            "dimension": kpi.dimension,
            "unit": kpi.unit,
            "actual_value": dev.get("actual_value"),
            "budget_value": dev.get("budget_value"),
            "deviation_amount": dev.get("deviation_amount"),
            "deviation_rate": dev.get("deviation_rate"),
            "is_over_budget": dev.get("is_over_budget"),
            "alert_level": level,
        })

    # alert_level 过滤
    if alert_level:
        items = [i for i in items if i["alert_level"] == alert_level]

    return {"period": period, "summary": summary, "items": items}


# ============================================================
# 报表3: KPI趋势报告
# ============================================================

@router.get("/kpi-trends")
def get_kpi_trends(
    kpi_id: Optional[int] = Query(None),
    dimension: Optional[str] = Query(None),
    months: int = Query(12, ge=3, le=36),
    db: Session = Depends(get_db),
):
    """KPI趋势报告 — 选定KPI的历史趋势线"""
    query = db.query(KPIDefinition).filter(KPIDefinition.status == "active")
    if kpi_id:
        query = query.filter(KPIDefinition.id == kpi_id)
    if dimension:
        query = query.filter(KPIDefinition.dimension == dimension)
    kpis = query.order_by(KPIDefinition.dimension, KPIDefinition.kpi_code).all()

    results = []
    for kpi in kpis:
        values = db.query(KPIValue).filter(
            KPIValue.kpi_id == kpi.id
        ).order_by(KPIValue.period.desc()).limit(months).all()
        values.reverse()

        trend = [{"period": v.period, "value": v.actual_value} for v in values]
        vals = [v.actual_value for v in values if v.actual_value is not None]

        target = kpi.target_value
        avg_val = round(sum(vals) / len(vals), 2) if vals else None
        max_val = max(vals) if vals else None
        min_val = min(vals) if vals else None

        # 趋势方向
        if len(vals) >= 2:
            first_half = sum(vals[:len(vals)//2]) / (len(vals)//2)
            second_half = sum(vals[len(vals)//2:]) / (len(vals) - len(vals)//2)
            trend_dir = "up" if second_half > first_half * 1.05 else "down" if second_half < first_half * 0.95 else "stable"
        else:
            trend_dir = "stable"

        results.append({
            "kpi_id": kpi.id,
            "kpi_code": kpi.kpi_code,
            "kpi_name": kpi.kpi_name,
            "dimension": kpi.dimension,
            "unit": kpi.unit,
            "target_value": target,
            "trend": trend,
            "trend_dir": trend_dir,
            "avg": avg_val,
            "max": max_val,
            "min": min_val,
        })

    return {"data": results}


# ============================================================
# 报表4: 四维度绩效评分卡
# ============================================================

DIM_CONFIG = {
    "finance": {"name": "财务维度", "icon": "💰", "color": "#409eff"},
    "customer": {"name": "客户维度", "icon": "🤝", "color": "#67c23a"},
    "process": {"name": "内部流程", "icon": "⚙️", "color": "#e6a23c"},
    "learning": {"name": "学习成长", "icon": "📚", "color": "#f56c6c"},
}


@router.get("/bsc-scorecard")
def get_bsc_scorecard(
    map_id: Optional[int] = Query(None),
    period: Optional[str] = Query(None),
    db: Session = Depends(get_db),
):
    """四维度绩效评分卡 — BSC健康度"""
    if period is None:
        period = datetime.now().strftime("%Y-%m")

    # 取最新的已发布地图
    map_query = db.query(StrategicMap).filter(StrategicMap.status == "published")
    if map_id:
        map_query = map_query.filter(StrategicMap.id == map_id)
    sm = map_query.order_by(StrategicMap.updated_at.desc()).first()

    if not sm:
        # 没有已发布地图，按维度聚合KPI
        return _build_scorecard_from_kpis(db, period)

    # 从战略地图维度数据构建评分卡
    dims = sm.dimensions
    if isinstance(dims, str):
        import json
        dims = json.loads(dims)

    dimensions = []
    total_score = 0
    dim_count = 0

    for dim in dims:
        dim_key = dim.get("key", "")
        config = DIM_CONFIG.get(dim_key, {"name": dim.get("name", dim_key), "icon": "📊", "color": "#999"})
        objectives = dim.get("objectives", [])

        obj_results = []
        dim_total = 0
        dim_valid = 0
        for obj in objectives:
            kpi_codes = obj.get("kpis", [])
            kpi_scores = []
            for code in kpi_codes:
                kpi = db.query(KPIDefinition).filter(KPIDefinition.kpi_code == code).first()
                if not kpi: continue
                v = db.query(KPIValue).filter(
                    KPIValue.kpi_id == kpi.id, KPIValue.period == period
                ).order_by(KPIValue.id.desc()).first()
                if v and v.actual_value and kpi.target_value:
                    ratio = v.actual_value / kpi.target_value
                    score = min(round(ratio * 100, 1), 100)
                    level = "green" if ratio >= 0.9 else "yellow" if ratio >= 0.7 else "red"
                    kpi_scores.append({"code": code, "name": kpi.kpi_name, "actual": v.actual_value, "target": kpi.target_value, "score": score, "level": level})
                    dim_total += score
                    dim_valid += 1

            obj_results.append({
                "name": obj.get("name", ""),
                "kpi_count": len(kpi_codes),
                "kpi_with_data": dim_valid,
                "kpis": kpi_scores,
            })

        dim_score = round(dim_total / dim_valid, 1) if dim_valid > 0 else 0
        dimensions.append({
            "key": dim_key,
            "name": config["name"],
            "icon": config["icon"],
            "color": config["color"],
            "score": dim_score,
            "objectives": obj_results,
        })
        total_score += dim_score
        dim_count += 1

    overall = round(total_score / dim_count, 1) if dim_count > 0 else 0

    return {
        "period": period,
        "map_id": sm.id,
        "map_title": sm.title,
        "overall_score": overall,
        "dimensions": dimensions,
    }


def _build_scorecard_from_kpis(db: Session, period: str) -> dict:
    """没有战略地图时，直接按维度聚合KPI算分"""
    kpis = db.query(KPIDefinition).filter(KPIDefinition.status == "active").all()
    dims: dict = {}

    for kpi in kpis:
        dim = kpi.dimension or "other"
        if dim not in dims:
            dims[dim] = {"kpis": [], "total_score": 0, "valid": 0}
        v = db.query(KPIValue).filter(
            KPIValue.kpi_id == kpi.id, KPIValue.period == period
        ).order_by(KPIValue.id.desc()).first()
        score = None
        level = "gray"
        if v and v.actual_value and kpi.target_value:
            ratio = v.actual_value / kpi.target_value
            score = min(round(ratio * 100, 1), 100)
            level = "green" if ratio >= 0.9 else "yellow" if ratio >= 0.7 else "red"
            dims[dim]["total_score"] += score
            dims[dim]["valid"] += 1

        dims[dim]["kpis"].append({
            "code": kpi.kpi_code,
            "name": kpi.kpi_name,
            "actual": v.actual_value if v else None,
            "target": kpi.target_value,
            "score": score,
            "level": level,
        })

    dimensions = []
    total_score = 0
    dim_count = 0
    for key, data in dims.items():
        config = DIM_CONFIG.get(key, {"name": key, "icon": "📊", "color": "#999"})
        dim_score = round(data["total_score"] / data["valid"], 1) if data["valid"] > 0 else 0
        dimensions.append({
            "key": key,
            "name": config["name"],
            "icon": config["icon"],
            "color": config["color"],
            "score": dim_score,
            "objectives": [{"name": "全部KPI", "kpis": data["kpis"], "kpi_count": len(data["kpis"]), "kpi_with_data": data["valid"]}],
        })
        total_score += dim_score
        dim_count += 1

    return {
        "period": period,
        "map_id": None,
        "map_title": None,
        "overall_score": round(total_score / dim_count, 1) if dim_count > 0 else 0,
        "dimensions": dimensions,
    }


# ============================================================
# 杜邦分析 (CMA P2)
# ============================================================

@router.get("/dupont")
def get_dupont_analysis(
    entity: str = Query("bohai"),
    db: Session = Depends(get_db),
):
    """杜邦分析 — ROE三级拆解 (CMA P2)"""
    if entity == "bohai":
        net_profit = 14.1  # 万
        revenue = 383  # 万
        total_assets = 533  # 万
        equity = 114  # 万

        net_profit_margin = round(net_profit / revenue * 100, 2)
        asset_turnover = round(revenue / total_assets, 4)
        financial_leverage = round(total_assets / equity, 2)
        roe = round(net_profit_margin / 100 * asset_turnover * financial_leverage * 100, 2)

        # 上期对比（模拟上一期数据）
        prev_roe = round(11.2, 2)
        roe_change = round(roe - prev_roe, 2)

        return {
            "entity": "bohai",
            "entity_name": "陕西博海科技（IT服务）",
            "period": "2026年H1",
            "roe": roe,
            "roe_change": roe_change,
            "roe_trend": "up" if roe_change > 0 else "down",
            "prev_roe": prev_roe,
            "factors": {
                "net_profit_margin": {
                    "value": net_profit_margin,
                    "label": "净利润率",
                    "desc": "净利润/收入",
                    "status": "🟡" if net_profit_margin < 5 else "✅",
                    "assessment": "IT经销行业正常偏低",
                    "raw": {"net_profit": net_profit, "revenue": revenue},
                },
                "asset_turnover": {
                    "value": asset_turnover,
                    "label": "资产周转率",
                    "desc": "收入/总资产",
                    "status": "🟡" if asset_turnover < 1 else "✅",
                    "assessment": "资金效率中等",
                    "raw": {"revenue": revenue, "total_assets": total_assets},
                },
                "financial_leverage": {
                    "value": financial_leverage,
                    "label": "财务杠杆",
                    "desc": "总资产/净资产",
                    "status": "🟡" if financial_leverage > 3 else "✅",
                    "assessment": "负债率78.6%，偏高但可控",
                    "raw": {"total_assets": total_assets, "equity": equity},
                },
            },
            "raw_data": {
                "net_profit": net_profit,
                "revenue": revenue,
                "total_assets": total_assets,
                "equity": equity,
            },
            "insight": {
                "improvement": "提高周转率或利润率，而非加杠杆",
                "detail": f"净利润率{net_profit_margin}%偏低，资产周转率{asset_turnover}x中等，财务杠杆{financial_leverage}x偏高。改善方向：提升毛利率或加快库存周转。",
            },
        }
    return {"error": "不支持的实体"}
