"""Tests for ExportService application service."""

from __future__ import annotations

from pathlib import Path
from typing import cast
from unittest.mock import AsyncMock, MagicMock
from uuid import uuid4

import pytest

from noteflow.application.services.export_service import ExportFormat, ExportService
from noteflow.domain.entities import Meeting, Segment
from noteflow.domain.value_objects import MeetingId


def _uow_with_meeting(meeting: Meeting | None, segments: list[Segment] | None = None) -> MagicMock:
    """Build a minimal async UnitOfWork double."""
    uow = MagicMock()
    uow.__aenter__ = AsyncMock(return_value=uow)
    uow.__aexit__ = AsyncMock(return_value=None)
    uow.commit = AsyncMock()
    uow.meetings = MagicMock(get=AsyncMock(return_value=meeting))
    uow.segments = MagicMock(get_by_meeting=AsyncMock(return_value=segments or []))
    return uow


@pytest.mark.asyncio
async def test_export_transcript_meeting_not_found() -> None:
    """export_transcript should raise when meeting is missing."""
    meeting_id = MeetingId(uuid4())
    service = ExportService(_uow_with_meeting(meeting=None))

    with pytest.raises(ValueError, match="not found"):
        await service.export_transcript(meeting_id)


@pytest.mark.asyncio
async def test_export_to_file_infers_format_and_writes(tmp_path: Path) -> None:
    """export_to_file infers markdown from extension and writes content."""
    meeting = Meeting.create(title="Demo")
    segments = [
        Segment(
            segment_id=0,
            text="Hello world",
            start_time=0.0,
            end_time=1.0,
            meeting_id=meeting.id,
        )
    ]
    uow = _uow_with_meeting(meeting, segments)
    service = ExportService(uow)

    output = await service.export_to_file(meeting.id, tmp_path / "export.markdown")

    assert output.suffix == ".md"
    assert output.exists()
    content = output.read_text(encoding="utf-8")
    assert "Hello world" in content


def test_infer_format_rejects_unknown_extension() -> None:
    """infer_format_from_extension should raise for unknown suffix."""
    service = ExportService(_uow_with_meeting(None))

    with pytest.raises(ValueError, match="Cannot infer format"):
        service.infer_format_from_extension(".txt")


def test_get_exporter_raises_for_unknown_format() -> None:
    """get_exporter should guard against unsupported enums."""
    service = ExportService(_uow_with_meeting(None))

    class FakeFormat:
        HTML = "html"

    with pytest.raises(ValueError, match="Unsupported"):
        service.get_exporter(cast(ExportFormat, FakeFormat.HTML))


def test_get_supported_formats_returns_names_and_extensions() -> None:
    """get_supported_formats should expose format metadata."""
    service = ExportService(_uow_with_meeting(None))

    formats = {name.lower(): ext for name, ext in service.get_supported_formats()}

    assert formats["markdown"] == ".md", "Markdown format should have .md extension"
    assert formats["html"] == ".html", "HTML format should have .html extension"
    assert formats["pdf"] == ".pdf", "PDF format should have .pdf extension"
