# coding: utf-8
"""xlsx-keywords:
  - 01_operators_usage
  - 01_top_{type_of_restriction}
"""
from ..review import Recommendation, append_recommendation
from ..xlsx_chart.chart import Chart, chart_add_series
from ..const import EXCEL_MAX_ROWS
from ..utils import (
    get_group_url,
    get_phrase_info
)
from ..xlsx_keywords.utils import (
    add_cpc_total,
    add_ctr_total,
)
import pandas as pd


def _table_flatten_by_phrases_info(df):

    if df.shape[0] == 0:
        return df

    df_export = df.loc[:, [
        "LoginName",
        "CampaignID",
        "GroupName",
        "GroupID",
        "DirectPhraseID",
        "PhraseText",
        "Shows",
        "Clicks",
        "Cost"]].copy()

    df_export = df_export.assign(PhraseInfo=lambda xf: xf.PhraseText.apply(get_phrase_info))
    df_export = (df_export.assign(
        FixedPhrase=lambda xf: xf.PhraseInfo.apply(lambda x: x.fixed_phrase),
        FixedForm=lambda xf: xf.PhraseInfo.apply(lambda x: x.fixed_form),
        FixedStopwords=lambda xf: xf.PhraseInfo.apply(lambda x: x.fixed_stopwords),
        FixedOrder=lambda xf: xf.PhraseInfo.apply(lambda x: x.fixed_order))
        .drop(["PhraseInfo"], axis=1)
    )
    df_export = (pd.concat(
        [
            df_export.query("FixedPhrase").assign(PhraseInfo="FixedPhrase"),
            df_export.query("FixedForm").assign(PhraseInfo="FixedForm"),
            df_export.query("FixedStopwords").assign(PhraseInfo="FixedStopwords"),
            df_export.query("FixedOrder").assign(PhraseInfo="FixedOrder"),
            df_export.query("not (FixedPhrase or FixedForm or FixedStopwords or FixedOrder)")
                     .assign(PhraseInfo="FixedNothing")],
        axis=0,
        ignore_index=True)
        .drop(["FixedPhrase", "FixedForm", "FixedStopwords", "FixedOrder"], axis=1)
    )

    return df_export


def table_operators_usage(df, normalize):
    "01_operators_usage"

    df_export = _table_flatten_by_phrases_info(df)
    df_export = df_export[df_export.Shows > 0]
    if df_export.shape[0] == 0:
        return None

    df_export = (df_export.groupby(
        "PhraseInfo")
        .agg({
            "Shows": sum,
            "Clicks": sum,
            "Cost": sum,
            "DirectPhraseID": lambda xs: xs.unique().size})
        .rename(columns={
            "DirectPhraseID": u"Кол-во фраз",
            "Shows": u"Показы",
            "Clicks": u"Клики",
            "Cost": u"Расходы"
        })
        .rename(index={
            "FixedPhrase": u"Кол-во слов",
            "FixedForm": u"Словоформа",
            "FixedStopwords": u"Стоп-слова",
            "FixedOrder": u"Порядок слов",
            "FixedNothing": u"Без ограничений"}))
    df_export.index.name = u"Тип ограничения"

    df_export[u"CPC"] = df_export[u"Расходы"] / df_export[u"Клики"]
    df_export[u"CTR"] = df_export[u"Клики"] / df_export[u"Показы"]

    if normalize:
        total_shows = df.Shows.sum() * 1.0
        total_clicks = df.Clicks.sum() * 1.0
        total_cost = df.Cost.sum() * 1.0
        total_phrases = df.DirectPhraseID.unique().size * 1.0

        fns = {
            u"Кол-во фраз": lambda xf: xf.loc[:, u"Кол-во фраз"] / total_phrases,
            u"Показы": lambda xf: xf.loc[:, u"Показы"] / total_shows,
            u"Клики": lambda xf: xf.loc[:, u"Клики"] / total_clicks,
            u"Расходы": lambda xf: xf.loc[:, u"Расходы"] / total_cost,
        }
        df_export = df_export.assign(**fns)

        cols_max = [u"CPC", u"CTR"]
        df_export.loc[:, cols_max] = df_export.loc[:, cols_max].apply(lambda x: x / x.max())

    df_export = df_export.loc[
        [u"Кол-во слов",
         u"Словоформа",
         u"Стоп-слова",
         u"Без ограничений",
         u"Порядок слов"],
        [u"Кол-во фраз",
         u"Показы",
         u"Клики",
         u"Расходы",
         u"CPC",
         u"CTR"]].fillna('')

    if normalize:
        # Минимальный порог из головы эксперта, можно менять
        has_error = (
            (df_export
             .drop(u'Без ограничений', axis=0)
             .applymap(lambda x: 0 if x == '' else x)
             .loc[
                 [u"Кол-во слов", u"Словоформа", u"Порядок слов"],
                 [u"Кол-во фраз", u"Показы"]] > 0.05)
            .any(axis=1)
            .max())

        if has_error:
            Rec = Recommendation(
                dataframe=df,
                internal_sheet_name="01_operators_usage",
                title=u"Спецоператоры",
                snippet=u"Возможно излишнее использование спецоператоров",
                importance_lvl=2)
            append_recommendation(df, Rec)

    if normalize:
        formats = {
            u"Кол-во фраз": "percent",
            u"Показы": "percent",
            u"Клики": "percent",
            u"Расходы": "percent",
            u"CPC": "float",
            u"CTR": "float"}
    else:
        formats = {
            u"Кол-во фраз": "int",
            u"Показы": "int",
            u"Клики": "int",
            u"Расходы": "float",
            u"CPC": "float",
            u"CTR": "percent"}

    setattr(df_export, "formats", formats)

    return df_export


def plot_operators_usage(writer, sheet_name, cell, df):
    """
    (ExcelWriter, str, DataFrame) -> ExcelWriter
    01_operators_usage
    """

    sheet = writer.book.get_worksheet_by_name(sheet_name)

    # Create chart
    chart = Chart(writer.book, "bar", "percent_stacked", u'Использованные ограничения')

    # Add data series.
    chart_add_series(chart, 0, {
        'values': u"='%s'!B2:E2" % sheet_name,
        "categories": u"='%s'!B1:E1" % sheet_name,
        "name": u"='%s'!A2" % sheet_name})
    chart_add_series(chart, 1, {
        'values': u"='%s'!B3:E3" % sheet_name,
        "categories": u"='%s'!B1:E1" % sheet_name,
        "name": u"='%s'!A3" % sheet_name})
    chart_add_series(chart, 2, {
        'values': u"='%s'!B4:E4" % sheet_name,
        "categories": u"='%s'!B1:E1" % sheet_name,
        "name": u"='%s'!A4" % sheet_name})
    chart_add_series(chart, 3, {
        'values': u"='%s'!B5:E5" % sheet_name,
        "categories": u"='%s'!B1:E1" % sheet_name,
        "name": u"='%s'!A5" % sheet_name})
    chart_add_series(chart, 4, {
        'values': u"='%s'!B6:E6" % sheet_name,
        "categories": u"='%s'!B1:E1" % sheet_name,
        "name": u"='%s'!A6" % sheet_name})

    # Insert the chart into the worksheet.
    sheet.insert_chart(cell, chart)

    return writer


def plot_operators_usage_p(writer, sheet_name, cell, df):
    """
    (ExcelWriter, str, DataFrame) -> ExcelWriter
    01_operators_usage
    """

    sheet = writer.book.get_worksheet_by_name(sheet_name)

    # Create chart
    chart = Chart(writer.book, "bar", "percent_stacked", u'Использованные ограничения')

    # Add data series.
    label_fmt = {'value': True, 'num_format': '0%'}
    chart_add_series(chart, 0, {
        'values': u"='%s'!K2:N2" % sheet_name,
        'data_labels': label_fmt,
        "categories": u"='%s'!K1:N1" % sheet_name,
        "name": u"='%s'!J2" % sheet_name})
    chart_add_series(chart, 1, {
        'values': u"='%s'!K3:N3" % sheet_name,
        'data_labels': label_fmt,
        "categories": u"='%s'!K1:N1" % sheet_name,
        "name": u"='%s'!J3" % sheet_name})
    chart_add_series(chart, 2, {
        'values': u"='%s'!K4:N4" % sheet_name,
        'data_labels': label_fmt,
        "categories": u"='%s'!K1:N1" % sheet_name,
        "name": u"='%s'!J4" % sheet_name})
    chart_add_series(chart, 3, {
        'values': u"='%s'!K5:N5" % sheet_name,
        'data_labels': label_fmt,
        "categories": u"='%s'!K1:N1" % sheet_name,
        "name": u"='%s'!J5" % sheet_name})
    chart_add_series(chart, 4, {
        'values': u"='%s'!K6:N6" % sheet_name,
        'data_labels': label_fmt,
        "categories": u"='%s'!K1:N1" % sheet_name,
        "name": u"='%s'!J6" % sheet_name})

    # Insert the chart into the worksheet.
    sheet.insert_chart(cell, chart)

    return writer


def table_top_restricted_phrases(df, type_of_restriction):
    "01_top_{type_of_restriction}"
    known_restrictions = ("FixedPhrase", "FixedForm", "FixedOrder", "FixedStopwords", "FixedNothing")
    assert type_of_restriction in known_restrictions, "unknown `type_of_restriction`: %s" % type_of_restriction

    df_export = _table_flatten_by_phrases_info(df)
    df_export = df_export.query("Shows > 0 and PhraseInfo == @type_of_restriction")
    if df_export.shape[0] == 0:
        return None

    df_export = (df_export.groupby(
        ["GroupID", "PhraseText"], as_index=False)
        .agg({
            "LoginName": lambda xs: xs.iloc[0],  # kind of some/any
            "CampaignID": lambda xs: xs.iloc[0],
            "GroupName": lambda xs: xs.iloc[0],
            "Shows": sum,
            "Clicks": sum,
            "Cost": sum})
        .sort_values("Shows", ascending=False)
        .head(EXCEL_MAX_ROWS)
        .assign(
        HelperURL=lambda xf: xf.apply(lambda x: get_group_url(x["CampaignID"], x["GroupID"]), axis=1))
    )

    add_cpc_total(df_export)
    add_ctr_total(df_export)

    df_export = df_export.loc[:, [
        "LoginName",
        "CampaignID",
        "GroupName",
        "GroupID",
        "PhraseText",
        "Shows",
        "Clicks",
        "Cost",
        "CPC",
        "CTR",
        "HelperURL"]].fillna('')

    df_export.rename(columns={
        "LoginName": u"Логин",
        "CampaignID": u"Кампания №",
        "GroupName": u"Название группы",
        "GroupID": u"Группа №",
        "PhraseText": u"Ключевая фраза",
        "Shows": u"Показы",
        "Clicks": u"Клики",
        "Cost": u"Расходы",
        "CPC": u"CPC",
        "CTR": u"CTR",
        "HelperURL": u"Ссылка на группу"},
        inplace=True)

    setattr(df_export, "formats", {u"Логин": "string",
                                   u"Кампания №": "string",
                                   u"Название группы": "string",
                                   u"Группа №": "string",
                                   u"Ключевая фраза": "string",
                                   u"Показы": "int",
                                   u"Клики": "int",
                                   u"Расходы": "float",
                                   u"CPC": "float",
                                   u"CTR": "percent",
                                   u"Ссылка на группу": "string"})

    return df_export
