import json

from flask import Blueprint, render_template, url_for, redirect
from flask_login import current_user, login_required
from app.models import Publisher
from operator import attrgetter
from app.constants import Role

bp = Blueprint('publisher', __name__)


@bp.route('/analytics')
@login_required
def analytics():
    """
    Fetches publisher relevant information to render on analytics page

    :return: Publisher analytics view
    """
    if current_user.role == Role.USER:
        return redirect(url_for('dashboard'))

    publisher = current_user.publisher
    revenue = get_percent_of_total_revenue(publisher)
    payment_percent = get_payment_percentages(publisher)
    articles = get_top_articles(publisher)
    data = {'name': publisher.name, 'revenue': revenue, 'payment_percent': payment_percent,
            'articles': articles}
    data = json.dumps(data)
    return render_template('index.html', data=data)


def get_top_articles(publisher):
    """
    Fetches MAX_ARTICLES most popular articles of given publisher

    :param publisher: Publisher object

    :return: list of article objects

    """
    MAX_ARTICLES = 4
    articles = [{'name': i.url, 'hits': i.hits} for i in sorted(publisher.articles, reverse=True,
                                                                key=attrgetter('hits'))[:MAX_ARTICLES] if i.hits]
    while len(articles) < MAX_ARTICLES:
        articles.append({'name': None, 'hits': 0})
    return articles


def get_payment_percentages(publisher):
    """
    This calculates percentages of different payment types used to access given publisher articles

    :param publisher: Publisher object

    :return: dictionary with keys: monthly, package and single. Each contains rounded percentage

    """
    payment_percent = {'monthly': publisher.monthly_pay, 'package': publisher.package_pay,
                       'single': publisher.single_pay}
    all_together = sum(payment_percent.values()) or 1
    return {k: round(v / all_together, 1) for k, v in payment_percent.items()}


def get_percent_of_total_revenue(publisher):
    """
    This calculates total % of revenue this publisher has generated

    :param publisher: Publisher object

    :return: % of total revenue generated by given publisher, value between 0-1

    """

    from app import db
    from sqlalchemy.sql import func
    qry = db.session.query(func.sum(Publisher.revenue).label('total_revenue'))
    for res in qry.all():
        print(res)
    total = Publisher.query.filter_by(name='All').first()
    total_monthly_rev = total.revenue - total.single_pay - total.package_pay
    # total monthly revenue is needed to calculate how much revenue one monthly access has generated
    per_read_monthly_rev = total_monthly_rev / total.monthly_pay if total.monthly_pay else 0
    publisher_monthly_pay_rev = per_read_monthly_rev * publisher.monthly_pay
    pub_rev = publisher.single_pay + publisher.package_pay + publisher_monthly_pay_rev
    return round(pub_rev / total.revenue, 1) if total.revenue > 0 else 0
