"""Reading an answer to "whose document is this?".

The reference is the whole point. Without it, a number arriving an hour later
into a self-chat with no threading can only be matched by guessing — and being
wrong files one client's bank statement onto another client's record, silently.

Most of what follows is about what is REFUSED. A parser that reads an answer out
of a message that was not one is the failure this feature could introduce.
"""

from __future__ import annotations

from app.documents.replies import read


class TestReadingAnAnswer:
    def test_a_reference_and_a_cnic(self):
        reply = read("DOC-1001 35201-1234567-1")

        assert reply.reference == "DOC-1001"
        assert reply.identifier == "3520112345671"

    def test_a_reference_and_a_bare_file_number(self):
        """The shape the notification actually invites.

        identifiers.py refuses a bare integer, correctly, because in free text
        it is not an identifier. After a reference it is the answer to a
        question — there is nothing else it could be.
        """
        reply = read("DOC-1001 2124")

        assert reply.reference == "DOC-1001"
        assert reply.identifier == "2124"

    def test_a_reference_and_a_labelled_file_number(self):
        reply = read("DOC-1001 file 2124")

        assert reply.identifier == "2124"

    def test_the_reference_may_come_second(self):
        # People type what they are looking at first.
        reply = read("35201-1234567-1 DOC-1001")

        assert reply.reference == "DOC-1001"
        assert reply.identifier == "3520112345671"

    def test_case_and_punctuation_do_not_matter(self):
        for text in ["doc-1001: 2124", "DOC-1001 - 2124", "Doc-1001,2124"]:
            assert read(text).identifier == "2124", text

    def test_a_file_number_with_a_letter_suffix(self):
        # This practice really has "884 A".
        assert read("DOC-1001 884A").identifier == "884A"

    def test_a_single_digit_file_number(self):
        """Found by running the whole thing against the real install.

        The first version of the pattern required at least two characters, and
        every test here had used a comfortable four-digit number. The first
        client on the install is file number 1 — so "DOC-1061 1" parsed as
        nothing, the reply would have been ignored, and the document left
        waiting with no indication why.

        identifiers.py says it plainly in its own docstring: these run "from
        single digits into the thousands". I had read that and still written a
        pattern that excluded them.
        """
        assert read("DOC-1061 1").identifier == "1"
        assert read("DOC-1061 7").identifier == "7"


class TestWhatIsRefused:
    def test_a_number_with_no_reference_is_not_a_reply(self):
        """The one that matters most.

        This is exactly the message that would arrive if somebody answered
        without the reference — and the only ways to attribute it are guesses.
        Refusing here leaves it to the existing path, which has its own
        deliberate rules, rather than inventing a second guess.
        """
        assert read("35201-1234567-1") is None
        assert read("file 2124") is None

    def test_prose_around_a_reference_is_not_an_identifier(self):
        """Where the relaxation stops.

        "2024" is a year. Reading it as file 2024 would file a document against
        whichever client happens to hold that number — the precise failure the
        bare-integer rule exists to prevent, reintroduced through the back door.
        """
        assert read("DOC-1001 I think this is from 2024 sometime") is None

    def test_a_reference_alone_is_not_an_answer(self):
        # Somebody acknowledging the message, not answering it.
        assert read("DOC-1001") is None
        assert read("DOC-1001 thanks") is None

    def test_ordinary_conversation_is_not_a_reply(self):
        for text in ["", None, "ok", "sending the rest tomorrow", "3 pages"]:
            assert read(text) is None, text

    def test_something_that_merely_looks_like_a_reference_is_not_one(self):
        for text in ["DOCTOR-1001 2124", "DOC- 1001 2124", "MYDOC-1001 2124"]:
            assert read(text) is None, text
