"""
CMA本体三支柱追溯链 API — 科目 ↔ KPI ↔ OKR的O 三层互联 (2026-08-19)

追溯链: 目标(O) → 指标(KPI) → 科目(数据)
  objective_kpi 表: O 由哪些 KPI 度量
  kpi_subject_map 表: KPI 由哪些科目计算
  krs 表: O 的关键结果 KR (OKR完整化)
"""
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy.orm import Session
from typing import Optional
from app.database import get_db
from app.deps import get_entity_id
from app.auth_middleware import require_role
from app.models import Objective, KPIDefinition, ObjectiveKPI, KPISubjectMap, KR, Subject

router = APIRouter(prefix="/api/cma/ontology", tags=["本体三支柱"],
    dependencies=[Depends(require_role("ceo", "finance", "it", "business"))],
)


def _num(v):
    """Decimal → float 便于 JSON 序列化"""
    return float(v) if v is not None else None


@router.get("/trace")
def trace_ontology(
    objective_id: int = Query(..., description="OKR目标ID, 从O→KPI→科目逐层追溯"),
    db: Session = Depends(get_db),
    entity_id: int = Depends(get_entity_id),
):
    """本体追溯链: O(目标) → KPI(指标) → 科目(数据) — 账套隔离 (2026-08-23 P2)"""
    obj = db.query(Objective).filter(Objective.id == objective_id, Objective.entity_id == entity_id).first()
    if not obj:
        raise HTTPException(404, "目标不存在")

    # 第2层: O 支撑的 KPI (objective_kpi)
    links = (
        db.query(ObjectiveKPI, KPIDefinition)
        .join(KPIDefinition, KPIDefinition.id == ObjectiveKPI.kpi_id)
        .filter(ObjectiveKPI.objective_id == objective_id)
        .order_by(ObjectiveKPI.id)
        .all()
    )

    # 第3层: 每个 KPI 依赖的科目 (kpi_subject_map)
    subject_by_code = {
        s.subject_code: s.subject_name
        for s in db.query(Subject).filter(Subject.is_active == 1).all()
    }
    kpi_layer = []
    for link, kpi in links:
        maps = (
            db.query(KPISubjectMap)
            .filter(KPISubjectMap.kpi_id == kpi.id)
            .order_by(KPISubjectMap.id)
            .all()
        )
        subjects = [
            {
                "subject_code": m.subject_code,
                "subject_name": subject_by_code.get(m.subject_code, ""),
                "calc_type": m.calc_type,
                "weight": _num(m.weight),
                "remark": m.remark,
            }
            for m in maps
        ]
        kpi_layer.append({
            "kpi_id": kpi.id,
            "kpi_code": kpi.kpi_code,
            "kpi_name": kpi.kpi_name,
            "dimension": kpi.dimension,
            "unit": kpi.unit,
            "weight": _num(link.weight),
            "formula": kpi.formula,
            "subjects": subjects,
        })

    # KR 层 (OKR完整化: O→KR)
    krs = db.query(KR).filter(KR.objective_id == objective_id).order_by(KR.id).all()
    kr_list = []
    for kr in krs:
        mkpi = db.query(KPIDefinition).filter(KPIDefinition.id == kr.metric_kpi_id).first() if kr.metric_kpi_id else None
        kr_list.append({
            "id": kr.id,
            "title": kr.title,
            "metric_kpi_id": kr.metric_kpi_id,
            "metric_kpi_code": mkpi.kpi_code if mkpi else None,
            "metric_kpi_name": mkpi.kpi_name if mkpi else None,
            "operator": kr.operator or ">=",
            "weight": _num(kr.weight),
            "target_value": _num(kr.target_value),
            "current_value": _num(kr.current_value),
            "progress": kr.progress,
            "status": kr.status,
            "due_date": kr.due_date.isoformat() if kr.due_date else None,
        })

    subject_total = sum(len(k["subjects"]) for k in kpi_layer)
    return {
        "objective": {
            "id": obj.id,
            "title": obj.title,
            "description": obj.description,
            "dimension": obj.dimension,
            "quarter": obj.quarter,
            "owner": obj.owner,
            "status": obj.status,
            "progress": obj.progress,
        },
        "krs": kr_list,
        "kpis": kpi_layer,
        "chain": {
            "objective_id": obj.id,
            "objective_title": obj.title,
            "kpi_count": len(kpi_layer),
            "subject_count": subject_total,
            "path": "O(目标) → KPI(指标) → 科目(数据)",
        },
    }


@router.get("/objectives")
def list_ontology_objectives(
    quarter: Optional[str] = Query(None, description="筛选季度: 2026Q3"),
    db: Session = Depends(get_db),
    entity_id: int = Depends(get_entity_id),
):
    """所有OKR目标的三层链路概览(前端OKR页用) — 账套隔离 (2026-08-23 P2)"""
    q = db.query(Objective).filter(Objective.entity_id == entity_id)
    if quarter:
        q = q.filter(Objective.quarter == quarter)
    objs = q.order_by(Objective.quarter.desc(), Objective.id).all()
    results = []
    for o in objs:
        kpi_links = (
            db.query(ObjectiveKPI, KPIDefinition)
            .join(KPIDefinition, KPIDefinition.id == ObjectiveKPI.kpi_id)
            .filter(ObjectiveKPI.objective_id == o.id)
            .all()
        )
        krs = db.query(KR).filter(KR.objective_id == o.id).all()
        results.append({
            "id": o.id,
            "title": o.title,
            "dimension": o.dimension,
            "quarter": o.quarter,
            "owner": o.owner,
            "status": o.status,
            "progress": o.progress,
            "kpi_count": len(kpi_links),
            "kr_count": len(krs),
            "kpis": [{"kpi_id": k.id, "kpi_code": k.kpi_code, "kpi_name": k.kpi_name,
                      "weight": _num(l.weight)} for l, k in kpi_links],
            "krs": [{"id": kr.id, "title": kr.title, "progress": kr.progress,
                     "status": kr.status,
                     "due_date": kr.due_date.isoformat() if kr.due_date else None}
                    for kr in krs],
        })
    return {"total": len(results), "items": results}
