from fastapi import APIRouter, Depends from sqlalchemy import func from sqlalchemy.orm import Session from ..auth import verify_token from ..database import get_db from ..models import NodeType, RequirementNode from ..schemas import StatsResponse router = APIRouter(prefix="/api/stats", tags=["stats"], dependencies=[Depends(verify_token)]) @router.get("", response_model=StatsResponse) def get_stats(project_id: int | None = None, db: Session = Depends(get_db)): query = db.query(RequirementNode) if project_id is not None: query = query.filter(RequirementNode.project_id == project_id) nodes = query.all() total = len(nodes) by_type = {} by_status: dict[str, int] = {} by_priority: dict[str, int] = {} quality_passing = 0 leaves_with_tests = 0 total_leaves = 0 for n in nodes: by_type[n.node_type.value] = by_type.get(n.node_type.value, 0) + 1 by_status[n.status.value] = by_status.get(n.status.value, 0) + 1 by_priority[n.priority.value] = by_priority.get(n.priority.value, 0) + 1 if n.traceable and n.measurable and n.consistent and n.single_purpose: quality_passing += 1 if n.node_type == NodeType.leaf: total_leaves += 1 if n.test_spec: leaves_with_tests += 1 coverage = (leaves_with_tests / total_leaves * 100) if total_leaves > 0 else 0.0 return StatsResponse( total_nodes=total, pillars=by_type.get("pillar", 0), requirements=by_type.get("requirement", 0), sub_requirements=by_type.get("sub_requirement", 0), leaves=by_type.get("leaf", 0), by_status=by_status, by_priority=by_priority, quality_passing=quality_passing, quality_failing=total - quality_passing, coverage_percent=round(coverage, 1), )