# coding: utf-8
"""xlsx-keywords:
  - 02_sitelinks_cnt
  - 02_bids_sl_count_lt
  - 02_description_sl_cnt
  - 02_description_eq_zero
  - 02_navig_incorrect
  - 03_callouts_cnt
  - 03_callouts_detail
  - 03_top_banners_has_uppercase
  - 03_top_banners_zero_callouts
  - 15_banners_desk_w_mob_stat
  - 15_banners_mob_w_desk_stat

Help:
[Quick Links](https://yandex.ru/support/direct/features/quick-links.xml) (Search)
[Callouts](https://yandex.ru/support/direct/features/callout.xml?lang=ru) (Search)
[Описания](https://yandex.ru/support/direct-news/n-2015-10-26.xml) (Search)
"""
from ..review import Recommendation, append_recommendation
from ..const import EXCEL_MAX_ROWS
from ..utils import (
    get_cid,
    get_cid_bid,
    has_uppercase_word,
    filter_by_adtype
)
from .utils import (
    add_cpc_search,
    add_cpc_rsya,
    add_cpc_mobile,
    add_cpc_desktop,
    add_cpc_total,
    add_ctr_search,
    add_ctr_rsya,
    add_ctr_mobile,
    add_ctr_desktop,
    add_ctr_total
)
import pandas as pd


def table_sitelinks_cnt(df, net_type, normalize):
    """02_sitelinks_cnt_[S|R]
    Note:
      net_type : Search | RSYA
    """
    NET_VARIANTS = ("Search", "RSYA")
    assert net_type in NET_VARIANTS, "`net_type` is not in %s" % NET_VARIANTS

    df_chart = filter_by_adtype(df, "TEXT_AD")
    df_chart = (df_chart[["Shows%s" % net_type,
                          "Clicks%s" % net_type,
                          "Cost%s" % net_type,
                          "SitelinksCnt",
                          "DirectBannerID"]]
                .groupby("SitelinksCnt")
                .agg({"Shows%s" % net_type: pd.np.sum,
                      "Clicks%s" % net_type: pd.np.sum,
                      "Cost%s" % net_type: pd.np.sum,
                      "DirectBannerID": lambda x: x.unique().size}))
    if df_chart.shape[0] == 0:
        return None

    if net_type == "Search":
        add_cpc_search(df_chart)
        add_ctr_search(df_chart)

        net_text = u"на поиске"
        sl_text = u"1-7"

    elif net_type == "RSYA":
        add_cpc_rsya(df_chart)
        add_ctr_rsya(df_chart)

        net_text = u"в сетях"
        sl_text = u"1-3"

    net_type_ru = {"Search": u"поиск", "RSYA": u"сети"}
    df_chart.rename(columns={
        "DirectBannerID": u"Кол-во объявлений",
        "Shows%s" % net_type: u"Показы (%s)" % net_type_ru[net_type],
        "Clicks%s" % net_type: u"Клики (%s)" % net_type_ru[net_type],
        "Cost%s" % net_type: u"Расходы (%s)" % net_type_ru[net_type],
        "CPC%s" % net_type: u"CPC (%s)" % net_type_ru[net_type],
        "CTR%s" % net_type: u"CTR (%s)" % net_type_ru[net_type]},
        inplace=True)
    df_chart.index.name = u"Кол-во быстрых ссылок"

    # Теоритический максимум по sitelinks (2019-10))
    max_sl_cnt = max(4, max(df_chart.index)) if net_type == "Search" else 4
    idx = range(max_sl_cnt + 1)
    sum_cols = [
        u"Кол-во объявлений",
        u"Показы (%s)" % net_type_ru[net_type],
        u"Клики (%s)" % net_type_ru[net_type],
        u"Расходы (%s)" % net_type_ru[net_type]
    ]
    max_cols = [u"CPC (%s)" % net_type_ru[net_type], u"CTR (%s)" % net_type_ru[net_type]]

    if normalize:
        df_chart.loc[:, sum_cols] = df_chart.loc[:, sum_cols].apply(lambda x: x / x.sum())
        df_chart.loc[:, max_cols] = df_chart.loc[:, max_cols].apply(lambda x: x / x.max())

        # Пороги из головы экперта, можно крутить
        try:
            sl_none_b, sl_none_s = df_chart.loc[0, [u"Кол-во объявлений", u"Показы (%s)" % net_type_ru[net_type]]]
        except KeyError:
            sl_none_b, sl_none_s = 0., 0.
        if sl_none_b > 0. or sl_none_s > 0.:
            Rec = Recommendation(
                dataframe=df,
                internal_sheet_name="02_sitelinks_cnt_S" if net_type == "Search" else "02_sitelinks_cnt_R",
                title=u"Быстрые ссылки %s" % net_text,
                snippet=u"Нет быстрых ссылок: %.0f%% объявлений (%.0f%% показов) %s"
                        % (sl_none_b * 100., sl_none_s * 100., net_text),
                importance_lvl=2)
            append_recommendation(df, Rec, uniq=False)

        # Пороги из головы экперта, можно крутить
        try:
            if net_type == "Search":
                sl_lt7_b, sl_lt7_s = (df_chart.loc[1:7, [u"Кол-во объявлений", u"Показы (%s)" % net_type_ru[net_type]]]
                                      .sum(axis=0))
            elif net_type == "RSYA":
                sl_lt7_b, sl_lt7_s = (df_chart.loc[1:3, [u"Кол-во объявлений", u"Показы (%s)" % net_type_ru[net_type]]]
                                      .sum(axis=0))
        except KeyError:
            sl_lt7_b, sl_lt7_s = 0., 0.

        if sl_lt7_b > 0. or sl_lt7_s > 0.:
            Rec = Recommendation(
                dataframe=df,
                internal_sheet_name="02_sitelinks_cnt_S" if net_type == "Search" else "02_sitelinks_cnt_R",
                title=u"Быстрые ссылки %s" % net_text,
                snippet=u"Настроено %s ссылок: %.0f%% объявлений (%.0f%% показов) %s"
                        % (sl_text, sl_lt7_b * 100., sl_lt7_s * 100., net_text),
                importance_lvl=2)
            append_recommendation(df, Rec, uniq=False)
    try:
        df_chart = df_chart.loc[idx, sum_cols + max_cols].fillna("")
    except KeyError:
        pass

    if normalize:
        formats = {
            u"Кол-во объявлений": "percent",
            u"Показы (%s)" % net_type_ru[net_type]: "percent",
            u"Клики (%s)" % net_type_ru[net_type]: "percent",
            u"Расходы (%s)" % net_type_ru[net_type]: "percent",
            u"CPC (%s)" % net_type_ru[net_type]: "float",
            u"CTR (%s)" % net_type_ru[net_type]: "float"}
    else:
        formats = {
            u"Кол-во объявлений": "int",
            u"Показы (%s)" % net_type_ru[net_type]: "int",
            u"Клики (%s)" % net_type_ru[net_type]: "int",
            u"Расходы (%s)" % net_type_ru[net_type]: "float",
            u"CPC (%s)" % net_type_ru[net_type]: "float",
            u"CTR (%s)" % net_type_ru[net_type]: "percent"}

    setattr(df_chart, "formats", formats)

    return df_chart


def table_bids_sl_count_lt(df, sort_criteria="ShowsSearch"):
    """02_bids_sl_count_lt"""

    max_sl_cnt = 8 if sort_criteria == "ShowsSearch" else 4
    df_chart = filter_by_adtype(df, "TEXT_AD")
    df_chart = (df_chart[(df_chart.SitelinksCnt < max_sl_cnt) & (df_chart[sort_criteria] > 0)]
                [["ShowsSearch", "ClicksSearch", "CostSearch",
                  "ShowsRSYA", "ClicksRSYA", "CostRSYA",
                  "CampaignID", "CampaignName", "DirectBannerID", "SitelinksCnt"]]
                .groupby(['CampaignID', 'CampaignName', 'DirectBannerID', 'SitelinksCnt'], as_index=False)
                .agg({
                    "ShowsSearch": pd.np.sum,
                    "ClicksSearch": pd.np.sum,
                    "CostSearch": pd.np.sum,
                    "ShowsRSYA": pd.np.sum,
                    "ClicksRSYA": pd.np.sum,
                    "CostRSYA": pd.np.sum})
                .sort_values(sort_criteria, ascending=False)
                .head(EXCEL_MAX_ROWS))

    if df_chart.shape[0] == 0:
        return None
    df_chart['HelperUrlCid'] = df_chart['CampaignID'].apply(get_cid)
    df_chart['HelperUrlBid'] = df_chart.apply(
        lambda row: get_cid_bid(row["CampaignID"], row["DirectBannerID"]),
        axis=1)

    add_cpc_search(df_chart)
    add_ctr_search(df_chart)
    add_cpc_rsya(df_chart)
    add_ctr_rsya(df_chart)

    df_chart.rename(columns={
        "CampaignID": u"Кампания №",
        "CampaignName": u"Название кампании",
        "DirectBannerID": u"Баннер №",
        "SitelinksCnt": u"Кол-во быстрых ссылок",
        "ShowsSearch": u"Показы (поиск)",
        "ClicksSearch": u"Клики (поиск)",
        "CostSearch": u"Расходы (поиск)",
        "CPCSearch": u"CPC (поиск)",
        "CTRSearch": u"CTR (поиск)",
        "ShowsRSYA": u"Показы (сети)",
        "ClicksRSYA": u"Клики (сети)",
        "CostRSYA": u"Расходы (сети)",
        "CPCRSYA": u"CPC (сети)",
        "CTRRSYA": u"CTR (сети)",
        "HelperUrlCid": u"Ссылка на кампанию",
        "HelperUrlBid": u"Ссылка на баннер"},
        inplace=True)

    df_chart = df_chart.loc[:, [u"Кампания №",
                                u"Название кампании",
                                u"Баннер №",
                                u"Кол-во быстрых ссылок",
                                u"Показы (поиск)",
                                u"Клики (поиск)",
                                u"Расходы (поиск)",
                                u"CPC (поиск)",
                                u"CTR (поиск)",
                                u"Показы (сети)",
                                u"Клики (сети)",
                                u"Расходы (сети)",
                                u"CPC (сети)",
                                u"CTR (сети)",
                                u"Ссылка на кампанию",
                                u"Ссылка на баннер"]]

    setattr(df_chart, "formats", {
        u"Кампания №": "string",
        u"Название кампании": "string",
        u"Баннер №": "string",
        u"Кол-во быстрых ссылок": "int",
        u"Показы (поиск)": "int",
        u"Клики (поиск)": "int",
        u"Расходы (поиск)": "float",
        u"CPC (поиск)": "float",
        u"CTR (поиск)": "percent",
        u"Показы (сети)": "int",
        u"Клики (сети)": "int",
        u"Расходы (сети)": "float",
        u"CPC (сети)": "float",
        u"CTR (сети)": "percent",
        u"Ссылка на кампанию": "string",
        u"Ссылка на баннер": "string"})

    return df_chart


def table_description_sl_cnt(df, normalize):
    """02_description_sl_cnt"""
    df_chart = filter_by_adtype(df, "TEXT_AD")
    df_chart = (df_chart[(df_chart.ShowsDesktop > 0) & (df_chart.SitelinksCnt > 0)]
                [["ShowsDesktop", "ClicksDesktop", "CostDesktop", "DescriptionSLCnt", "DirectBannerID"]]
                .groupby("DescriptionSLCnt")
                .agg({"ShowsDesktop": pd.np.sum,
                      "ClicksDesktop": pd.np.sum,
                      "CostDesktop": pd.np.sum,
                      "DirectBannerID": lambda x: x.unique().size})
                )
    if df_chart.shape[0] == 0:
        return None

    add_cpc_desktop(df_chart)
    add_ctr_desktop(df_chart)
    df_chart.rename(columns={
        "DirectBannerID": u"Кол-во объявлений",
        "ShowsDesktop": u"Показы (деск.)",
        "ClicksDesktop": u"Клики (деск.)",
        "CostDesktop": u"Расходы (деск.)",
        "CPCDesktop": u"CPC (деск.)",
        "CTRDesktop": u"CTR (деск.)"},
        inplace=True)
    df_chart.index.name = u"Кол-во описаний к БС"

    max_sl_cnt = max(4, max(df_chart.index))  # Теоритический максимум по sitelinks (2016-09))
    if normalize:
        sum_cols = [u"Кол-во объявлений", u"Показы (деск.)", u"Клики (деск.)", u"Расходы (деск.)"]
        max_cols = [u"CPC (деск.)", u"CTR (деск.)"]
        df_chart.loc[:, sum_cols] = df_chart.loc[:, sum_cols].apply(lambda x: x / x.sum())
        df_chart.loc[:, max_cols] = df_chart.loc[:, max_cols].apply(lambda x: x / x.max())

        # Пороги из головы экперта, можно крутить
        try:
            desc_none_b, desc_none_s = df_chart.loc[0, [u"Кол-во объявлений", u"Показы (деск.)"]]
        except KeyError:
            desc_none_b, desc_none_s = 0., 0.
        if desc_none_b > 0. or desc_none_s > 0.:
            Rec = Recommendation(
                dataframe=df,
                internal_sheet_name="02_description_sl_cnt",
                title=u"Описания к быстрым ссылкам",
                snippet=u"Нет описаний: %.0f%% объявлений (%.0f%% показов)" % (desc_none_b * 100., desc_none_s * 100.),
                importance_lvl=2)
            append_recommendation(df, Rec, uniq=False)

        # Пороги из головы экперта, можно крутить
        try:
            desc_lt7_b, desc_lt7_s = df_chart.loc[1:7, [u"Кол-во объявлений", u"Показы (деск.)"]].sum(axis=0)
        except KeyError:
            desc_lt7_b, desc_lt7_s = 0., 0.
        if desc_lt7_b > 0. or desc_lt7_s > 0.:
            Rec = Recommendation(
                dataframe=df,
                internal_sheet_name="02_description_sl_cnt",
                title=u"Описания к быстрым ссылкам",
                snippet=u"Настроено 1-7 описаний: %.0f%% объявлений (%.0f%% показов)" %
                        (desc_lt7_b * 100., desc_lt7_s * 100.),
                importance_lvl=2)
            append_recommendation(df, Rec, uniq=False)

    df_chart = df_chart.loc[range(max_sl_cnt + 1), [u"Кол-во объявлений",
                                                    u"Показы (деск.)",
                                                    u"Клики (деск.)",
                                                    u"Расходы (деск.)",
                                                    u"CPC (деск.)",
                                                    u"CTR (деск.)"]].fillna("")

    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_chart, "formats", formats)

    return df_chart


def table_top_banners_zero_description(df):
    """02_description_eq_zero"""
    df_chart = filter_by_adtype(df, "TEXT_AD")
    df_chart = df_chart.loc[
        (df_chart.SitelinksCnt > 0) &
        (df_chart.DescriptionSLCnt == 0) &
        (df_chart.ShowsDesktop > 0)].copy()
    if df_chart.shape[0] == 0:
        return None
    df_chart = (df_chart
                .groupby(["CampaignID", "DirectBannerID"], as_index=False)
                .agg({"ShowsDesktop": pd.np.sum,
                      "ClicksDesktop": pd.np.sum,
                      "CostDesktop": pd.np.sum})
                .sort_values("ShowsDesktop", ascending=False)
                .reset_index(drop=True)
                .head(EXCEL_MAX_ROWS)
                .assign(HelperUrlCid=lambda x: x.CampaignID.apply(get_cid),
                        HelperUrlBid=lambda x: x.apply(
                            lambda row: get_cid_bid(row.CampaignID, row.DirectBannerID),
                            axis=1))
                )
    if df_chart.shape[0] == 0:
        return None

    add_cpc_desktop(df_chart)
    add_ctr_desktop(df_chart)
    df_chart.rename(columns={
        "CampaignID": u"Кампания №",
        "DirectBannerID": u"Баннер №",
        "ShowsDesktop": u"Показы (деск.)",
        "ClicksDesktop": u"Клики (деск.)",
        "CostDesktop": u"Расходы (деск.)",
        "CPCDesktop": u"CPC (деск.)",
        "CTRDesktop": u"CTR (деск.)",
        "HelperUrlCid": u"Ссылка на кампанию",
        "HelperUrlBid": u"Ссылка на баннер"},
        inplace=True)

    df_chart = df_chart.loc[:, [u"Кампания №",
                                u"Баннер №",
                                u"Показы (деск.)",
                                u"Клики (деск.)",
                                u"Расходы (деск.)",
                                u"CPC (деск.)",
                                u"CTR (деск.)",
                                u"Ссылка на кампанию",
                                u"Ссылка на баннер"]]

    setattr(df_chart, "formats", {u"Кампания №": "string",
                                  u"Баннер №": "string",
                                  u"Показы (деск.)": "int",
                                  u"Клики (деск.)": "int",
                                  u"Расходы (деск.)": "float",
                                  u"CPC (деск.)": "float",
                                  u"CTR (деск.)": "percent",
                                  u"Ссылка на кампанию": "string",
                                  u"Ссылка на баннер": "string"})

    return df_chart


def table_top_banners_navig_incorrect(df):
    """02_navig_incorrect
    Navig-answer is impossible when SL equal MAX_SL and Descriptions less then MAX_SL
    """
    MAX_SL = 4
    df_chart = filter_by_adtype(df, "TEXT_AD")
    df_chart = (df_chart[
        (df_chart.DescriptionSLCnt < MAX_SL) &
        (df_chart.SitelinksCnt == MAX_SL) &
        (df_chart.ShowsDesktop > 0)
    ][["CampaignID", "DirectBannerID", "PhraseText",
       "ShowsDesktop", "ClicksDesktop", "CostDesktop"]]
        .groupby(["CampaignID", "DirectBannerID", "PhraseText"], as_index=False)
        .agg({"ShowsDesktop": pd.np.sum,
              "ClicksDesktop": pd.np.sum,
              "CostDesktop": pd.np.sum})
        .sort_values("ShowsDesktop", ascending=False)
        .reset_index(drop=True)
        .head(EXCEL_MAX_ROWS))
    if df_chart.shape[0] == 0:
        return None

    add_cpc_desktop(df_chart)
    add_ctr_desktop(df_chart)
    df_chart.rename(columns={
        "CampaignID": u"Кампания №",
        "DirectBannerID": u"Баннер №",
        "ShowsDesktop": u"Показы (деск.)",
        "ClicksDesktop": u"Клики (деск.)",
        "CostDesktop": u"Расходы (деск.)",
        "CPCDesktop": u"CPC (деск.)",
        "CTRDesktop": u"CTR (деск.)"},
        inplace=True)

    df_chart = df_chart.loc[:, [u"Кампания №", u"Баннер №",
                                u"Показы (деск.)", u"Клики (деск.)", u"Расходы (деск.)",
                                u"CPC (деск.)", u"CTR (деск.)"]]

    setattr(df_chart, "formats", {u"Кампания №": "string",
                                  u"Баннер №": "string",
                                  u"Показы (деск.)": "int",
                                  u"Клики (деск.)": "int",
                                  u"Расходы (деск.)": "float",
                                  u"CPC (деск.)": "float",
                                  u"CTR (деск.)": "percent"})

    return df_chart


def table_callouts_cnt(df, net_type, normalize):
    """03_callouts_cnt_[S|R]

    Note:
      net_type : Search | RSYA
    """
    NET_VARIANTS = ("Search", "RSYA")
    assert net_type in NET_VARIANTS, "`net_type` is not in %s" % NET_VARIANTS
    df_chart = filter_by_adtype(df, "TEXT_AD")
    df_chart = df_chart[
        (df_chart["Shows%s" % net_type] > 0) &
        (df_chart.isMobileBanner == False)].copy()  # noqa:E712
    if df_chart.shape[0] == 0:
        return None
    df_chart = (df_chart[["Shows%s" % net_type,
                          "Clicks%s" % net_type,
                          "Cost%s" % net_type,
                          "CalloutsCnt",
                          "DirectBannerID"]]
                .assign(CalloutsCnt=lambda df: df.CalloutsCnt > 0)
                .groupby("CalloutsCnt")
                .agg({"Shows%s" % net_type: pd.np.sum,
                      "Clicks%s" % net_type: pd.np.sum,
                      "Cost%s" % net_type: pd.np.sum,
                      "DirectBannerID": lambda x: x.unique().size}))
    if df_chart.shape[0] == 0:
        return None
    if net_type == "Search":
        add_cpc_search(df_chart)
        add_ctr_search(df_chart)
    if net_type == "RSYA":
        add_cpc_rsya(df_chart)
        add_ctr_rsya(df_chart)
    net_type_ru = {"Search": u"поиск", "RSYA": u"сети"}
    df_chart.rename(columns={
        "DirectBannerID": u"Кол-во объявлений",
        "Shows%s" % net_type: u"Показы (%s)" % net_type_ru[net_type],
        "Clicks%s" % net_type: u"Клики (%s)" % net_type_ru[net_type],
        "Cost%s" % net_type: u"Расходы (%s)" % net_type_ru[net_type],
        "CPC%s" % net_type: u"CPC (%s)" % net_type_ru[net_type],
        "CTR%s" % net_type: u"CTR (%s)" % net_type_ru[net_type]},
        inplace=True)
    df_chart.rename(index={
        0: u"Без уточнений",
        1: u"Есть уточнения"},
        inplace=True)
    df_chart.index.name = u"Уточнения"

    if normalize:
        sum_col = [u"Кол-во объявлений",
                   u"Показы (%s)" % net_type_ru[net_type],
                   u"Клики (%s)" % net_type_ru[net_type],
                   u"Расходы (%s)" % net_type_ru[net_type]]
        max_col = [u"CPC (%s)" % net_type_ru[net_type],
                   u"CTR (%s)" % net_type_ru[net_type]]
        df_chart.loc[:, sum_col] = df_chart.loc[:, sum_col].apply(lambda x: x / x.sum())
        df_chart.loc[:, max_col] = df_chart.loc[:, max_col].apply(lambda x: x / x.max())

        # Все лимиты из головы эксперта, можно двигать
        try:
            callouts_none_b, callouts_none_s = df_chart.loc[
                u"Без уточнений",
                [u"Кол-во объявлений", u"Показы (%s)" % net_type_ru[net_type]]]
        except KeyError:
            callouts_none_b, callouts_none_s = 0, 0
        if callouts_none_b > 0.1 or callouts_none_s > 0.1:
            Rec = Recommendation(
                dataframe=df,
                internal_sheet_name="03_callouts_cnt_%s" % net_type[0],  # S или R
                title=u"Уточнения",
                snippet=u"Уточнения не настроены в %.0f%% объявлений для %.0f%% показов" %
                        (callouts_none_b * 100., callouts_none_s * 100.),
                importance_lvl=2)

            append_recommendation(df, Rec)

    df_chart = df_chart.loc[[u"Без уточнений",
                             u"Есть уточнения"],
                            [u"Кол-во объявлений",
                             u"Показы (%s)" % net_type_ru[net_type],
                             u"Клики (%s)" % net_type_ru[net_type],
                             u"Расходы (%s)" % net_type_ru[net_type],
                             u"CPC (%s)" % net_type_ru[net_type],
                             u"CTR (%s)" % net_type_ru[net_type]]
                            ].fillna("")

    if normalize:
        formats = {
            u"Кол-во объявлений": "percent",
            u"Показы (%s)" % net_type_ru[net_type]: "percent",
            u"Клики (%s)" % net_type_ru[net_type]: "percent",
            u"Расходы (%s)" % net_type_ru[net_type]: "percent",
            u"CPC (%s)" % net_type_ru[net_type]: "float",
            u"CTR (%s)" % net_type_ru[net_type]: "float"}
    else:
        formats = {
            u"Кол-во объявлений": "int",
            u"Показы (%s)" % net_type_ru[net_type]: "int",
            u"Клики (%s)" % net_type_ru[net_type]: "int",
            u"Расходы (%s)" % net_type_ru[net_type]: "float",
            u"CPC (%s)" % net_type_ru[net_type]: "float",
            u"CTR (%s)" % net_type_ru[net_type]: "percent"}

    setattr(df_chart, "formats", formats)

    return df_chart


def table_callouts_detail(df, normalize, net_type):
    """03_callouts_detail_[S|R]

    Note:
      net_type : Search | RSYA
    """
    NET_VARIANTS = ("Search", "RSYA")
    assert net_type in NET_VARIANTS, "`net_type` is not in %s" % NET_VARIANTS
    df_chart = filter_by_adtype(df, "TEXT_AD")
    df_chart = df_chart[
        (df_chart["Shows%s" % net_type] > 0) &
        (df_chart.isMobileBanner == False)
        ].copy()  # noqa:E712
    if df_chart.shape[0] == 0:
        return None
    df_chart = (df_chart[["Shows%s" % net_type,
                          "Clicks%s" % net_type,
                          "Cost%s" % net_type,
                          "CalloutsCnt",
                          "DirectBannerID"]]
                .groupby("CalloutsCnt")
                .agg({"Shows%s" % net_type: pd.np.sum,
                      "Clicks%s" % net_type: pd.np.sum,
                      "Cost%s" % net_type: pd.np.sum,
                      "DirectBannerID": lambda x: x.unique().size}))
    if df_chart.shape[0] == 0:
        return None
    if net_type == "Search":
        add_cpc_search(df_chart)
        add_ctr_search(df_chart)
    if net_type == "RSYA":
        add_cpc_rsya(df_chart)
        add_ctr_rsya(df_chart)
    net_type_ru = {"Search": u"поиск", "RSYA": u"сети"}
    df_chart.rename(columns={
        "DirectBannerID": u"Кол-во объявлений",
        "Shows%s" % net_type: u"Показы (%s)" % net_type_ru[net_type],
        "Clicks%s" % net_type: u"Клики (%s)" % net_type_ru[net_type],
        "Cost%s" % net_type: u"Расходы (%s)" % net_type_ru[net_type],
        "CPC%s" % net_type: u"CPC (%s)" % net_type_ru[net_type],
        "CTR%s" % net_type: u"CTR (%s)" % net_type_ru[net_type]},
        inplace=True)
    df_chart.index.name = u"Кол-во уточнений"

    if normalize:
        sum_col = [u"Кол-во объявлений",
                   u"Показы (%s)" % net_type_ru[net_type],
                   u"Клики (%s)" % net_type_ru[net_type],
                   u"Расходы (%s)" % net_type_ru[net_type]]
        max_col = [u"CPC (%s)" % net_type_ru[net_type],
                   u"CTR (%s)" % net_type_ru[net_type]]
        df_chart.loc[:, sum_col] = df_chart.loc[:, sum_col].apply(lambda x: x / x.sum())
        df_chart.loc[:, max_col] = df_chart.loc[:, max_col].apply(lambda x: x / x.max())

        # Лимиты из головы эксперта, можно двигать при необходимости
        callouts_lt3_b, callouts_lt3_s = df_chart.loc[:2, [u"Кол-во объявлений", u"Показы (%s)" % net_type_ru[net_type]]].sum(axis=0)
        if callouts_lt3_b > 0. or callouts_lt3_s > 0.:
            if net_type == 'Search':
                net_text = u"на поиске"
            else:
                net_text = u"в сетях"
            Rec = Recommendation(
                dataframe=df,
                internal_sheet_name="03_callouts_detail_%s" % net_type[0],  # S or R
                title=u"Уточнения",
                snippet=u"Меньше трёх уточнений у %.0f%% объявлений (%.0f%% показов) %s" % (callouts_lt3_b * 100., callouts_lt3_s * 100., net_text),
                importance_lvl=2)

            append_recommendation(df, Rec)

    df_chart = df_chart.loc[:, [u"Кол-во объявлений",
                                u"Показы (%s)" % net_type_ru[net_type],
                                u"Клики (%s)" % net_type_ru[net_type],
                                u"Расходы (%s)" % net_type_ru[net_type],
                                u"CPC (%s)" % net_type_ru[net_type],
                                u"CTR (%s)" % net_type_ru[net_type]]]

    if normalize:
        formats = {
            u"Кол-во объявлений": "percent",
            u"Показы (%s)" % net_type_ru[net_type]: "percent",
            u"Клики (%s)" % net_type_ru[net_type]: "percent",
            u"Расходы (%s)" % net_type_ru[net_type]: "percent",
            u"CPC (%s)" % net_type_ru[net_type]: "float",
            u"CTR (%s)" % net_type_ru[net_type]: "float"}
    else:
        formats = {
            u"Кол-во объявлений": "int",
            u"Показы (%s)" % net_type_ru[net_type]: "int",
            u"Клики (%s)" % net_type_ru[net_type]: "int",
            u"Расходы (%s)" % net_type_ru[net_type]: "float",
            u"CPC (%s)" % net_type_ru[net_type]: "float",
            u"CTR (%s)" % net_type_ru[net_type]: "percent"}

    setattr(df_chart, "formats", formats)

    return df_chart


def table_top_banners_zero_callouts(df, sort_criteria):
    """03_top_banners_zero_callouts

    Note:
      sort_criteria : ShowsSearch | ShowsRSYA
    """
    CRITERIA_VARIANTS = ("ShowsSearch", "ShowsRSYA")
    assert sort_criteria in CRITERIA_VARIANTS, \
           "`sort_criteria` is not in %s" % CRITERIA_VARIANTS  # noqa: E127 (over-indented)
    df_chart = filter_by_adtype(df, "TEXT_AD")
    df_chart = df_chart.loc[
        (df_chart[sort_criteria] > 0) &
        (df_chart.isMobileBanner == False) &  # у мобильных объявлений нет уточнений
        (df_chart.CalloutsCnt == 0)
        ].copy()  # noqa:E712
    if df_chart.shape[0] == 0:
        return None
    df_chart = (df_chart
                .groupby(["CampaignID", "CampaignName", "DirectBannerID"], as_index=False)
                .agg({
                    "ShowsSearch": pd.np.sum,
                    "ClicksSearch": pd.np.sum,
                    "CostSearch": pd.np.sum,
                    "ShowsRSYA": pd.np.sum,
                    "ClicksRSYA": pd.np.sum,
                    "CostRSYA": pd.np.sum})
                .sort_values(sort_criteria, ascending=False)
                .reset_index(drop=True)
                .head(EXCEL_MAX_ROWS)
                .assign(HelperUrlCid=lambda x: x.CampaignID.apply(get_cid),
                        HelperUrlBid=lambda x: x.apply(
                            lambda row: get_cid_bid(row.CampaignID, row.DirectBannerID),
                            axis=1)))
    if df_chart.shape[0] == 0:
        return None

    add_cpc_search(df_chart)
    add_ctr_search(df_chart)
    add_cpc_rsya(df_chart)
    add_ctr_rsya(df_chart)

    df_chart.rename(columns={
        "CampaignID": u"Кампания №",
        "CampaignName": u"Название кампании",
        "DirectBannerID": u"Баннер №",
        "ShowsSearch": u"Показы (поиск)",
        "ClicksSearch": u"Клики (поиск)",
        "CostSearch": u"Расходы (поиск)",
        "CPCSearch": u"CPC (поиск)",
        "CTRSearch": u"CTR (поиск)",
        "ShowsRSYA": u"Показы (сети)",
        "ClicksRSYA": u"Клики (сети)",
        "CostRSYA": u"Расходы (сети)",
        "CPCRSYA": u"CPC (сети)",
        "CTRRSYA": u"CTR (сети)",
        "HelperUrlCid": u"Ссылка на кампанию",
        "HelperUrlBid": u"Ссылка на баннер"},
        inplace=True)

    df_chart = df_chart.loc[:, [u"Кампания №",
                                u"Название кампании",
                                u"Баннер №",
                                u"Показы (поиск)",
                                u"Клики (поиск)",
                                u"Расходы (поиск)",
                                u"CPC (поиск)",
                                u"CTR (поиск)",
                                u"Показы (сети)",
                                u"Клики (сети)",
                                u"Расходы (сети)",
                                u"CPC (сети)",
                                u"CTR (сети)",
                                u"Ссылка на кампанию",
                                u"Ссылка на баннер"]]

    setattr(df_chart, "formats", {
        u"Кампания №": "string",
        u"Название кампании": "string",
        u"Баннер №": "string",
        u"Показы (поиск)": "int",
        u"Клики (поиск)": "int",
        u"Расходы (поиск)": "float",
        u"CPC (поиск)": "float",
        u"CTR (поиск)": "percent",
        u"Показы (сети)": "int",
        u"Клики (сети)": "int",
        u"Расходы (сети)": "float",
        u"CPC (сети)": "float",
        u"CTR (сети)": "percent",
        u"Ссылка на кампанию": "string",
        u"Ссылка на баннер": "string"})

    return df_chart


def table_top_banners_has_uppercase(df):
    """03_top_banners_has_uppercase"""

    df_chart = filter_by_adtype(df, "TEXT_AD")
    df_chart = df_chart[(df_chart["Shows"] > 0)][
        ["DirectBannerID", "Title", "Body", "Shows", "Clicks", "Cost"]].copy()
    if df_chart.shape[0] == 0:
        return None
    has_uppercase = (df_chart["Title"].apply(has_uppercase_word) | df_chart["Body"].apply(has_uppercase_word))
    df_chart = (df_chart[has_uppercase]
                .groupby(["DirectBannerID", "Title", "Body"], as_index=False)
                .agg({
                    "Shows": pd.np.sum,
                    "Clicks": pd.np.sum,
                    "Cost": pd.np.sum})
                .sort_values("Shows", ascending=False)
                .head(EXCEL_MAX_ROWS))

    add_cpc_total(df_chart)
    add_ctr_total(df_chart)

    if df_chart.shape[0] == 0:
        return None
    else:
        df_chart = df_chart.loc[:, ["DirectBannerID", "Title", "Body",
                                    "Shows", "Clicks", "Cost", "CPC", "CTR"]]

        setattr(df_chart, "formats", {"DirectBannerID": "string",
                                      "Title": "string",
                                      "Body": "string",
                                      "Shows": "int",
                                      "Clicks": "int",
                                      "Cost": "float",
                                      "CPC": "float",
                                      "CTR": "percent"})

        return df_chart


def table_top_banners_desktop_type_incorrect(df):
    """15_banners_desk_w_mob_stat"""

    df_chart = filter_by_adtype(df, "TEXT_AD")
    df_chart = (df_chart[(df_chart.isMobileBanner == False) &
                         (df_chart.ShowsMobile > 0)]  # noqa:712 (comparison to False)
                .groupby(["CampaignID", "CampaignName", "GroupID", "DirectBannerID", "Title", "Body"], as_index=False)
                .agg({"ShowsMobile": pd.np.sum,
                      "ClicksMobile": pd.np.sum,
                      "CostMobile": pd.np.sum})
                .sort_values("ShowsMobile", ascending=False)
                .reset_index(drop=True)
                .head(EXCEL_MAX_ROWS))

    if df_chart.shape[0] == 0:
        return None

    add_cpc_mobile(df_chart)
    add_ctr_mobile(df_chart)

    df_chart.rename(columns={
        "CampaignID": u"Кампания №",
        "CampaignName": u"Название кампании",
        "GroupID": u"Группа №",
        "DirectBannerID": u"Баннер №",
        "Title": u"Заголовок",
        "Body": u"Объявление",
        "ShowsMobile": u"Показы (моб.)",
        "ClicksMobile": u"Клики (моб.)",
        "CostMobile": u"Расходы (моб.)",
        "CPCMobile": u"CPC (моб.)",
        "CTRMobile": u"CTR (моб.)"},
        inplace=True)

    df_chart = df_chart.loc[:, [u"Кампания №",
                                u"Название кампании",
                                u"Группа №",
                                u"Баннер №",
                                u"Заголовок",
                                u"Объявление",
                                u"Показы (моб.)",
                                u"Клики (моб.)",
                                u"Расходы (моб.)",
                                u"CPC (моб.)",
                                u"CTR (моб.)"]]

    setattr(df_chart, "formats", {
        u"Кампания №": "string",
        u"Название кампании": "string",
        u"Группа №": "string",
        u"Баннер №": "string",
        u"Заголовок": "string",
        u"Объявление": "string",
        u"Показы (моб.)": "int",
        u"Клики (моб.)": "int",
        u"Расходы (моб.)": "float",
        u"CPC (моб.)": "float",
        u"CTR (моб.)": "percent"})

    # Все пороги из головы эксперта, можно менять
    shows_total = filter_by_adtype(df, "TEXT_AD").Shows.sum() * 1.
    shows_mob = df_chart.loc[:, u"Показы (моб.)"].sum() * 1.
    share_of_mobile_shows = shows_mob / shows_total * 1.
    if share_of_mobile_shows > 0.1:
        Rec = Recommendation(
            dataframe=df,
            internal_sheet_name="15_banners_desk_w_mob_stat",
            title=u"Мобильные объявления",
            snippet=u"Не менее %.0f%% показов десктопных объявлений случилось на мобильных устройствах" % (share_of_mobile_shows * 100.),
            importance_lvl=2)

        append_recommendation(df, Rec)

    return df_chart


def table_top_banners_mobile_type_incorrect(df):
    """15_banners_mob_w_desk_stat"""

    df_chart = filter_by_adtype(df, "TEXT_AD")
    df_chart = (df_chart[df_chart.isMobileBanner & (df_chart.ShowsDesktop > 0)]
                .groupby(["CampaignID", "CampaignName", "GroupID", "DirectBannerID", "Title", "Body"], as_index=False)
                .agg({"ShowsDesktop": pd.np.sum,
                      "ClicksDesktop": pd.np.sum,
                      "CostDesktop": pd.np.sum})
                .sort_values("ShowsDesktop", ascending=False)
                .reset_index(drop=True)
                .head(EXCEL_MAX_ROWS))

    if df_chart.shape[0] == 0:
        return None

    add_cpc_desktop(df_chart)
    add_ctr_desktop(df_chart)

    df_chart.rename(columns={
        "CampaignID": u"Кампания №",
        "CampaignName": u"Название кампании",
        "GroupID": u"Группа №",
        "DirectBannerID": u"Баннер №",
        "Title": u"Заголовок",
        "Body": u"Объявление",
        "ShowsDesktop": u"Показы (не моб.)",
        "ClicksDesktop": u"Клики (не моб.)",
        "CostDesktop": u"Расходы (не моб.)",
        "CPCDesktop": u"CPC (не моб.)",
        "CTRDesktop": u"CTR (не моб.)"},
        inplace=True)

    df_chart = df_chart.loc[:, [u"Кампания №",
                                u"Название кампании",
                                u"Группа №",
                                u"Баннер №",
                                u"Заголовок",
                                u"Объявление",
                                u"Показы (не моб.)",
                                u"Клики (не моб.)",
                                u"Расходы (не моб.)",
                                u"CPC (не моб.)",
                                u"CTR (не моб.)"]]

    setattr(df_chart, "formats", {
        u"Кампания №": "string",
        u"Название кампании": "string",
        u"Группа №": "string",
        u"Баннер №": "string",
        u"Заголовок": "string",
        u"Объявление": "string",
        u"Показы (не моб.)": "int",
        u"Клики (не моб.)": "int",
        u"Расходы (не моб.)": "float",
        u"CPC (не моб.)": "float",
        u"CTR (не моб.)": "percent"})

    return df_chart
