# coding: utf-8
"""xlsx-keywords:
  - 01_top_non-bolded_phrases
  - 01_operators_usage
  - 01_top_{type_of_restriction}
  - 11_top_phrases_lost_clicks
  - 12_top_phrases_strange_pos
  - 13_top_cpc_phrases
"""
from ..xlsx_chart.chart import Chart, chart_add_series
from ..const import EXCEL_MAX_ROWS
from ..utils import (
    get_cid_bid,
    get_group_url,
    phrase_process,
    filter_by_adtype,
    get_phrase_info
)
from .utils import (
    add_cpc_search,
    add_ctr_search,
    add_cpc_total,
    add_ctr_total,
    add_ctr_spec,
    add_ctr_other
)
import pandas as pd


def table_top_nonbolded_phrases(df):
    """01_top_non-bolded_phrases"""

    df_chart = filter_by_adtype(df, "TEXT_AD")
    df_chart = df_chart[[
        "BoldedWordsCnt",
        "WordsCnt",
        "ShowsSearch",
        "ClicksSearch",
        "CostSearch",
        "PhraseText",
        "NonBoldedWords",
        "Title",
        "Body",
        "DirectBannerID",
        "CampaignID",
        "CampaignName"]].copy()

    df_chart = df_chart.loc[
        (df_chart.WordsCnt != 0) &
        (df_chart.ShowsSearch > 0) &
        (df_chart.BoldedWordsCnt < df_chart.WordsCnt) &
        (df_chart.NonBoldedWords != ""), :]

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

    df_chart["PhraseBoldShare"] = df_chart.BoldedWordsCnt / df_chart.WordsCnt
    df_chart.drop(["BoldedWordsCnt", "WordsCnt"], axis=1, inplace=True)
    df_chart['ShowsSearchNonBolded'] = ((1 - df_chart['PhraseBoldShare']) * df_chart['ShowsSearch']).astype(int)
    df_chart.sort_values("ShowsSearchNonBolded", ascending=False, inplace=True)
    df_chart['HelperURL'] = df_chart.apply(
        lambda row: get_cid_bid(row["CampaignID"], row["DirectBannerID"]),
        axis=1)

    add_cpc_search(df_chart)
    add_ctr_search(df_chart)

    df_chart = df_chart[[
        "CampaignID", "CampaignName", "DirectBannerID", "Title", "Body",
        "PhraseText", "NonBoldedWords", "ShowsSearch",
        "ClicksSearch", "CostSearch", "CPCSearch", "CTRSearch", "HelperURL"]].fillna(value='')

    df_chart.rename(columns={
        "CampaignID": u"Кампания №",
        "CampaignName": u"Название кампании",
        "DirectBannerID": u"Баннер №",
        "Title": u"Заголовок",
        "Body": u"Объявление",
        "PhraseText": u"Ключевая фраза",
        "NonBoldedWords": u"Неподсвеченное слово",
        "ShowsSearch": u"Показы (поиск)",
        "ClicksSearch": u"Клики (поиск)",
        "CostSearch": u"Расходы (поиск)",
        "CPCSearch": u"CPC (поиск)",
        "CTRSearch": u"CTR (поиск)",
        "HelperURL": u"Ссылка на баннер"},
        inplace=True)

    setattr(df_chart, "formats", {u"Кампания №": "string",
                                  u"Название кампании": "string",
                                  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_chart


def _table_flatten_by_phrases_info(df):

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

    df_export = df.loc[:, [
        "LoginName",
        "CampaignID",
        "GroupName",
        "GroupID",
        "BSPhraseID",
        "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,
            "BSPhraseID": lambda xs: xs.unique().size})
        .rename(columns={
            "BSPhraseID": 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:
        cols_sum = [u"Кол-во фраз", u"Показы", u"Клики", u"Расходы"]
        df_export.loc[:, cols_sum] = df_export.loc[:, cols_sum].apply(lambda x: x / x.sum())
        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:
        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


def table_top_phrases_lost_clicks(df):
    """11_top_phrases_lost_clicks"""

    df_chart = filter_by_adtype(df, "TEXT_AD")
    df_chart = df_chart.loc[
        (df_chart.ClicksSpec > 0) &
        (df_chart.ClicksSpec <= df_chart.ShowsSpec)].copy()

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

    df_chart = (df_chart.assign(
        PhraseText=lambda x: x.PhraseText.apply(phrase_process))
        [["CampaignID", "DirectBannerID", "PhraseText",
          "ShowsSpec", "ClicksSpec", "ShowsOther", "ClicksOther"]]
        .groupby(["CampaignID", "DirectBannerID", "PhraseText"], as_index=False)
        .agg({"ShowsSpec": pd.np.sum,
              "ClicksSpec": pd.np.sum,
              "ShowsOther": pd.np.sum,
              "ClicksOther": pd.np.sum})
        .assign(MaxClicks=lambda x: x.ClicksSpec / x.ShowsSpec * (x.ShowsOther + x.ShowsSpec))
        .assign(LostClicks=lambda x: x.ClicksSpec / x.ShowsSpec * x.ShowsOther - x.ClicksOther)
        .sort_values("LostClicks", ascending=False)
        .head(EXCEL_MAX_ROWS))

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

    add_ctr_spec(df_chart)
    add_ctr_other(df_chart)

    df_chart['HelperUrlBid'] = df_chart.apply(
        lambda row: get_cid_bid(row["CampaignID"], row["DirectBannerID"]),
        axis=1)

    df_chart.rename(columns={
        "CampaignID": u"Кампания №",
        "DirectBannerID": u"Баннер №",
        "PhraseText": u"Ключевая фраза",
        "HelperUrlBid": u"Ссылка на баннер",
        "ShowsSpec": u"Показы (спец.)",
        "ClicksSpec": u"Клики (спец.)",
        "CTRSpec": u"CTR (спец.)",
        "ShowsOther": u"Показы (юж./пр. блок)",
        "ClicksOther": u"Клики (юж./пр. блок)",
        "CTROther": u"CTR (юж./пр. блок)",
        "MaxClicks": u"Максимум кликов",
        "LostClicks": u"Упущенные клики"},
        inplace=True)

    df_chart = df_chart.loc[:, [u"Кампания №", u"Баннер №", u"Ключевая фраза", u"Ссылка на баннер",
                                u"Показы (спец.)", u"Клики (спец.)", u"CTR (спец.)",
                                u"Показы (юж./пр. блок)", u"Клики (юж./пр. блок)", u"CTR (юж./пр. блок)",
                                u"Максимум кликов",
                                u"Упущенные клики"]]

    setattr(df_chart, "formats", {u"Кампания №": "string",
                                  u"Баннер №": "string",
                                  u"Ключевая фраза": "string",
                                  u"Ссылка на баннер": "string",
                                  u"Показы (спец.)": "int",
                                  u"Клики (спец.)": "int",
                                  u"CTR (спец.)": "percent",
                                  u"Показы (юж./пр. блок)": "int",
                                  u"Клики (юж./пр. блок)": "int",
                                  u"CTR (юж./пр. блок)": "percent",
                                  u"Максимум кликов": "int",
                                  u"Упущенные клики": "int"})

    return df_chart


def table_top_phrases_strange_pos(df):
    """12_top_phrases_strange_pos"""
    df_chart = df.loc[~df.AvgPosShowsOther.isnull(), :].copy()
    try:
        df_chart = df.loc[df.AvgPosShowsOther != "None", :].copy()
    except TypeError:
        pass
    if df_chart.shape[0] == 0:
        return None
    df_chart.AvgPosShowsOther = df_chart.AvgPosShowsOther.astype(float)
    df_chart["ShowsSpecShare"] = df_chart["ShowsSpec"] / df_chart["ShowsSearch"]
    df_chart["CPC_spec"] = df_chart["CostSpec"] / df_chart["ClicksSpec"]
    df_chart["CPC_other"] = df_chart["CostOther"] / df_chart["ClicksOther"]
    df_chart["CPC_ratio"] = df_chart["CPC_spec"] / df_chart["CPC_other"]
    df_chart["CTR_spec"] = df_chart["ClicksSpec"] / df_chart["ShowsSpec"]
    df_chart["CTR_other"] = df_chart["ClicksOther"] / df_chart["ShowsOther"]
    df_chart = (df_chart[(df_chart["ShowsSpecShare"] < .9) &
                         (df_chart["CPC_ratio"] < 2) &
                         (df_chart.AvgPosShowsOther < 4.5) &
                         (df_chart.ShowsOther > 50)]
                [["CampaignID", "CampaignName", "DirectBannerID",
                  "PhraseText", "AvgPosShowsOther", "ShowsOther", "ShowsSpec",
                  "CPC_spec", "CPC_other", "CTR_spec", "CTR_other"]]
                .sort_values("ShowsOther", ascending=False)
                .reset_index(drop=True)
                .fillna(0)
                .round(3))

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

    df_chart.rename(columns={
        "CampaignID": u"Кампания №",
        "CampaignName": u"Название кампании",
        "DirectBannerID": u"Баннер №",
        "PhraseText": u"Ключевая фраза",
        "AvgPosShowsOther": u"Ср. поз. показов (юж./пр. блок)",
        "ShowsOther": u"Показы (юж./пр. блок)",
        "ShowsSpec": u"Показы (спец)",
        "CPC_other": u"CPC (юж./пр. блок)",
        "CPC_spec": u"CPC (спец)",
        "CTR_other": u"CTR (юж./пр. блок)",
        "CTR_spec": u"CTR (спец.)"},
        inplace=True)

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

    return df_chart


def table_top_cpc_phrases(df):
    """13_top_cpc_phrases"""

    df_chart = (df[["DirectBannerID", "PhraseText", "Shows", "Clicks", "Cost"]]
                .groupby(["DirectBannerID", "PhraseText"], as_index=False)
                .sum()
                .assign(CPC=lambda x: x.Cost / x.Clicks)
                .assign(CTR=lambda x: x.Clicks / x.Shows)
                .fillna(0)
                .sort_values("CPC", ascending=False)
                .reset_index(drop=True)
                .head(EXCEL_MAX_ROWS))

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

    df_chart.rename(columns={
        "DirectBannerID": u"Баннер №",
        "PhraseText": u"Ключевая фраза",
        # "AvgPosShowsOther": u"Ср. поз. показов (юж./пр. блок)",
        "Shows": u"Показы",
        "Clicks": u"Клики",
        "Cost": u"Расходы",
        "CPC": u"CPC",
        "CTR": u"CTR"},
        inplace=True)

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

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

    return df_chart
