"""Proto conversion utilities for client operations."""

from __future__ import annotations

from collections.abc import Sequence
from typing import Protocol

from noteflow.grpc._types import AnnotationInfo, MeetingInfo
from noteflow.grpc.proto import noteflow_pb2


class ProtoSegment(Protocol):
    """Protocol for segment payloads used by the client."""

    segment_id: int
    text: str
    start_time: float
    end_time: float
    language: str
    speaker_id: str
    speaker_confidence: float


class ProtoMeeting(Protocol):
    """Protocol for meeting payloads used by the client."""

    id: str
    title: str
    state: int
    created_at: float
    started_at: float
    ended_at: float
    duration_seconds: float
    segments: Sequence[ProtoSegment]


class ProtoAnnotation(Protocol):
    """Protocol for annotation payloads used by the client."""

    id: str
    meeting_id: str
    annotation_type: int
    text: str
    start_time: float
    end_time: float
    segment_ids: Sequence[int]
    created_at: float


# Meeting state mapping
MEETING_STATE_MAP: dict[int, str] = {
    noteflow_pb2.MEETING_STATE_UNSPECIFIED: "unknown",
    noteflow_pb2.MEETING_STATE_CREATED: "created",
    noteflow_pb2.MEETING_STATE_RECORDING: "recording",
    noteflow_pb2.MEETING_STATE_STOPPED: "stopped",
    noteflow_pb2.MEETING_STATE_COMPLETED: "completed",
    noteflow_pb2.MEETING_STATE_ERROR: "error",
}

# Annotation type mapping
ANNOTATION_TYPE_MAP: dict[int, str] = {
    noteflow_pb2.ANNOTATION_TYPE_UNSPECIFIED: "note",
    noteflow_pb2.ANNOTATION_TYPE_ACTION_ITEM: "action_item",
    noteflow_pb2.ANNOTATION_TYPE_DECISION: "decision",
    noteflow_pb2.ANNOTATION_TYPE_NOTE: "note",
    noteflow_pb2.ANNOTATION_TYPE_RISK: "risk",
}

# Reverse mapping for annotation types
ANNOTATION_TYPE_TO_PROTO: dict[str, int] = {
    "note": noteflow_pb2.ANNOTATION_TYPE_NOTE,
    "action_item": noteflow_pb2.ANNOTATION_TYPE_ACTION_ITEM,
    "decision": noteflow_pb2.ANNOTATION_TYPE_DECISION,
    "risk": noteflow_pb2.ANNOTATION_TYPE_RISK,
}

# Export format mapping
EXPORT_FORMAT_TO_PROTO: dict[str, int] = {
    "markdown": noteflow_pb2.EXPORT_FORMAT_MARKDOWN,
    "html": noteflow_pb2.EXPORT_FORMAT_HTML,
}

# Job status mapping
JOB_STATUS_MAP: dict[int, str] = {
    noteflow_pb2.JOB_STATUS_UNSPECIFIED: "unknown",
    noteflow_pb2.JOB_STATUS_QUEUED: "queued",
    noteflow_pb2.JOB_STATUS_RUNNING: "running",
    noteflow_pb2.JOB_STATUS_COMPLETED: "completed",
    noteflow_pb2.JOB_STATUS_FAILED: "failed",
}


def proto_to_meeting_info(meeting: ProtoMeeting) -> MeetingInfo:
    """Convert proto Meeting to MeetingInfo.

    Args:
        meeting: Proto meeting message.

    Returns:
        MeetingInfo dataclass.
    """
    return MeetingInfo(
        id=meeting.id,
        title=meeting.title,
        state=MEETING_STATE_MAP.get(meeting.state, "unknown"),
        created_at=meeting.created_at,
        started_at=meeting.started_at,
        ended_at=meeting.ended_at,
        duration_seconds=meeting.duration_seconds,
        segment_count=len(meeting.segments),
    )


def proto_to_annotation_info(annotation: ProtoAnnotation) -> AnnotationInfo:
    """Convert proto Annotation to AnnotationInfo.

    Args:
        annotation: Proto annotation message.

    Returns:
        AnnotationInfo dataclass.
    """
    return AnnotationInfo(
        id=annotation.id,
        meeting_id=annotation.meeting_id,
        annotation_type=ANNOTATION_TYPE_MAP.get(annotation.annotation_type, "note"),
        text=annotation.text,
        start_time=annotation.start_time,
        end_time=annotation.end_time,
        segment_ids=list(annotation.segment_ids),
        created_at=annotation.created_at,
    )


def annotation_type_to_proto(annotation_type: str) -> int:
    """Convert annotation type string to proto enum.

    Args:
        annotation_type: Type string.

    Returns:
        Proto enum value (int accepted by protobuf enum fields).
    """
    return ANNOTATION_TYPE_TO_PROTO.get(
        annotation_type, noteflow_pb2.ANNOTATION_TYPE_NOTE
    )


def export_format_to_proto(format_str: str) -> int:
    """Convert export format string to proto enum.

    Args:
        format_str: Format string.

    Returns:
        Proto enum value (int accepted by protobuf enum fields).
    """
    return EXPORT_FORMAT_TO_PROTO.get(
        format_str, noteflow_pb2.EXPORT_FORMAT_MARKDOWN
    )


def job_status_to_str(status: int) -> str:
    """Convert job status proto enum to string.

    Args:
        status: Proto enum value.

    Returns:
        Status string.
    """
    return JOB_STATUS_MAP.get(status, "unknown")
