from __future__ import annotations
from typing import Optional
from fastapi import APIRouter, Depends, Body
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession
from ...db import get_session
from ...auth_core import get_current_account, get_current_user
from ...services.routing_engine import LeadPayload, route_lead
from ...services.reporting_emitter import EventEmitter
from datetime import datetime
import uuid

router = APIRouter(prefix="/api/v2/routing", tags=["routing"])


class RouteRequest(BaseModel):
    lead_id: Optional[str] = None
    email: Optional[str] = None
    company: Optional[str] = None
    state: Optional[str] = None
    country: Optional[str] = None
    employees: Optional[int] = None
    website: Optional[str] = None
    tenant_id: Optional[str] = None


class RouteResponse(BaseModel):
    decision: str
    owner_id: Optional[str] = None
    pool_id: Optional[str] = None
    reason: Optional[str] = None
    rule_id: Optional[str] = None


@router.post("/route", response_model=RouteResponse)
async def route_endpoint(
    payload: RouteRequest = Body(...),
    db: AsyncSession = Depends(get_session),
    account_id: str = Depends(get_current_account),
    user_id: Optional[str] = Depends(get_current_user),
) -> RouteResponse:
    lead = LeadPayload(
        lead_id=payload.lead_id,
        email=payload.email,
        company=payload.company,
        state=payload.state,
        country=payload.country,
        employees=payload.employees,
        website=payload.website,
    )

    # Execute routing decision
    decision = route_lead(db, lead, tenant_id=payload.tenant_id)

    # Emit routing event to audit trail
    emitter = EventEmitter()
    event_id = str(uuid.uuid4())

    # Determine the routing outcome type
    if decision.get("decision") == "routed":
        op = "assign_owner"
        after_value = decision.get("owner_id")
        reason = (
            f"Routed to {decision.get('owner_id')} via {decision.get('reason', 'rule')}"
        )
    elif decision.get("decision") == "pooled":
        op = "assign_pool"
        after_value = decision.get("pool_id")
        reason = f"Added to pool {decision.get('pool_id')}"
    else:
        op = "routing_failed"
        after_value = None
        reason = decision.get("reason", "No matching rules")

    # Create routing event
    routing_event = {
        "id": event_id,
        "changeset_id": str(uuid.uuid4()),  # Each routing is its own changeset
        "sequence_num": 0,  # Will be set by emitter
        "applied_at": datetime.utcnow(),
        "op": op,
        "field": "owner"
        if op == "assign_owner"
        else "pool"
        if op == "assign_pool"
        else None,
        "before_value": None,  # Routing typically doesn't have a before value
        "after_value": after_value,
        "object_type": "lead",
        "object_id": payload.lead_id or f"temp_{payload.email}",
        "actor_type": "user" if user_id else "system",
        "actor_id": user_id or "routing_engine",
        "status": "applied",
        "confidence": 1.0 if decision.get("rule_id") else 0.5,
        "tier": "certain" if decision.get("rule_id") else "possible",
        "reason_text": reason,
        "reason_id": decision.get("rule_id"),
        "contains_pii": bool(payload.email),  # Email is PII
        "checksum": None,  # Will be set by emitter
        "partition_key": None,  # Will be set by emitter
    }

    # Emit the event asynchronously (don't block routing)
    try:
        await emitter.emit(db, str(account_id), routing_event)
    except Exception as e:
        # Log but don't fail routing if emission fails
        print(f"Failed to emit routing event: {e}")

    return RouteResponse(**decision)
