import os
import unittest
from shutil import rmtree
from tempfile import mkdtemp

from pelican import Pelican
from pelican.settings import read_settings
from pelican.tests.support import LoggedTestCase, mute

CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
CONTENT_DIR = os.path.join(CURRENT_DIR, "simple_content")


class TestTemplateInheritance(LoggedTestCase):
    def setUp(self):
        super().setUp()
        self.temp_output = mkdtemp(prefix="pelican_test_output.")
        self.temp_theme = mkdtemp(prefix="pelican_test_theme.")
        self.temp_cache = mkdtemp(prefix="pelican_test_cache.")

        # Create test theme directory structure
        os.makedirs(os.path.join(self.temp_theme, "templates"), exist_ok=True)

        # Create base.html template that inherits from simple theme
        template_content = """{% extends "!simple/base.html" %}

{% block head %}
{{ super() }}
    <link rel="stylesheet" type="text/css" href="{{ SITEURL }}/theme/css/style.css" />
{% endblock %}

{% block footer %}
    <p>New footer</p>
{% endblock %}
"""

        with open(os.path.join(self.temp_theme, "templates", "base.html"), "w") as f:
            f.write(template_content)

    def tearDown(self):
        """Clean up temporary directories and files"""
        for path in [self.temp_output, self.temp_theme, self.temp_cache]:
            if os.path.exists(path):
                rmtree(path)

        super().tearDown()

    def test_simple_theme(self):
        """Test that when a template is missing from our theme, Pelican falls back
        to using the template from the simple theme."""

        settings = read_settings(
            path=None,
            override={
                "THEME": "simple",
                "PATH": CONTENT_DIR,
                "OUTPUT_PATH": self.temp_output,
                "CACHE_PATH": self.temp_cache,
                "SITEURL": "http://example.com",
                # Disable unnecessary output that might cause failures
                "ARCHIVES_SAVE_AS": "",
                "CATEGORIES_SAVE_AS": "",
                "TAGS_SAVE_AS": "",
                "AUTHOR_SAVE_AS": "",
                "AUTHORS_SAVE_AS": "",
            },
        )

        pelican = Pelican(settings=settings)
        mute(True)(pelican.run)()

        output_file = os.path.join(self.temp_output, "test-md-file.html")
        self.assertTrue(os.path.exists(output_file))

        with open(output_file) as f:
            content = f.read()

        # Verify file content is present
        self.assertIn("Test md File", content)

        # Verify simple theme content is present
        self.assertIn('<html lang="en">', content)
        self.assertIn("Proudly powered by", content)

        # Verify our custom theme additions are NOT present
        # (since we should be using the simple theme's template directly)
        self.assertNotIn(
            '<link rel="stylesheet" type="text/css" href="http://example.com/theme/css/style.css"',
            content,
        )

    def test_theme_inheritance(self):
        """Test that theme inheritance works correctly"""
        settings = read_settings(
            path=None,
            override={
                "THEME": self.temp_theme,
                "PATH": CONTENT_DIR,
                "OUTPUT_PATH": self.temp_output,
                "CACHE_PATH": self.temp_cache,
                "SITEURL": "http://example.com",
                # Disable unnecessary output that might cause failures
                "ARCHIVES_SAVE_AS": "",
                "CATEGORIES_SAVE_AS": "",
                "TAGS_SAVE_AS": "",
                "AUTHOR_SAVE_AS": "",
                "AUTHORS_SAVE_AS": "",
            },
        )

        pelican = Pelican(settings=settings)
        # Generate the site with muted output
        mute(True)(pelican.run)()

        # Check the output file
        output_file = os.path.join(self.temp_output, "test-md-file.html")
        self.assertTrue(os.path.exists(output_file))

        with open(output_file) as f:
            content = f.read()

        # Verify inheritance worked
        self.assertIn('<html lang="en">', content)  # From simple theme

        # Verify super() maintained original head content
        self.assertIn('<meta charset="utf-8"', content)

        # Verify our changes were included
        self.assertIn(
            '<link rel="stylesheet" type="text/css" href="http://example.com/theme/css/style.css"',
            content,
        )
        self.assertNotIn("Proudly powered by", content)
        self.assertIn("New footer", content)

    def test_disabled_categories_no_links(self):
        """When CATEGORY_SAVE_AS is empty, articles without an explicit
        category should not get a default category or show category links."""

        # Create an article without a Category metadata line
        content_dir = mkdtemp(prefix="pelican_test_content.")
        with open(os.path.join(content_dir, "no_category.md"), "w") as f:
            f.write(
                "Title: No Category Article\n"
                "Date: 2024-01-01\n\n"
                "Article without a category.\n"
            )

        try:
            settings = read_settings(
                path=None,
                override={
                    "THEME": "simple",
                    "PATH": content_dir,
                    "OUTPUT_PATH": self.temp_output,
                    "CACHE_PATH": self.temp_cache,
                    "SITEURL": "http://example.com",
                    "CATEGORY_SAVE_AS": None,
                    "CATEGORY_URL": None,
                    "CATEGORIES_SAVE_AS": None,
                },
            )

            pelican = Pelican(settings=settings)
            mute(True)(pelican.run)()

            with open(os.path.join(self.temp_output, "no-category-article.html")) as f:
                content = f.read()

            self.assertNotIn("Category:", content)
        finally:
            rmtree(content_dir)

    def test_category_and_tag_feed_titles_use_slug(self):
        """Feed link titles on category/tag pages should have unique titles."""

        settings = read_settings(
            path=None,
            override={
                "THEME": "simple",
                "PATH": CONTENT_DIR,
                "OUTPUT_PATH": self.temp_output,
                "CACHE_PATH": self.temp_cache,
                "SITEURL": "http://example.com",
                "SITENAME": "My Site",
                "CATEGORY_FEED_ATOM": "feeds/{slug}.atom.xml",
                "TAG_FEED_ATOM": "feeds/tag-{slug}.atom.xml",
            },
        )

        pelican = Pelican(settings=settings)
        mute(True)(pelican.run)()

        cat_file = os.path.join(self.temp_output, "category", "test.html")
        with open(cat_file) as f:
            cat_content = f.read()
        self.assertIn('title="Test Category Atom Feed"', cat_content)

        tag_file = os.path.join(self.temp_output, "tag", "foo.html")
        with open(tag_file) as f:
            tag_content = f.read()
        self.assertIn('title="Foo Tag Atom Feed"', tag_content)

    def test_simple_theme_no_css_link(self):
        """The simple theme has no static/css/ directory, so the CSS_FILE
        link should not be rendered."""

        settings = read_settings(
            path=None,
            override={
                "THEME": "simple",
                "PATH": CONTENT_DIR,
                "OUTPUT_PATH": self.temp_output,
                "CACHE_PATH": self.temp_cache,
                "SITEURL": "http://example.com",
            },
        )

        pelican = Pelican(settings=settings)
        mute(True)(pelican.run)()

        with open(os.path.join(self.temp_output, "test-md-file.html")) as f:
            content = f.read()

        self.assertNotIn("/theme/css/main.css", content)

    def test_child_theme_with_css_file(self):
        """A child theme that provides static/css/main.css should have the
        CSS_FILE link rendered."""

        # Add a CSS file to the child theme
        css_dir = os.path.join(self.temp_theme, "static", "css")
        os.makedirs(css_dir)
        with open(os.path.join(css_dir, "main.css"), "w") as f:
            f.write("body { margin: 0; }")

        settings = read_settings(
            path=None,
            override={
                "THEME": self.temp_theme,
                "PATH": CONTENT_DIR,
                "OUTPUT_PATH": self.temp_output,
                "CACHE_PATH": self.temp_cache,
                "SITEURL": "http://example.com",
            },
        )

        pelican = Pelican(settings=settings)
        mute(True)(pelican.run)()

        with open(os.path.join(self.temp_output, "test-md-file.html")) as f:
            content = f.read()

        self.assertIn(
            'href="http://example.com/theme/css/main.css"',
            content,
        )

    def test_css_only_theme(self):
        """A theme with only a static/css/main.css file (no templates)
        should work by falling back to the simple theme's templates."""

        css_only_theme = mkdtemp(prefix="pelican_test_css_only_theme.")
        css_dir = os.path.join(css_only_theme, "static", "css")
        os.makedirs(css_dir)
        with open(os.path.join(css_dir, "main.css"), "w") as f:
            f.write("body { margin: 0; }")

        try:
            settings = read_settings(
                path=None,
                override={
                    "THEME": css_only_theme,
                    "PATH": CONTENT_DIR,
                    "OUTPUT_PATH": self.temp_output,
                    "CACHE_PATH": self.temp_cache,
                    "SITEURL": "http://example.com",
                },
            )

            pelican = Pelican(settings=settings)
            mute(True)(pelican.run)()

            with open(os.path.join(self.temp_output, "test-md-file.html")) as f:
                content = f.read()

            self.assertIn(
                'href="http://example.com/theme/css/main.css"',
                content,
            )
            self.assertIn("Proudly powered by", content)
        finally:
            rmtree(css_only_theme)


if __name__ == "__main__":
    unittest.main()
