import pytest
from flask import url_for
from freezegun import freeze_time

from app.utils.letters import (
    get_letter_printing_statement,
    get_letter_validation_error,
    printing_today_or_tomorrow,
)
from tests import NotifyBeautifulSoup


@pytest.mark.parametrize(
    "utc_datetime",
    [
        "2018-08-01T23:00:00+00:00",
        "2018-08-01T16:29:00+00:00",
        "2018-11-01T00:00:00+00:00",
        "2018-11-01T10:00:00+00:00",
        "2018-11-01T17:29:00+00:00",
    ],
)
def test_printing_today_or_tomorrow_returns_today(utc_datetime):
    with freeze_time(utc_datetime):
        assert printing_today_or_tomorrow(utc_datetime) == "today"


@pytest.mark.parametrize(
    "utc_datetime",
    [
        "2018-08-01T22:59:00+00:00",
        "2018-08-01T16:30:00+00:00",
        "2018-11-01T17:30:00+00:00",
        "2018-11-01T21:00:00+00:00",
        "2018-11-01T23:59:00+00:00",
    ],
)
def test_printing_today_or_tomorrow_returns_tomorrow(utc_datetime):
    with freeze_time(utc_datetime):
        assert printing_today_or_tomorrow(utc_datetime) == "tomorrow"


@pytest.mark.parametrize(
    "created_at, current_datetime",
    [
        ("2017-07-07T12:00:00+00:00", "2017-07-07 16:29:00"),  # created today, summer
        ("2017-07-06T23:30:00+00:00", "2017-07-07 16:29:00"),  # created just after midnight, summer
        ("2017-12-12T12:00:00+00:00", "2017-12-12 17:29:00"),  # created today, winter
        ("2017-12-12T21:30:00+00:00", "2017-12-13 17:29:00"),  # created after 5:30 yesterday
        ("2017-03-25T17:31:00+00:00", "2017-03-26 16:29:00"),  # over clock change period on 2017-03-26
    ],
)
def test_get_letter_printing_statement_when_letter_prints_today(created_at, current_datetime):
    with freeze_time(current_datetime):
        statement = get_letter_printing_statement("created", created_at)

    assert statement == "Printing starts today at 5:30pm"


@pytest.mark.parametrize(
    "created_at, current_datetime",
    [
        ("2017-07-07T16:31:00+00:00", "2017-07-07 22:59:00"),  # created today, summer
        ("2017-12-12T17:31:00+00:00", "2017-12-12 23:59:00"),  # created today, winter
    ],
)
def test_get_letter_printing_statement_when_letter_prints_tomorrow(created_at, current_datetime):
    with freeze_time(current_datetime):
        statement = get_letter_printing_statement("created", created_at)

    assert statement == "Printing starts tomorrow at 5:30pm"


@pytest.mark.parametrize(
    "created_at, print_day",
    [
        ("2017-07-06T16:29:00+00:00", "yesterday"),
        ("2017-12-01T00:00:00+00:00", "on 1 December"),
        ("2017-03-26T12:00:00+00:00", "on 26 March"),
    ],
)
@freeze_time("2017-07-07 12:00:00")
def test_get_letter_printing_statement_for_letter_that_has_been_sent(created_at, print_day):
    statement = get_letter_printing_statement("delivered", created_at)

    assert statement == f"Printed {print_day} at 5:30pm"


def test_get_letter_validation_error_for_unknown_error():
    assert get_letter_validation_error("Unknown error") == {"title": "Validation failed"}


@pytest.mark.parametrize(
    "error_message, invalid_pages, expected_title, expected_content, expected_summary",
    [
        (
            "letter-not-a4-portrait-oriented",
            [2],
            "Your letter is not A4 portrait size",
            "You need to change the size or orientation of page 2. Files must meet our letter specification.",
            "Validation failed because page 2 is not A4 portrait size.Files must meet our letter specification.",
        ),
        (
            "letter-not-a4-portrait-oriented",
            [2, 3, 4],
            "Your letter is not A4 portrait size",
            (
                "You need to change the size or orientation of pages 2, 3 and 4. "
                "Files must meet our letter specification."
            ),
            (
                "Validation failed because pages 2, 3 and 4 are not A4 portrait size."
                "Files must meet our letter specification."
            ),
        ),
        (
            "content-outside-printable-area",
            [2],
            "Your content is outside the printable area",
            "You need to edit page 2.Files must meet our letter specification.",
            (
                "Validation failed because content is outside the printable area "
                "on page 2."
                "Files must meet our letter specification."
            ),
        ),
        (
            "letter-too-long",
            None,
            "Your letter is too long",
            "Letters must be 10 pages or less (5 double-sided sheets of paper). Your letter is 13 pages long.",
            (
                "Validation failed because this letter is 13 pages long."
                "Letters must be 10 pages or less (5 double-sided sheets of paper)."
            ),
        ),
        (
            "unable-to-read-the-file",
            None,
            "There’s a problem with your file",
            "Notify cannot read this PDF.Save a new copy of your file and try again.",
            "Validation failed because Notify cannot read this PDF.Save a new copy of your file and try again.",
        ),
        (
            "address-is-empty",
            None,
            "The address block is empty",
            "You need to add a recipient address.Files must meet our letter specification.",
            "Validation failed because the address block is empty.Files must meet our letter specification.",
        ),
        (
            "not-a-real-uk-postcode",
            None,
            "There’s a problem with the address for this letter",
            "The last line of the address must be a real UK postcode.",
            "Validation failed because the last line of the address is not a real UK postcode.",
        ),
        (
            "cant-send-international-letters",
            None,
            "There’s a problem with the address for this letter",
            "You do not have permission to send letters to other countries.",
            "Validation failed because your service cannot send letters to other countries.",
        ),
        (
            "not-a-real-uk-postcode-or-country",
            None,
            "There’s a problem with the address for this letter",
            "The last line of the address must be a UK postcode or another country.",
            "Validation failed because the last line of the address is not a UK postcode or another country.",
        ),
        (
            "not-enough-address-lines",
            None,
            "There’s a problem with the address for this letter",
            "The address must be at least 3 lines long.",
            "Validation failed because the address must be at least 3 lines long.",
        ),
        (
            "too-many-address-lines",
            None,
            "There’s a problem with the address for this letter",
            "The address must be no more than 7 lines long.",
            "Validation failed because the address must be no more than 7 lines long.",
        ),
        (
            "invalid-char-in-address",
            None,
            "There’s a problem with the address for this letter",
            "Address lines must not start with any of the following characters: @ ( ) = [ ] ” \\ / , < > ~",
            (
                "Validation failed because address lines must not start with any of the following "
                "characters: @ ( ) = [ ] ” \\ / , < > ~"
            ),
        ),
    ],
)
def test_get_letter_validation_error_for_known_errors(
    client_request,
    error_message,
    invalid_pages,
    expected_title,
    expected_content,
    expected_summary,
):
    error = get_letter_validation_error(error_message, invalid_pages=invalid_pages, page_count=13)
    detail = NotifyBeautifulSoup(error["detail"], "html.parser")
    summary = NotifyBeautifulSoup(error["summary"], "html.parser")

    assert error["title"] == expected_title

    assert detail.text == expected_content
    if detail.select_one("a"):
        assert detail.select_one("a")["href"] == url_for("main.guidance_upload_a_letter")

    assert summary.text == expected_summary
    if summary.select_one("a"):
        assert summary.select_one("a")["href"] == url_for("main.guidance_upload_a_letter")
