from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Dict, List, Literal, Optional


WebhookEvent = Literal[
    "intent_shift",
    "policy_blocked",
    "approval_requested",
    "compliance_drop",
]


@dataclass
class ExecutionStep:
    stepNumber: int
    type: str
    toolName: Optional[str] = None
    toolArgs: Optional[Dict[str, Any]] = None
    toolResult: Optional[Dict[str, Any]] = None
    latencyMs: Optional[int] = None


@dataclass
class ExecutionTrace:
    id: str
    orgId: str
    agentId: str
    status: str
    stepCount: int
    toolCalls: List[Dict[str, Any]] = field(default_factory=list)
    startedAt: str = ""
    sessionId: Optional[str] = None
    completedAt: Optional[str] = None
    durationMs: Optional[int] = None

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "ExecutionTrace":
        return cls(
            id=data.get("id", ""),
            orgId=data.get("orgId", ""),
            agentId=data.get("agentId", ""),
            status=data.get("status", "open"),
            stepCount=data.get("stepCount", 0),
            toolCalls=data.get("toolCalls", []),
            startedAt=data.get("startedAt", ""),
            sessionId=data.get("sessionId"),
            completedAt=data.get("completedAt"),
            durationMs=data.get("durationMs"),
        )


@dataclass
class IntentTrace:
    id: str
    orgId: str
    agentId: str
    declaredIntent: str
    status: str
    createdAt: str = ""
    executionTraceId: Optional[str] = None
    resolvedIntent: Optional[str] = None
    fidelityScore: Optional[float] = None
    closedAt: Optional[str] = None

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "IntentTrace":
        return cls(
            id=data.get("id", ""),
            orgId=data.get("orgId", ""),
            agentId=data.get("agentId", ""),
            declaredIntent=data.get("declaredIntent", ""),
            status=data.get("status", "open"),
            createdAt=data.get("createdAt", ""),
            executionTraceId=data.get("executionTraceId"),
            resolvedIntent=data.get("resolvedIntent"),
            fidelityScore=data.get("fidelityScore"),
            closedAt=data.get("closedAt"),
        )


@dataclass
class IntentShift:
    id: str
    intentTraceId: str
    observedIntent: str
    severity: str
    timestamp: str = ""
    shiftReason: Optional[str] = None
    decision: Optional[str] = None
    evaluationId: Optional[str] = None
    approvalRequestId: Optional[str] = None

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "IntentShift":
        return cls(
            id=data.get("id", ""),
            intentTraceId=data.get("intentTraceId", ""),
            observedIntent=data.get("observedIntent", ""),
            severity=data.get("severity", "medium"),
            timestamp=data.get("timestamp", ""),
            shiftReason=data.get("shiftReason"),
            decision=data.get("decision"),
            evaluationId=data.get("evaluationId"),
            approvalRequestId=data.get("approvalRequestId"),
        )


@dataclass
class IntentCloseResult:
    fidelityScore: float
    shifts: int
    status: str

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "IntentCloseResult":
        return cls(
            fidelityScore=data.get("fidelityScore", 0.0),
            shifts=data.get("shifts", 0),
            status=data.get("status", "closed"),
        )


@dataclass
class EvaluationResult:
    decision: str
    evaluationId: str
    reason: Optional[str] = None
    approvalRequestId: Optional[str] = None

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "EvaluationResult":
        return cls(
            decision=data.get("decision", "allow"),
            evaluationId=data.get("evaluationId", ""),
            reason=data.get("reason"),
            approvalRequestId=data.get("approvalRequestId"),
        )


@dataclass
class ApprovalRequest:
    id: str
    orgId: str
    policyEvaluationId: str
    agentId: str
    actionType: str
    actionPayload: Dict[str, Any]
    status: str
    requestedAt: str
    resolvedAt: Optional[str] = None
    resolvedBy: Optional[str] = None

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "ApprovalRequest":
        return cls(
            id=data.get("id", ""),
            orgId=data.get("orgId", ""),
            policyEvaluationId=data.get("policyEvaluationId", ""),
            agentId=data.get("agentId", ""),
            actionType=data.get("actionType", ""),
            actionPayload=data.get("actionPayload", {}),
            status=data.get("status", "pending"),
            requestedAt=data.get("requestedAt", ""),
            resolvedAt=data.get("resolvedAt"),
            resolvedBy=data.get("resolvedBy"),
        )


@dataclass
class WebhookEndpoint:
    id: str
    orgId: str
    url: str
    secret: str
    events: List[WebhookEvent]
    status: str
    format: str
    createdAt: str
    deliveryCount: Optional[int] = None

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "WebhookEndpoint":
        return cls(
            id=data.get("id", ""),
            orgId=data.get("orgId", ""),
            url=data.get("url", ""),
            secret=data.get("secret", ""),
            events=data.get("events", []),
            status=data.get("status", "active"),
            format=data.get("format", "json"),
            createdAt=data.get("createdAt", ""),
            deliveryCount=data.get("deliveryCount"),
        )


@dataclass
class WebhookDelivery:
    id: str
    webhookId: str
    orgId: str
    status: str
    statusCode: int
    durationMs: int
    createdAt: str
    responseBody: Optional[str] = None
    error: Optional[str] = None

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "WebhookDelivery":
        return cls(
            id=data.get("id", ""),
            webhookId=data.get("webhookId", ""),
            orgId=data.get("orgId", ""),
            status=data.get("status", "failed"),
            statusCode=data.get("statusCode", 0),
            durationMs=data.get("durationMs", 0),
            createdAt=data.get("createdAt", ""),
            responseBody=data.get("responseBody"),
            error=data.get("error"),
        )


@dataclass
class OrgMember:
    id: str
    orgId: str
    email: str
    name: str
    role: str
    inviteStatus: str
    createdAt: str

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "OrgMember":
        return cls(
            id=data.get("id", ""),
            orgId=data.get("orgId", ""),
            email=data.get("email", ""),
            name=data.get("name", ""),
            role=data.get("role", "developer"),
            inviteStatus=data.get("inviteStatus", "active"),
            createdAt=data.get("createdAt", ""),
        )


@dataclass
class AuditLogEntry:
    id: str
    orgId: str
    memberId: str
    memberEmail: str
    action: str
    resourceType: str
    resourceId: str
    before: Optional[Dict[str, Any]]
    after: Optional[Dict[str, Any]]
    timestamp: str

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "AuditLogEntry":
        return cls(
            id=data.get("id", ""),
            orgId=data.get("orgId", ""),
            memberId=data.get("memberId", ""),
            memberEmail=data.get("memberEmail", ""),
            action=data.get("action", ""),
            resourceType=data.get("resourceType", ""),
            resourceId=data.get("resourceId", ""),
            before=data.get("before"),
            after=data.get("after"),
            timestamp=data.get("timestamp", ""),
        )


@dataclass
class RetentionPolicy:
    orgId: str
    eventsRetentionDays: int
    tracesRetentionDays: int
    auditLogRetentionDays: int
    updatedAt: str

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "RetentionPolicy":
        return cls(
            orgId=data.get("orgId", ""),
            eventsRetentionDays=data.get("eventsRetentionDays", 90),
            tracesRetentionDays=data.get("tracesRetentionDays", 90),
            auditLogRetentionDays=data.get("auditLogRetentionDays", 365),
            updatedAt=data.get("updatedAt", ""),
        )


@dataclass
class Subscription:
    id: str
    orgId: str
    stripeCustomerId: Optional[str]
    stripeSubscriptionId: Optional[str]
    plan: str
    status: str
    currentPeriodStart: str
    currentPeriodEnd: str
    createdAt: str

    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> "Subscription":
        return cls(
            id=data.get("id", ""),
            orgId=data.get("orgId", ""),
            stripeCustomerId=data.get("stripeCustomerId"),
            stripeSubscriptionId=data.get("stripeSubscriptionId"),
            plan=data.get("plan", "free"),
            status=data.get("status", "active"),
            currentPeriodStart=data.get("currentPeriodStart", ""),
            currentPeriodEnd=data.get("currentPeriodEnd", ""),
            createdAt=data.get("createdAt", ""),
        )
