"""What a knowledge base article's topic decides about seeing the article.

An article's topic is an Application. When that application is retired the
article describes something no longer in service, and showing it beside live
documentation reads as though it were current - so it does not show at all.

`isactive` is the ONLY property of an application that decides this. In
particular `ishidden`, which governs whether an application appears on the tiles
page, says nothing about whether it can be the subject of an article.
"""

import pytest

from shopdb.core.models import Application
from plugins.knowledgebase.models import KnowledgeBase


@pytest.fixture
def library(db):
    """One application of each interesting shape, with an article each."""
    applications = {
        'live': Application(appname='Live App', isinstallable=True,
                            ishidden=False, isactive=True),
        'notinstallable': Application(appname='Manual App', isinstallable=False,
                                      ishidden=False, isactive=True),
        'hidden': Application(appname='Hidden App', isinstallable=False,
                              ishidden=True, isactive=True),
        'retired': Application(appname='Retired App', isinstallable=True,
                               ishidden=False, isactive=False),
    }
    db.session.add_all(applications.values())
    db.session.flush()

    articles = {
        'live': KnowledgeBase(shortdescription='Live runbook', linkurl='u',
                              appid=applications['live'].appid, clicks=3,
                              isactive=True),
        'hidden': KnowledgeBase(shortdescription='Hidden runbook', linkurl='u',
                                appid=applications['hidden'].appid, clicks=2,
                                isactive=True),
        'retired': KnowledgeBase(shortdescription='Retired runbook', linkurl='u',
                                 appid=applications['retired'].appid, clicks=5,
                                 isactive=True),
        'topicless': KnowledgeBase(shortdescription='General note', linkurl='u',
                                   appid=None, clicks=1, isactive=True),
    }
    db.session.add_all(articles.values())
    db.session.commit()
    return {'applications': applications, 'articles': articles}


def titles(client, url='/api/knowledgebase'):
    return sorted(row['shortdescription']
                  for row in client.get(url).get_json()['data'])


def test_an_article_about_a_retired_application_does_not_show(client, library):
    assert 'Retired runbook' not in titles(client)


def test_an_article_with_no_topic_still_shows(client, library):
    """A null topic is not a retired one. Not every article is about an
    application, and those must not be collateral damage."""
    assert 'General note' in titles(client)


def test_a_hidden_application_is_still_a_valid_topic(client, library):
    """ishidden keeps an application off the tiles page. It says nothing about
    documentation, and isactive is the only filter that applies here."""
    assert 'Hidden runbook' in titles(client)


def test_searching_a_retired_application_name_finds_nothing(client, library):
    """The topic search matched on application name without checking isactive,
    which surfaced retired articles and printed the retired application as their
    subject."""
    assert titles(client, '/api/knowledgebase?search=Retired App') == []


def test_searching_a_title_does_not_resurrect_a_retired_article(client, library):
    """Hiding it from the list and finding it by title would be no rule at all."""
    found = titles(client, '/api/knowledgebase?search=runbook')
    assert 'Retired runbook' not in found
    assert 'Live runbook' in found


def test_the_counts_agree_with_the_list(client, library):
    """A total that includes articles nobody can see is a total nobody can
    reconcile against the page."""
    visible = titles(client)
    stats = client.get('/api/knowledgebase/stats').get_json()['data']
    total = stats.get('total_articles', stats.get('totalarticles'))
    clicks = stats.get('total_clicks', stats.get('totalclicks'))
    assert total == len(visible) == 3
    # 3 + 2 + 1 from the live, hidden-topic and topicless articles; the retired
    # article's 5 clicks are excluded along with the article.
    assert clicks == 6


def test_the_topic_list_offers_every_active_application(client, library):
    """What the article form's topic dropdown fetches. Installable or not,
    hidden or not - only retired is excluded."""
    offered = sorted(row['appname'] for row in client.get(
        '/api/applications?perpage=100&showhidden=true').get_json()['data'])
    assert offered == ['Hidden App', 'Live App', 'Manual App']
    assert 'Retired App' not in offered
