"""
Component smoke tests — Story 2.2 (AC: 2).

Tests render each Jinja2 macro component with minimal valid context using
render_template_string + app.test_request_context('/').  A Jinja2 UndefinedError
would raise an exception (not return a 200); these tests confirm all required
template variables are satisfied by the macro's parameter list.
"""
import pytest
from flask import render_template_string
from flask_wtf import FlaskForm
from wtforms import StringField


# ---------------------------------------------------------------------------
# Minimal WTForms form used by form_row tests
# ---------------------------------------------------------------------------
class _MinimalForm(FlaskForm):
    """Minimal form with one StringField for testing form_row component."""
    username = StringField('Username')


# ---------------------------------------------------------------------------
# alert.html
# ---------------------------------------------------------------------------
class TestAlertComponent:
    def test_alert_success_renders(self, app):
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/alert.html' import render_alert %}"
                "{{ render_alert(type='success', message='Operation successful') }}"
            )
        assert 'Operation successful' in html
        assert '<div' in html

    def test_alert_error_renders(self, app):
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/alert.html' import render_alert %}"
                "{{ render_alert(type='error', message='Something went wrong') }}"
            )
        assert 'Something went wrong' in html
        assert 'alert' in html  # role="alert" for errors

    def test_alert_warning_renders(self, app):
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/alert.html' import render_alert %}"
                "{{ render_alert(type='warning', message='Watch out') }}"
            )
        assert 'Watch out' in html

    def test_alert_info_renders(self, app):
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/alert.html' import render_alert %}"
                "{{ render_alert(type='info', message='FYI note') }}"
            )
        assert 'FYI note' in html


# ---------------------------------------------------------------------------
# empty_state.html
# ---------------------------------------------------------------------------
class TestEmptyStateComponent:
    def test_empty_state_minimal_renders(self, app):
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/empty_state.html' import render_empty_state %}"
                "{{ render_empty_state(title='Nothing here', description='No items found') }}"
            )
        assert 'Nothing here' in html
        assert 'No items found' in html

    def test_empty_state_with_cta_renders(self, app):
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/empty_state.html' import render_empty_state %}"
                "{{ render_empty_state("
                "   title='No transactions',"
                "   description='Add one to start',"
                "   cta_text='Add Transaction',"
                "   cta_url='/transactions/create'"
                ") }}"
            )
        assert 'Add Transaction' in html
        assert '/transactions/create' in html

    def test_empty_state_no_cta_when_only_text_given(self, app):
        """CTA link NOT rendered when cta_url is absent."""
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/empty_state.html' import render_empty_state %}"
                "{{ render_empty_state(title='Empty', description='Nothing', cta_text='Click') }}"
            )
        assert 'href' not in html


# ---------------------------------------------------------------------------
# page_header.html
# ---------------------------------------------------------------------------
class TestPageHeaderComponent:
    def test_page_header_title_only(self, app):
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/page_header.html' import render_page_header %}"
                "{{ render_page_header(title='My Page') }}"
            )
        assert 'My Page' in html
        assert '<h1' in html

    def test_page_header_with_subtitle_and_action(self, app):
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/page_header.html' import render_page_header %}"
                "{{ render_page_header("
                "   title='Transactions',"
                "   subtitle='Your full history',"
                "   action_text='Add Transaction',"
                "   action_url='/transactions/create'"
                ") }}"
            )
        assert 'Transactions' in html
        assert 'Your full history' in html
        assert 'Add Transaction' in html
        assert '/transactions/create' in html

    def test_page_header_no_action_when_url_absent(self, app):
        """Action link NOT rendered when action_url is absent."""
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/page_header.html' import render_page_header %}"
                "{{ render_page_header(title='Test', action_text='Do It') }}"
            )
        assert 'Do It' not in html


# ---------------------------------------------------------------------------
# stat_card.html
# ---------------------------------------------------------------------------
class TestStatCardComponent:
    def test_stat_card_minimal_renders(self, app):
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/stat_card.html' import render_stat_card %}"
                "{{ render_stat_card(label='Total Spent', value='$1,234.56') }}"
            )
        assert 'Total Spent' in html
        assert '$1,234.56' in html

    def test_stat_card_with_delta_renders(self, app):
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/stat_card.html' import render_stat_card %}"
                "{{ render_stat_card("
                "   label='Monthly Spend',"
                "   value='$500',"
                "   delta='+$50',"
                "   delta_type='negative'"
                ") }}"
            )
        assert 'Monthly Spend' in html
        assert '+$50' in html


# ---------------------------------------------------------------------------
# pagination.html
# ---------------------------------------------------------------------------
class TestPaginationComponent:
    def test_pagination_page1_shows_next_not_prev(self, app):
        """Page 1 of 10 — next link is an <a>, prev is a disabled span."""
        with app.test_request_context('/'):
            url_fn = lambda p: f'/transactions/?page={p}'
            html = render_template_string(
                "{% from 'components/pagination.html' import render_pagination %}"
                "{{ render_pagination(page=1, total=100, per_page=10, url_for_page=url_fn) }}",
                url_fn=url_fn,
            )
        assert 'page=2' in html        # next link present
        assert '<a' in html            # at least one <a> (Next)
        # Previous should be a disabled span, not an <a>
        assert 'aria-disabled' in html

    def test_pagination_middle_page_shows_both_links(self, app):
        """Page 3 of 10 — both previous and next are <a> tags."""
        with app.test_request_context('/'):
            url_fn = lambda p: f'/transactions/?page={p}'
            html = render_template_string(
                "{% from 'components/pagination.html' import render_pagination %}"
                "{{ render_pagination(page=3, total=100, per_page=10, url_for_page=url_fn) }}",
                url_fn=url_fn,
            )
        assert 'page=2' in html
        assert 'page=4' in html

    def test_pagination_last_page_shows_prev_not_next(self, app):
        """Last page — prev link present, next is disabled span."""
        with app.test_request_context('/'):
            url_fn = lambda p: f'/transactions/?page={p}'
            html = render_template_string(
                "{% from 'components/pagination.html' import render_pagination %}"
                "{{ render_pagination(page=10, total=100, per_page=10, url_for_page=url_fn) }}",
                url_fn=url_fn,
            )
        assert 'page=9' in html
        assert 'page=11' not in html


# ---------------------------------------------------------------------------
# confirm_modal.html
# ---------------------------------------------------------------------------
class TestConfirmModalComponent:
    def test_confirm_modal_renders_structure(self, app):
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/confirm_modal.html' import render_confirm_modal %}"
                "{{ render_confirm_modal("
                "   modal_id='del-modal',"
                "   title='Delete Item',"
                "   message='Are you sure?',"
                "   confirm_url='/delete/1'"
                ") }}"
            )
        assert 'del-modal' in html
        assert 'Delete Item' in html
        assert 'Are you sure?' in html
        assert '/delete/1' in html
        assert 'role="dialog"' in html

    def test_confirm_trigger_renders(self, app):
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/confirm_modal.html' import render_confirm_trigger %}"
                "{{ render_confirm_trigger(modal_id='del-modal', label='Delete') }}"
            )
        assert 'del-modal' in html
        assert 'Delete' in html
        assert 'data-confirm-target' in html


# ---------------------------------------------------------------------------
# form_row.html
# ---------------------------------------------------------------------------
class TestFormRowComponent:
    def test_form_row_renders_label_and_input(self, app):
        with app.test_request_context('/'):
            form = _MinimalForm()
            html = render_template_string(
                "{% from 'components/form_row.html' import render_field %}"
                "{{ render_field(field=form.username) }}",
                form=form,
            )
        assert 'Username' in html
        assert 'input' in html

    def test_form_row_custom_label_text(self, app):
        with app.test_request_context('/'):
            form = _MinimalForm()
            html = render_template_string(
                "{% from 'components/form_row.html' import render_field %}"
                "{{ render_field(field=form.username, label_text='Your Name') }}",
                form=form,
            )
        assert 'Your Name' in html

    def test_form_row_errors_render(self, app):
        """When a field has errors, they appear in the rendered output."""
        with app.test_request_context('/'):
            form = _MinimalForm()
            form.username.errors = ['This field is required.']
            html = render_template_string(
                "{% from 'components/form_row.html' import render_field %}"
                "{{ render_field(field=form.username) }}",
                form=form,
            )
        assert 'This field is required.' in html


# ---------------------------------------------------------------------------
# progress_bar.html
# ---------------------------------------------------------------------------
class TestProgressBarComponent:
    def test_progress_bar_safe_state(self, app):
        """value=50 → auto-computed state = safe (< 70)."""
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/progress_bar.html' import render_progress_bar %}"
                "{{ render_progress_bar(value=50, label='Groceries') }}"
            )
        assert 'Groceries' in html
        assert '50' in html
        assert 'safe' in html

    def test_progress_bar_warning_state(self, app):
        """value=85 → auto-computed state = warning (70–89)."""
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/progress_bar.html' import render_progress_bar %}"
                "{{ render_progress_bar(value=85, label='Dining') }}"
            )
        assert 'warning' in html

    def test_progress_bar_danger_state(self, app):
        """value=95 → auto-computed state = danger (≥ 90)."""
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/progress_bar.html' import render_progress_bar %}"
                "{{ render_progress_bar(value=95, label='Entertainment') }}"
            )
        assert 'danger' in html

    def test_progress_bar_explicit_state_overrides(self, app):
        """Explicit state parameter overrides auto-computation."""
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/progress_bar.html' import render_progress_bar %}"
                "{{ render_progress_bar(value=40, label='Test', state='danger') }}"
            )
        assert 'danger' in html

    def test_progress_bar_has_aria_attributes(self, app):
        with app.test_request_context('/'):
            html = render_template_string(
                "{% from 'components/progress_bar.html' import render_progress_bar %}"
                "{{ render_progress_bar(value=60) }}"
            )
        assert 'role="progressbar"' in html
        assert 'aria-valuenow' in html
