"""
AgentPhone response models.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Optional


# --- Numbers ---

@dataclass
class PhoneNumber:
    id: str
    phone_number: str
    country: str
    status: str
    agent_id: Optional[str]
    created_at: str
    type: Optional[str] = None

    @classmethod
    def from_dict(cls, d: dict) -> "PhoneNumber":
        return cls(
            id=d["id"],
            phone_number=d["phoneNumber"],
            country=d["country"],
            status=d["status"],
            agent_id=d.get("agentId"),
            created_at=d["createdAt"],
            type=d.get("type"),
        )


@dataclass
class PhoneNumberList:
    data: list[PhoneNumber]
    has_more: bool
    total: int

    @classmethod
    def from_dict(cls, d: dict) -> "PhoneNumberList":
        return cls(
            data=[PhoneNumber.from_dict(n) for n in d["data"]],
            has_more=d["hasMore"],
            total=d["total"],
        )


# --- Contacts ---

@dataclass
class Contact:
    id: str
    phone_number: str
    name: str
    created_at: str
    updated_at: str
    email: Optional[str] = None
    notes: Optional[str] = None

    @classmethod
    def from_dict(cls, d: dict) -> "Contact":
        return cls(
            id=d["id"],
            phone_number=d["phoneNumber"],
            name=d["name"],
            email=d.get("email"),
            notes=d.get("notes"),
            created_at=d["createdAt"],
            updated_at=d["updatedAt"],
        )


@dataclass
class ContactList:
    data: list[Contact]
    has_more: bool
    total: int

    @classmethod
    def from_dict(cls, d: dict) -> "ContactList":
        return cls(
            data=[Contact.from_dict(c) for c in d["data"]],
            has_more=d["hasMore"],
            total=d["total"],
        )


# --- Messages ---

@dataclass
class Message:
    id: str
    from_number: str
    to_number: str
    body: str
    received_at: str
    direction: Optional[str] = None
    channel: Optional[str] = None
    media_url: Optional[str] = None
    conversation_id: Optional[str] = None

    @classmethod
    def from_dict(cls, d: dict) -> "Message":
        return cls(
            id=d["id"],
            from_number=d.get("fromNumber") or d.get("from_") or d.get("from", ""),
            to_number=d.get("toNumber") or d.get("to", ""),
            body=d["body"],
            received_at=d["receivedAt"],
            direction=d.get("direction"),
            channel=d.get("channel"),
            media_url=d.get("mediaUrl"),
            conversation_id=d.get("conversationId"),
        )


@dataclass
class MessageList:
    data: list[Message]
    has_more: bool

    @classmethod
    def from_dict(cls, d: dict) -> "MessageList":
        return cls(
            data=[Message.from_dict(m) for m in d["data"]],
            has_more=d["hasMore"],
        )


# --- Agents ---

@dataclass
class AgentNumber:
    id: str
    phone_number: str
    status: str
    type: str = "sms"

    @classmethod
    def from_dict(cls, d: dict) -> "AgentNumber":
        return cls(
            id=d["id"],
            phone_number=d["phoneNumber"],
            status=d["status"],
            type=d.get("type", "sms"),
        )


@dataclass
class Agent:
    id: str
    name: str
    description: Optional[str]
    created_at: str
    voice_mode: Optional[str] = None
    system_prompt: Optional[str] = None
    begin_message: Optional[str] = None
    voice: Optional[str] = None
    transfer_number: Optional[str] = None
    voicemail_message: Optional[str] = None
    numbers: list[AgentNumber] = field(default_factory=list)

    @classmethod
    def from_dict(cls, d: dict) -> "Agent":
        return cls(
            id=d["id"],
            name=d["name"],
            description=d.get("description"),
            created_at=d["createdAt"],
            voice_mode=d.get("voiceMode"),
            system_prompt=d.get("systemPrompt"),
            begin_message=d.get("beginMessage"),
            voice=d.get("voice"),
            transfer_number=d.get("transferNumber"),
            voicemail_message=d.get("voicemailMessage"),
            numbers=[AgentNumber.from_dict(n) for n in d.get("numbers", [])],
        )


@dataclass
class AgentList:
    data: list[Agent]
    has_more: bool
    total: int

    @classmethod
    def from_dict(cls, d: dict) -> "AgentList":
        return cls(
            data=[Agent.from_dict(a) for a in d["data"]],
            has_more=d.get("hasMore", False),
            total=d["total"],
        )


# --- Calls ---

@dataclass
class CallTranscript:
    id: str
    transcript: str
    response: Optional[str]
    created_at: str

    @classmethod
    def from_dict(cls, d: dict) -> "CallTranscript":
        return cls(
            id=d["id"],
            transcript=d["transcript"],
            response=d.get("response"),
            created_at=d["createdAt"],
        )


@dataclass
class Call:
    id: str
    from_number: str
    to_number: str
    direction: str
    status: str
    started_at: str
    ended_at: Optional[str]
    agent_id: Optional[str]
    transcripts: list[CallTranscript] = field(default_factory=list)
    phone_number_id: Optional[str] = None
    agent_name: Optional[str] = None
    recording_url: Optional[str] = None
    recording_available: bool = False
    duration_seconds: Optional[int] = None

    @classmethod
    def from_dict(cls, d: dict) -> "Call":
        return cls(
            id=d["id"],
            from_number=d["fromNumber"],
            to_number=d["toNumber"],
            direction=d["direction"],
            status=d["status"],
            started_at=d["startedAt"],
            ended_at=d.get("endedAt"),
            agent_id=d.get("agentId"),
            transcripts=[CallTranscript.from_dict(t) for t in d.get("transcripts", [])],
            phone_number_id=d.get("phoneNumberId"),
            agent_name=d.get("agentName"),
            recording_url=d.get("recordingUrl"),
            recording_available=d.get("recordingAvailable", False),
            duration_seconds=d.get("durationSeconds"),
        )


@dataclass
class CallList:
    data: list[Call]
    has_more: bool
    total: int

    @classmethod
    def from_dict(cls, d: dict) -> "CallList":
        return cls(
            data=[Call.from_dict(c) for c in d["data"]],
            has_more=d["hasMore"],
            total=d["total"],
        )


# --- Conversations ---

@dataclass
class ConversationMessage:
    id: str
    from_number: str
    to_number: str
    body: str
    received_at: str
    direction: Optional[str] = None
    channel: Optional[str] = None
    media_url: Optional[str] = None

    @classmethod
    def from_dict(cls, d: dict) -> "ConversationMessage":
        return cls(
            id=d["id"],
            from_number=d.get("fromNumber") or d.get("from_") or d.get("from", ""),
            to_number=d.get("toNumber") or d.get("to", ""),
            body=d["body"],
            received_at=d["receivedAt"],
            direction=d.get("direction"),
            channel=d.get("channel"),
            media_url=d.get("mediaUrl"),
        )


@dataclass
class Conversation:
    id: str
    phone_number: str
    participant: str
    last_message_at: Optional[str]
    message_count: int
    agent_id: Optional[str]
    messages: list[ConversationMessage] = field(default_factory=list)
    phone_number_id: Optional[str] = None
    last_message_preview: Optional[str] = None
    metadata: Optional[dict] = None

    @classmethod
    def from_dict(cls, d: dict) -> "Conversation":
        return cls(
            id=d["id"],
            phone_number=d["phoneNumber"],
            participant=d.get("participant") or d.get("contactNumber", ""),
            last_message_at=d.get("lastMessageAt"),
            message_count=d.get("messageCount", 0),
            agent_id=d.get("agentId"),
            messages=[ConversationMessage.from_dict(m) for m in d.get("messages", [])],
            phone_number_id=d.get("phoneNumberId"),
            last_message_preview=d.get("lastMessagePreview"),
            metadata=d.get("metadata"),
        )


@dataclass
class ConversationList:
    data: list[Conversation]
    has_more: bool
    total: int

    @classmethod
    def from_dict(cls, d: dict) -> "ConversationList":
        return cls(
            data=[Conversation.from_dict(c) for c in d["data"]],
            has_more=d["hasMore"],
            total=d["total"],
        )


# --- Usage ---

@dataclass
class PlanLimits:
    numbers: int
    messages_per_month: int
    voice_minutes_per_month: int
    max_call_duration_minutes: int
    concurrent_calls: int

    @classmethod
    def from_dict(cls, d: dict) -> "PlanLimits":
        return cls(
            numbers=d["numbers"],
            messages_per_month=d["messagesPerMonth"],
            voice_minutes_per_month=d["voiceMinutesPerMonth"],
            max_call_duration_minutes=d["maxCallDurationMinutes"],
            concurrent_calls=d["concurrentCalls"],
        )


@dataclass
class PlanInfo:
    name: str
    limits: PlanLimits

    @classmethod
    def from_dict(cls, d: dict) -> "PlanInfo":
        return cls(name=d["name"], limits=PlanLimits.from_dict(d["limits"]))


@dataclass
class NumberLimits:
    used: int
    limit: int
    remaining: int

    @classmethod
    def from_dict(cls, d: dict) -> "NumberLimits":
        return cls(used=d["used"], limit=d["limit"], remaining=d["remaining"])


@dataclass
class UsageStats:
    total_messages: int
    messages_last_24h: int
    messages_last_7d: int
    messages_last_30d: int
    total_calls: int
    calls_last_24h: int
    calls_last_7d: int
    calls_last_30d: int
    total_webhook_deliveries: int
    successful_webhook_deliveries: int
    failed_webhook_deliveries: int

    @classmethod
    def from_dict(cls, d: dict) -> "UsageStats":
        return cls(
            total_messages=d["totalMessages"],
            messages_last_24h=d["messagesLast24h"],
            messages_last_7d=d["messagesLast7d"],
            messages_last_30d=d["messagesLast30d"],
            total_calls=d["totalCalls"],
            calls_last_24h=d["callsLast24h"],
            calls_last_7d=d["callsLast7d"],
            calls_last_30d=d["callsLast30d"],
            total_webhook_deliveries=d["totalWebhookDeliveries"],
            successful_webhook_deliveries=d["successfulWebhookDeliveries"],
            failed_webhook_deliveries=d["failedWebhookDeliveries"],
        )


@dataclass
class Usage:
    plan: PlanInfo
    numbers: NumberLimits
    stats: UsageStats
    period_start: str
    period_end: str

    @classmethod
    def from_dict(cls, d: dict) -> "Usage":
        return cls(
            plan=PlanInfo.from_dict(d["plan"]),
            numbers=NumberLimits.from_dict(d["numbers"]),
            stats=UsageStats.from_dict(d["stats"]),
            period_start=d["periodStart"],
            period_end=d["periodEnd"],
        )


@dataclass
class DailyUsagePoint:
    date: str
    messages: int
    calls: int
    webhooks: int

    @classmethod
    def from_dict(cls, d: dict) -> "DailyUsagePoint":
        return cls(date=d["date"], messages=d["messages"], calls=d["calls"], webhooks=d["webhooks"])


@dataclass
class DailyUsage:
    data: list[DailyUsagePoint]
    days: int

    @classmethod
    def from_dict(cls, d: dict) -> "DailyUsage":
        return cls(data=[DailyUsagePoint.from_dict(p) for p in d["data"]], days=d["days"])


@dataclass
class MonthlyUsagePoint:
    month: str
    messages: int
    calls: int
    webhooks: int

    @classmethod
    def from_dict(cls, d: dict) -> "MonthlyUsagePoint":
        return cls(month=d["month"], messages=d["messages"], calls=d["calls"], webhooks=d["webhooks"])


@dataclass
class MonthlyUsage:
    data: list[MonthlyUsagePoint]
    months: int

    @classmethod
    def from_dict(cls, d: dict) -> "MonthlyUsage":
        return cls(data=[MonthlyUsagePoint.from_dict(p) for p in d["data"]], months=d["months"])


# --- Webhooks ---

@dataclass
class Webhook:
    id: str
    url: str
    secret: str
    status: str
    context_limit: int
    created_at: str
    timeout: Optional[int] = None

    @classmethod
    def from_dict(cls, d: dict) -> "Webhook":
        return cls(
            id=d["id"],
            url=d["url"],
            secret=d["secret"],
            status=d["status"],
            context_limit=d["contextLimit"],
            created_at=d["createdAt"],
            timeout=d.get("timeout"),
        )


@dataclass
class WebhookDelivery:
    id: str
    status: str
    attempt_count: int
    created_at: str
    message_id: Optional[str] = None
    http_status: Optional[int] = None
    error_message: Optional[str] = None
    last_attempt_at: Optional[str] = None
    next_retry_at: Optional[str] = None
    event_type: Optional[str] = None
    channel: Optional[str] = None
    response_body: Optional[str] = None

    @classmethod
    def from_dict(cls, d: dict) -> "WebhookDelivery":
        return cls(
            id=d["id"],
            message_id=d.get("messageId"),
            status=d["status"],
            http_status=d.get("httpStatus"),
            error_message=d.get("errorMessage"),
            response_body=d.get("responseBody"),
            attempt_count=d["attemptCount"],
            last_attempt_at=d.get("lastAttemptAt"),
            next_retry_at=d.get("nextRetryAt"),
            created_at=d["createdAt"],
            event_type=d.get("eventType"),
            channel=d.get("channel"),
        )


@dataclass
class WebhookDeliveryStats:
    total: int
    success: int
    failed: int
    pending: int
    success_rate: float
    by_event_type: dict
    by_hour: list[dict]

    @classmethod
    def from_dict(cls, d: dict) -> "WebhookDeliveryStats":
        return cls(
            total=d["total"],
            success=d["success"],
            failed=d["failed"],
            pending=d["pending"],
            success_rate=d["successRate"],
            by_event_type=d.get("byEventType", {}),
            by_hour=d.get("byHour", []),
        )


# --- Webhook event payload ---

@dataclass
class WebhookHistoryItem:
    content: str
    direction: str
    channel: str
    at: str

    @classmethod
    def from_dict(cls, d: dict) -> "WebhookHistoryItem":
        return cls(
            content=d["content"],
            direction=d["direction"],
            channel=d["channel"],
            at=d["at"],
        )


@dataclass
class WebhookEventData:
    conversation_id: Optional[str]
    number_id: Optional[str]
    from_number: str
    to_number: str
    message: str
    direction: str
    received_at: str

    @classmethod
    def from_dict(cls, d: dict) -> "WebhookEventData":
        return cls(
            conversation_id=d.get("conversationId"),
            number_id=d.get("numberId"),
            from_number=d["from"],
            to_number=d["to"],
            message=d["message"],
            direction=d["direction"],
            received_at=d["receivedAt"],
        )


@dataclass
class WebhookEvent:
    event: str
    channel: str
    timestamp: str
    agent_id: Optional[str]
    data: WebhookEventData
    recent_history: list[WebhookHistoryItem] = field(default_factory=list)
    conversation_state: Optional[dict] = None

    @classmethod
    def from_dict(cls, d: dict) -> "WebhookEvent":
        return cls(
            event=d["event"],
            channel=d["channel"],
            timestamp=d["timestamp"],
            agent_id=d.get("agentId"),
            data=WebhookEventData.from_dict(d["data"]),
            recent_history=[WebhookHistoryItem.from_dict(h) for h in d.get("recentHistory", [])],
            conversation_state=d.get("conversationState"),
        )
