from pathlib import Path

import pytest

from chitai.services.utils import guess_content_type


@pytest.mark.parametrize(
    ("filename", "expected"),
    [
        # What `mimetypes` already knows, kept here so a host with a thin
        # /etc/mime.types cannot change the answer without a test noticing.
        ("Frankenstein.epub", "application/epub+zip"),
        ("Calculus.pdf", "application/pdf"),
        ("Persepolis.azw3", "application/vnd.amazon.mobi8-ebook"),
        ("Watchmen.cbz", "application/vnd.comicbook+zip"),
        # What it does not, and where a Calibre library's older formats live.
        ("Dune.mobi", "application/x-mobipocket-ebook"),
        ("Dune.prc", "application/x-mobipocket-ebook"),
        ("Dune.azw", "application/vnd.amazon.ebook"),
        ("Voyna i Mir.fb2", "application/x-fictionbook+xml"),
        ("Voyna i Mir.fbz", "application/x-zip-compressed-fb2"),
        ("Reader.lit", "application/x-ms-reader"),
        ("Reader.lrf", "application/x-sony-bbeb"),
        ("Watchmen.cb7", "application/x-cb7"),
        # Case is not part of the answer, and Calibre writes formats uppercase.
        ("Dune.MOBI", "application/x-mobipocket-ebook"),
        # Nothing can name these, and None is the answer rather than a placeholder.
        ("Notes.xyzzy", None),
        ("README", None),
    ],
)
def test_guess_content_type(filename: str, expected: str | None) -> None:
    assert guess_content_type(Path(filename)) == expected
    # A str and a Path must agree, and an upload's `filename` carries its relative
    # path, so a name with directories in front of it has to resolve the same way.
    assert guess_content_type(filename) == expected
    assert guess_content_type(f"Some Author/Some Book/{filename}") == expected


def test_fallback_is_used_only_when_the_extension_says_nothing() -> None:
    """A client's claim fills a gap; it never overrides the name."""
    assert (
        guess_content_type(Path("Dune.mobi"), fallback="application/pdf")
        == "application/x-mobipocket-ebook"
    )
    assert (
        guess_content_type(Path("Notes.xyzzy"), fallback="application/epub+zip")
        == "application/epub+zip"
    )


def test_an_unspecified_fallback_is_not_an_answer() -> None:
    """
    `application/octet-stream` from a client is it saying it does not know.

    Browsers post exactly that for every extension they do not recognise, which is most
    ebook formats. Storing it would be indistinguishable from having determined a
    format, so it is discarded and the column keeps its null.
    """
    assert (
        guess_content_type(Path("Notes.xyzzy"), fallback="application/octet-stream")
        is None
    )
