"""Tests for fill_template.py"""
import json
import pathlib
import sys

import pytest

sys.path.insert(0, str(pathlib.Path(__file__).parents[1]))

from fill_template import fill_template, build_venue_list_html, _format_date, _format_time

FIXTURES = pathlib.Path(__file__).parents[1] / "fixtures" / "brief_prada2.json"
TEMPLATE_DIR = (
    pathlib.Path(__file__).parents[3]
    / "emails templates" / "Loyalty"
)
TEMPLATE_FR = TEMPLATE_DIR / "template_FR.html"
TEMPLATE_NL = TEMPLATE_DIR / "template_NL.html"


@pytest.fixture
def brief():
    data = json.loads(FIXTURES.read_text(encoding="utf-8"))
    # Inject hero_image_src since it is set by run_local.py after compositing
    data["fr"]["hero_image_src"] = "https://cdn.example.com/hero_FR.jpg"
    data["nl"]["hero_image_src"] = "https://cdn.example.com/hero_NL.jpg"
    return data


class TestFormatHelpers:
    """Unit tests for ISO date/time → language-specific string helpers."""

    def test_format_date_fr_april(self):
        assert _format_date("2026-04-30", "fr") == "30 avril"

    def test_format_date_fr_may(self):
        assert _format_date("2026-05-15", "fr") == "15 mai"

    def test_format_date_fr_january(self):
        assert _format_date("2026-01-01", "fr") == "1 janvier"

    def test_format_date_fr_december(self):
        assert _format_date("2026-12-25", "fr") == "25 décembre"

    def test_format_date_nl_april(self):
        assert _format_date("2026-04-30", "nl") == "30 april"

    def test_format_date_nl_may(self):
        assert _format_date("2026-05-15", "nl") == "15 mei"

    def test_format_date_nl_january(self):
        assert _format_date("2026-01-01", "nl") == "1 januari"

    def test_format_date_nl_december(self):
        assert _format_date("2026-12-25", "nl") == "25 december"

    def test_format_time_fr_round_hour(self):
        assert _format_time("20:00", "fr") == "20h00"

    def test_format_time_fr_with_minutes(self):
        assert _format_time("19:30", "fr") == "19h30"

    def test_format_time_nl_round_hour(self):
        assert _format_time("20:00", "nl") == "20.00 uur"

    def test_format_time_nl_with_minutes(self):
        assert _format_time("19:30", "nl") == "19.30 uur"

    def test_format_date_invalid_lang_raises(self):
        with pytest.raises(ValueError, match="lang must be"):
            _format_date("2026-04-30", "de")

    def test_format_time_invalid_lang_raises(self):
        with pytest.raises(ValueError, match="lang must be"):
            _format_time("20:00", "de")

    def test_format_time_malformed_raises(self):
        with pytest.raises(ValueError):
            _format_time("2000", "fr")


class TestBuildVenueListHtml:
    def test_returns_ul_element(self, brief):
        html = build_venue_list_html(brief["venues"], lang="fr")
        assert html.startswith("<ul")
        assert "</ul>" in html

    def test_fr_venue_names_present(self, brief):
        html = build_venue_list_html(brief["venues"], lang="fr")
        assert "Kinepolis Bruxelles" in html
        assert "Kinepolis Liège" in html

    def test_nl_venue_names_present(self, brief):
        html = build_venue_list_html(brief["venues"], lang="nl")
        assert "Kinepolis Brussel" in html
        assert "Kinepolis Luik" in html

    def test_fr_versions_present(self, brief):
        html = build_venue_list_html(brief["venues"], lang="fr")
        assert "version originale sous-titrée" in html
        assert "version française" in html

    def test_nl_versions_present(self, brief):
        html = build_venue_list_html(brief["venues"], lang="nl")
        assert "originele versie met ondertitels" in html
        assert "Franse versie" in html

    def test_venue_name_is_bold(self, brief):
        html = build_venue_list_html(brief["venues"], lang="fr")
        assert "<strong" in html

    def test_two_li_items(self, brief):
        html = build_venue_list_html(brief["venues"], lang="fr")
        assert html.count("<li>") == 2

    def test_invalid_lang_raises(self, brief):
        with pytest.raises(ValueError, match="lang must be 'fr' or 'nl'"):
            build_venue_list_html(brief["venues"], lang="de")


class TestFillTemplateFR:
    @pytest.fixture
    def filled(self, brief):
        return fill_template(TEMPLATE_FR.read_text(encoding="utf-8"), brief, lang="fr")

    def test_no_tokens_remain(self, filled):
        assert "{{" not in filled and "}}" not in filled

    def test_hero_image_src_replaced(self, filled):
        assert "DevilPrada2-FR.jpg" not in filled
        assert "https://cdn.example.com/hero_FR.jpg" in filled

    def test_h1_intro_replaced(self, filled, brief):
        assert brief["fr"]["h1_intro"] in filled

    def test_date_time_line(self, filled):
        # After schema change: brief has event_date="2026-04-30", event_time="20:00"
        # fill_template must produce "30 avril | 20h00" in the FR output
        assert "30 avril" in filled
        assert "20h00" in filled

    def test_body_paragraph_replaced(self, filled, brief):
        assert "vous accordez à Proximus" in filled

    def test_cta_href_contains_base_url(self, filled, brief):
        assert brief["cta_url"] in filled

    def test_cta_href_contains_eloqua_suffix(self, filled):
        assert "?l=fr" in filled
        assert "Loyalty_SFDC1" in filled

    def test_cta_text_replaced(self, filled, brief):
        assert brief["fr"]["cta_text"] in filled

    def test_venues_rendered(self, filled):
        assert "Kinepolis Bruxelles" in filled

    def test_about_title_uses_fr_movie_title(self, filled, brief):
        assert brief["movie_title_fr"] in filled

    def test_synopsis_replaced(self, filled, brief):
        assert brief["fr"]["synopsis"] in filled

    def test_closing_line_replaced(self, filled, brief):
        assert brief["fr"]["closing_line"] in filled

    def test_legal_disclaimer_replaced(self, filled, brief):
        assert brief["fr"]["legal_disclaimer"] in filled

    def test_eloqua_view_online_token_preserved(self, filled):
        assert "~~eloqua..type--emailfield..syntax--siteid..encodeFor--url~~" in filled

    def test_eloqua_dynamic_content_block_preserved(self, filled):
        assert 'elqid="1449"' in filled

    def test_is_valid_html(self, filled):
        assert filled.strip().lower().startswith("<!doctype html")


class TestFillTemplateNL:
    @pytest.fixture
    def filled(self, brief):
        return fill_template(TEMPLATE_NL.read_text(encoding="utf-8"), brief, lang="nl")

    def test_no_tokens_remain(self, filled):
        assert "{{" not in filled and "}}" not in filled

    def test_h1_intro_replaced(self, filled, brief):
        assert brief["nl"]["h1_intro"] in filled

    def test_date_time_line(self, filled):
        # After schema change: brief has event_date="2026-04-30", event_time="20:00"
        # fill_template must produce "30 april | 20.00 uur" in the NL output
        assert "30 april" in filled
        assert "20.00 uur" in filled

    def test_venues_rendered(self, filled):
        assert "Kinepolis Brussel" in filled

    def test_about_title_uses_nl_movie_title(self, filled, brief):
        assert brief["movie_title_nl"] in filled

    def test_synopsis_replaced(self, filled, brief):
        assert brief["nl"]["synopsis"] in filled

    def test_eloqua_dynamic_content_block_preserved(self, filled):
        assert 'elqid="1430"' in filled

    def test_legal_disclaimer_replaced(self, filled, brief):
        assert brief["nl"]["legal_disclaimer"] in filled


class TestFillTemplateInvalidLang:
    def test_invalid_lang_raises(self, brief):
        with pytest.raises(ValueError, match="lang must be 'fr' or 'nl'"):
            fill_template("dummy", brief, lang="en")
