"""
Tests for template rendering and structure

Tests cover:
- Template inheritance
- Microformats2 markup
- HTML structure and validity
- Template variables and context
- Flash message rendering
- Error templates
"""

import pytest
from starpunk import create_app
from starpunk.notes import create_note


@pytest.fixture
def app(tmp_path):
    """Create test application"""
    test_data_dir = tmp_path / "data"
    test_data_dir.mkdir(parents=True, exist_ok=True)

    test_config = {
        "TESTING": True,
        "DATABASE_PATH": test_data_dir / "starpunk.db",
        "DATA_PATH": test_data_dir,
        "NOTES_PATH": test_data_dir / "notes",
        "SESSION_SECRET": "test-secret",
        "SITE_URL": "http://localhost:5000",
        "ADMIN_ME": "https://test.example.com",
        "DEV_MODE": False,
        "SITE_NAME": "Test StarPunk",
        "VERSION": "0.5.0",
    }
    app = create_app(config=test_config)
    yield app


@pytest.fixture
def client(app):
    """Test client"""
    return app.test_client()


class TestBaseTemplate:
    """Test base.html template"""

    def test_base_has_doctype(self, client):
        """Test base template has HTML5 doctype"""
        response = client.get("/")
        assert response.status_code == 200
        assert response.data.startswith(b"<!DOCTYPE html>")

    def test_base_has_charset(self, client):
        """Test base template has charset meta tag"""
        response = client.get("/")
        assert response.status_code == 200
        assert b'charset="UTF-8"' in response.data or b"charset=UTF-8" in response.data

    def test_base_has_viewport(self, client):
        """Test base template has viewport meta tag"""
        response = client.get("/")
        assert response.status_code == 200
        assert b"viewport" in response.data
        assert b"width=device-width" in response.data

    def test_base_has_title(self, client):
        """Test base template has title"""
        response = client.get("/")
        assert response.status_code == 200
        assert b"<title>" in response.data
        assert b"StarPunk" in response.data

    def test_base_has_stylesheet(self, client):
        """Test base template links to stylesheet"""
        response = client.get("/")
        assert response.status_code == 200
        assert b"<link" in response.data
        assert b"stylesheet" in response.data
        assert b"style.css" in response.data

    def test_base_has_rss_link(self, client):
        """Test base template has RSS feed link"""
        response = client.get("/")
        assert response.status_code == 200
        assert b"application/rss+xml" in response.data or b"feed.xml" in response.data

    def test_base_has_header(self, client):
        """Test base template has header"""
        response = client.get("/")
        assert response.status_code == 200
        assert b"<header" in response.data

    def test_base_has_main(self, client):
        """Test base template has main content area"""
        response = client.get("/")
        assert response.status_code == 200
        assert b"<main" in response.data

    def test_base_has_footer(self, client):
        """Test base template has footer"""
        response = client.get("/")
        assert response.status_code == 200
        assert b"<footer" in response.data

    def test_base_footer_has_version(self, client):
        """Test footer shows version number"""
        response = client.get("/")
        assert response.status_code == 200
        assert b"0.5.0" in response.data

    def test_base_has_navigation(self, client):
        """Test base has navigation"""
        response = client.get("/")
        assert response.status_code == 200
        assert b"<nav" in response.data or b'href="/"' in response.data


class TestHomepageTemplate:
    """Test index.html template"""

    def test_homepage_has_h_feed(self, client):
        """Test homepage has h-feed microformat"""
        with client.application.test_request_context():
            create_note("# Test\n\nContent", published=True)

        response = client.get("/")
        assert response.status_code == 200
        assert b"h-feed" in response.data

    def test_homepage_notes_have_h_entry(self, client):
        """Test notes on homepage have h-entry"""
        with client.application.test_request_context():
            create_note("# Test\n\nContent", published=True)

        response = client.get("/")
        assert response.status_code == 200
        assert b"h-entry" in response.data

    def test_homepage_empty_state(self, client):
        """Test homepage shows message when no notes"""
        response = client.get("/")
        assert response.status_code == 200
        # Should have some indication of empty state
        data_lower = response.data.lower()
        assert (
            b"no notes" in data_lower
            or b"welcome" in data_lower
            or b"get started" in data_lower
        )


class TestNoteTemplate:
    """Test note.html template"""

    def test_note_has_h_entry(self, client):
        """Test note page has h-entry microformat"""
        with client.application.test_request_context():
            note = create_note("# Test Note\n\nContent here.", published=True)

        response = client.get(f"/note/{note.slug}")
        assert response.status_code == 200
        assert b"h-entry" in response.data

    def test_note_has_e_content(self, client):
        """Test note has e-content for content"""
        with client.application.test_request_context():
            note = create_note("# Test Note\n\nContent here.", published=True)

        response = client.get(f"/note/{note.slug}")
        assert response.status_code == 200
        assert b"e-content" in response.data

    def test_note_has_dt_published(self, client):
        """Test note has dt-published for date"""
        with client.application.test_request_context():
            note = create_note("# Test Note\n\nContent here.", published=True)

        response = client.get(f"/note/{note.slug}")
        assert response.status_code == 200
        assert b"dt-published" in response.data

    def test_note_has_u_url(self, client):
        """Test note has u-url for permalink"""
        with client.application.test_request_context():
            note = create_note("# Test Note\n\nContent here.", published=True)

        response = client.get(f"/note/{note.slug}")
        assert response.status_code == 200
        assert b"u-url" in response.data

    def test_note_renders_markdown(self, client):
        """Test note content is rendered as HTML"""
        with client.application.test_request_context():
            note = create_note("# Heading\n\n**Bold** text.", published=True)

        response = client.get(f"/note/{note.slug}")
        assert response.status_code == 200
        # Should have HTML heading
        assert b"<h1" in response.data
        # Should have bold
        assert b"<strong>" in response.data or b"<b>" in response.data


class TestAdminTemplates:
    """Test admin templates"""

    def test_login_template_has_form(self, client):
        """Test login page has form"""
        response = client.get("/auth/login")
        assert response.status_code == 200
        assert b"<form" in response.data

    def test_login_has_me_input(self, client):
        """Test login form has 'me' URL input"""
        response = client.get("/auth/login")
        assert response.status_code == 200
        assert b'name="me"' in response.data or b'id="me"' in response.data

    def test_login_has_submit_button(self, client):
        """Test login form has submit button"""
        response = client.get("/auth/login")
        assert response.status_code == 200
        assert b'type="submit"' in response.data or b"<button" in response.data

    def test_dashboard_extends_admin_base(self, client):
        """Test dashboard uses admin base template"""
        from starpunk.auth import create_session

        with client.application.test_request_context():
            token = create_session("https://test.example.com")

        client.set_cookie("starpunk_session", token)
        response = client.get("/admin/")
        assert response.status_code == 200
        # Should have admin-specific elements
        assert b"Dashboard" in response.data or b"Admin" in response.data

    def test_new_note_form_has_textarea(self, client):
        """Test new note form has textarea"""
        from starpunk.auth import create_session

        with client.application.test_request_context():
            token = create_session("https://test.example.com")

        client.set_cookie("starpunk_session", token)
        response = client.get("/admin/new")
        assert response.status_code == 200
        assert b"<textarea" in response.data

    def test_new_note_form_has_published_checkbox(self, client):
        """Test new note form has published checkbox"""
        from starpunk.auth import create_session

        with client.application.test_request_context():
            token = create_session("https://test.example.com")

        client.set_cookie("starpunk_session", token)
        response = client.get("/admin/new")
        assert response.status_code == 200
        assert b'type="checkbox"' in response.data

    def test_edit_form_prefilled(self, client):
        """Test edit form is prefilled with content"""
        from starpunk.auth import create_session

        with client.application.test_request_context():
            token = create_session("https://test.example.com")
            note = create_note("# Edit Test\n\nContent.", published=True)

        client.set_cookie("starpunk_session", token)
        response = client.get(f"/admin/edit/{note.id}")
        assert response.status_code == 200
        assert b"Edit Test" in response.data


class TestFlashMessages:
    """Test flash message rendering"""

    def test_flash_message_success(self, client):
        """Test success flash message renders"""
        with client.session_transaction() as session:
            session["_flashes"] = [("success", "Operation successful")]

        response = client.get("/")
        assert response.status_code == 200
        assert b"Operation successful" in response.data
        assert b"flash" in response.data or b"success" in response.data

    def test_flash_message_error(self, client):
        """Test error flash message renders"""
        with client.session_transaction() as session:
            session["_flashes"] = [("error", "An error occurred")]

        response = client.get("/")
        assert response.status_code == 200
        assert b"An error occurred" in response.data
        assert b"flash" in response.data or b"error" in response.data

    def test_flash_message_warning(self, client):
        """Test warning flash message renders"""
        with client.session_transaction() as session:
            session["_flashes"] = [("warning", "Be careful")]

        response = client.get("/")
        assert response.status_code == 200
        assert b"Be careful" in response.data

    def test_multiple_flash_messages(self, client):
        """Test multiple flash messages render"""
        with client.session_transaction() as session:
            session["_flashes"] = [
                ("success", "First message"),
                ("error", "Second message"),
            ]

        response = client.get("/")
        assert response.status_code == 200
        assert b"First message" in response.data
        assert b"Second message" in response.data


class TestErrorTemplates:
    """Test error page templates"""

    def test_404_template(self, client):
        """Test 404 error page"""
        response = client.get("/nonexistent")
        assert response.status_code == 404
        assert b"404" in response.data or b"Not Found" in response.data

    def test_404_has_home_link(self, client):
        """Test 404 page has link to homepage"""
        response = client.get("/nonexistent")
        assert response.status_code == 404
        assert b'href="/"' in response.data


class TestDevModeIndicator:
    """Test dev mode warning in templates"""

    def test_dev_mode_warning_shown(self, tmp_path):
        """Test dev mode warning appears when enabled"""
        test_data_dir = tmp_path / "dev_data"
        test_data_dir.mkdir(parents=True, exist_ok=True)

        test_config = {
            "TESTING": True,
            "DATABASE_PATH": test_data_dir / "starpunk.db",
            "DATA_PATH": test_data_dir,
            "NOTES_PATH": test_data_dir / "notes",
            "SESSION_SECRET": "test-secret",
            "SITE_URL": "http://localhost:5000",
            "DEV_MODE": True,
            "DEV_ADMIN_ME": "https://dev.example.com",
        }
        app = create_app(config=test_config)

        client = app.test_client()
        response = client.get("/")
        assert response.status_code == 200
        assert b"DEVELOPMENT MODE" in response.data or b"DEV MODE" in response.data

    def test_dev_mode_warning_not_shown(self, client):
        """Test dev mode warning not shown in production"""
        response = client.get("/")
        assert response.status_code == 200
        assert b"DEVELOPMENT MODE" not in response.data


class TestTemplateVariables:
    """Test template variables are available"""

    def test_config_available(self, client):
        """Test config is available in templates"""
        response = client.get("/")
        assert response.status_code == 200
        # VERSION should be rendered
        assert b"0.5.0" in response.data

    def test_site_name_available(self, client):
        """Test SITE_NAME is available"""
        response = client.get("/")
        assert response.status_code == 200
        # Should have site name in title or header
        assert b"<title>" in response.data

    def test_url_for_works(self, client):
        """Test url_for generates correct URLs"""
        response = client.get("/")
        assert response.status_code == 200
        # Should have URLs like /admin, /admin/login, etc.
        assert b"href=" in response.data


# IndieAuth client discovery tests (h-app microformats) removed in Phase 1
# The h-app markup was only needed when StarPunk acted as an IndieAuth client
# for Micropub authorization. With the authorization server removed, these
# discovery microformats are no longer needed.
# See: docs/architecture/indieauth-removal-phases.md
