"""
Approval Rules Router — CRUD for approval workflow rules.

Endpoints:
- GET    /api/v1/approval-rules           — list rules
- POST   /api/v1/approval-rules           — create rule
- PUT    /api/v1/approval-rules/{id}      — update rule
- DELETE /api/v1/approval-rules/{id}      — delete rule
- POST   /api/v1/approval-rules/resolve   — resolve matching rule for tool context
"""

from fastapi import APIRouter, Depends, HTTPException, status, Request
from typing import List
import structlog
from sqlalchemy.orm import Session

from control_plane_api.app.database import get_db
from control_plane_api.app.middleware.auth import get_current_organization
from control_plane_api.app.services.approval_rule_service import ApprovalRuleService
from control_plane_api.app.schemas.approval_rule import (
    ApprovalRuleCreate,
    ApprovalRuleUpdate,
    ApprovalRuleResponse,
    ResolveApprovalRuleRequest,
    ResolveApprovalRuleResponse,
)

logger = structlog.get_logger()

router = APIRouter(tags=["Approval Rules"])


def get_rule_service(
    organization: dict = Depends(get_current_organization),
    db: Session = Depends(get_db),
) -> ApprovalRuleService:
    return ApprovalRuleService(organization_id=organization["id"], db=db)


def _rule_to_response(rule) -> ApprovalRuleResponse:
    return ApprovalRuleResponse(
        id=str(rule.id),
        organization_id=rule.organization_id,
        name=rule.name,
        description=rule.description,
        scope_type=rule.scope_type,
        scope_value=rule.scope_value,
        approver_type=rule.approver_type,
        approver_value=rule.approver_value,
        auto_approve_roles=rule.auto_approve_roles,
        require_reason=rule.require_reason,
        timeout_minutes=rule.timeout_minutes,
        enabled=rule.enabled,
        priority=rule.priority,
        created_at=rule.created_at.isoformat() if rule.created_at else None,
        updated_at=rule.updated_at.isoformat() if rule.updated_at else None,
    )


@router.get("", response_model=List[ApprovalRuleResponse])
def list_approval_rules(
    service: ApprovalRuleService = Depends(get_rule_service),
):
    """List all approval rules for the current organization."""
    rules = service.list_rules()
    return [_rule_to_response(r) for r in rules]


@router.post("", response_model=ApprovalRuleResponse, status_code=status.HTTP_201_CREATED)
def create_approval_rule(
    body: ApprovalRuleCreate,
    service: ApprovalRuleService = Depends(get_rule_service),
):
    """Create a new approval rule."""
    rule = service.create_rule(body.model_dump())
    return _rule_to_response(rule)


# NOTE: /resolve must be defined BEFORE /{rule_id} to prevent FastAPI from
# treating "resolve" as a UUID path parameter.
@router.post("/resolve", response_model=ResolveApprovalRuleResponse)
def resolve_approval_rule(
    body: ResolveApprovalRuleRequest,
    request: Request,
    service: ApprovalRuleService = Depends(get_rule_service),
    organization: dict = Depends(get_current_organization),
):
    """Given a tool context, return the matching rule and approver info.

    The user's groups are resolved from the authenticated session (Kubiya API),
    not passed in the request body. This ensures auto_approve_roles checks
    are based on the actual Kubiya group membership.
    """
    # User group names resolved from Kubiya API's user_groups objects
    # e.g. ["Admin", "Users", "DevOps"] — used for auto_approve_roles matching
    user_group_names = organization.get("user_group_names") or []

    result = service.resolve_rule(
        tool_name=body.tool_name,
        risk_level=body.risk_level,
        category=body.category,
        user_groups=user_group_names,
    )

    rule = result["rule"]
    rule_response = _rule_to_response(rule) if rule else None
    return ResolveApprovalRuleResponse(
        rule_id=str(rule.id) if rule else None,
        rule_name=rule.name if rule else None,
        rule=rule_response,
        approver_emails=result["approver_emails"],
        auto_approved=result["auto_approved"],
        require_reason=rule.require_reason if rule else False,
        timeout_minutes=rule.timeout_minutes if rule else 1440,
        message=result["message"],
    )


@router.put("/{rule_id}", response_model=ApprovalRuleResponse)
def update_approval_rule(
    rule_id: str,
    body: ApprovalRuleUpdate,
    service: ApprovalRuleService = Depends(get_rule_service),
):
    """Update an existing approval rule."""
    data = body.model_dump(exclude_unset=True)
    rule = service.update_rule(rule_id, data)
    if not rule:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Approval rule not found")
    return _rule_to_response(rule)


@router.delete("/{rule_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_approval_rule(
    rule_id: str,
    service: ApprovalRuleService = Depends(get_rule_service),
):
    """Delete an approval rule."""
    if not service.delete_rule(rule_id):
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Approval rule not found")
