"""Tests for GenerateSummary RPC fallback behavior."""

from __future__ import annotations

from collections.abc import Sequence

import grpc
import pytest

from noteflow.application.services.summarization_service import (
    SummarizationMode,
    SummarizationService,
    SummarizationServiceResult,
)
from noteflow.domain.entities import Segment
from noteflow.domain.summarization import ProviderUnavailableError
from noteflow.domain.value_objects import MeetingId
from noteflow.grpc._config import ServicesConfig
from noteflow.grpc.proto import noteflow_pb2
from noteflow.grpc.service import NoteFlowServicer


class _DummyContext:
    """Minimal gRPC context that raises if abort is invoked."""

    async def abort(self, code: grpc.StatusCode, details: str) -> None:
        raise AssertionError(f"abort called: {code} - {details}")


@pytest.mark.asyncio
async def test_generate_summary_uses_placeholder_when_service_missing() -> None:
    """Ensure RPC returns a placeholder when no summarization service is configured."""

    servicer = NoteFlowServicer()
    store = servicer.get_memory_store()

    meeting = store.create("Test Meeting")
    store.add_segment(
        str(meeting.id),
        Segment(segment_id=0, text="Hello world", start_time=0.0, end_time=1.0, language="en"),
    )

    response = await servicer.GenerateSummary(
        noteflow_pb2.GenerateSummaryRequest(meeting_id=str(meeting.id)),
        _DummyContext(),
    )

    assert response.executive_summary != "", "executive summary should not be empty"
    assert response.model_version == "placeholder/v0", "should use placeholder model"
    retrieved_meeting = store.get(str(meeting.id))
    assert retrieved_meeting is not None, "Meeting should exist after creation"
    assert retrieved_meeting.summary is not None, "summary should be stored on meeting"


class _FailingSummarizationService(SummarizationService):
    """Summarization service that always reports provider unavailability."""

    async def summarize(
        self,
        meeting_id: MeetingId,
        segments: Sequence[Segment],
        mode: SummarizationMode | None = None,
        max_key_points: int | None = None,
        max_action_items: int | None = None,
        style_prompt: str | None = None,
    ) -> SummarizationServiceResult:
        raise ProviderUnavailableError("LLM unavailable")


@pytest.mark.asyncio
async def test_generate_summary_falls_back_when_provider_unavailable() -> None:
    """Provider errors should fall back to placeholder instead of failing the RPC."""

    servicer = NoteFlowServicer(services=ServicesConfig(summarization_service=_FailingSummarizationService()))
    store = servicer.get_memory_store()

    meeting = store.create("Test Meeting")
    store.add_segment(
        str(meeting.id),
        Segment(
            segment_id=1, text="Action item noted", start_time=0.0, end_time=2.0, language="en"
        ),
    )

    response = await servicer.GenerateSummary(
        noteflow_pb2.GenerateSummaryRequest(meeting_id=str(meeting.id)),
        _DummyContext(),
    )

    assert response.executive_summary != "", "fallback should produce non-empty summary"
    assert response.model_version == "placeholder/v0", "fallback should use placeholder model"
