# -*- coding: utf-8 -*-
import pandas as pd
from benchmarking import abs_bench_table
from utils import calculate_shares, fill_client_comp_columns, fill_empty_df, filter_by_date


def calculate_rating(task, data_df, sort_by='DirectCost', other=False):
    df = (data_df
          .loc[:, ['Client', 'DirectClicks', 'DirectCost', task.target]]
          .groupby('Client', as_index=False).sum()
          .assign(CPA=lambda df_: df_['DirectCost'] / df_[task.target],
                  CR=lambda df_: df_[task.target] / df_['DirectClicks'])
          )
    for col_name in ['CPA', 'CR']:
        df[col_name] = df[col_name].replace([pd.np.inf], 0)

    client_df = df[df['Client'] == task.client].reset_index(drop=True)
    if client_df.empty:
        client_df = fill_empty_df({'Client': [task.client] if task.client else ['None'],
                                   'DirectClicks': [0], 'DirectCost': [0], task.target: [0],
                                   'CPA': [0], 'CR': [0]}
                                  )
    comp_df = df[df['Client'] != task.client].sort_values(by=sort_by, ascending=False).reset_index(drop=True)
    if comp_df.shape[0] > 20 and other:
        other_df = pd.DataFrame(comp_df.loc[20:, :].sum()).T
        other_df['Client'] = u'Прочие конкуренты'

        comp_df = pd.concat([comp_df.loc[:19, :], other_df]).reset_index(drop=True)

    df = pd.concat([client_df, comp_df]).reset_index().fillna(0)

    return df


def calculate_grouped_table(task, data_df, *opt, **kwargs):
    group_by, place, device = kwargs.get('group_by'), kwargs.get('place'), kwargs.get('device')
    assert group_by in ['Category', 'Place', 'Device', 'BannerType', 'TargetingType'], 'unknown group_by %s' % group_by

    column, params = opt
    formula = params.get('formula')

    group_cols = [group_by, 'Client']
    cols = [formula['divinded'], formula['devider']] if formula else [column]
    for col in task.filter_by.values():
        if col not in cols:
            cols.append(col)

    if place:
        data_df = data_df.loc[data_df.Place.isin([place])]
    if device:
        data_df = data_df.loc[data_df.Device.isin([device])]

    df = (filter_by_date(data_df, task.periods['period_2'])
          .loc[:, group_cols + cols]
          .groupby(group_cols, as_index=False).sum()
          )

    df = grouped_table(task, df, group_by, column, formula, place=place)
    df = df.replace([pd.np.nan, pd.np.inf, -pd.np.inf], 0)

    return [df]


def grouped_table(task, df, *opt, **kwargs):
    group_by, column, formula = opt
    cols = [formula['divinded'], formula['devider']] if formula else [column]
    for col in task.filter_by.values():
        if col not in cols:
            cols.append(col)

    rows = get_row_indexes(task, group_by, kwargs.get('place'))

    empty_df = fill_empty_df({
        group_by: rows,
        'Client%s' % column: [0] * len(rows),
        'Comp%s' % column: [0] * len(rows), 'CompSum': [0] * len(rows),
        'CompMax': [0] * len(rows), 'CompMin': [0] * len(rows),

        'Client%s' % task.filter_by['Clicks']: [0] * len(rows),
        'Client%s' % task.filter_by['Conversions']: [0] * len(rows),
        'Comp%s' % task.filter_by['Clicks']: [0] * len(rows),
        'Comp%s' % task.filter_by['Conversions']: [0] * len(rows)},
        group_by=group_by
    )

    if df.empty:
        df = empty_df.copy()
    else:
        df = fill_client_comp_columns(task.client, df, cols)
        if formula is None:
            df = abs_bench_table(task, df, column, group_by=group_by).set_index(group_by)

        else:
            div_col, dev_col = formula['divinded'], formula['devider']

            df = (df.groupby(group_by, as_index=True)
                  .agg({'Client%s' % div_col: pd.np.sum,
                        'Client%s' % dev_col: pd.np.sum,
                        'Comp%s' % div_col: pd.np.sum,
                        'Comp%s' % dev_col: pd.np.sum,
                        'Client%s' % task.filter_by['Clicks']: pd.np.sum,
                        'Client%s' % task.filter_by['Conversions']: pd.np.sum,
                        'Comp%s' % task.filter_by['Clicks']: pd.np.sum,
                        'Comp%s' % task.filter_by['Conversions']: pd.np.sum,
                        })
                  )
            df['Client%s' % column] = df['Client%s' % div_col] / df['Client%s' % dev_col]
            df['Comp%s' % column] = df['Comp%s' % div_col] / df['Comp%s' % dev_col]

    not_in_index = [row for row in rows if row not in df.index]
    if not_in_index:
        df = df.append(empty_df.loc[not_in_index, ])

    return df.loc[rows, :].reset_index() if rows else df.reset_index()


def get_row_indexes(task, group_by, place):
    if group_by == 'Place':
        return [u'Поиск', u'Сети']

    elif group_by == 'Device':
        return [u'Десктопы', u'Смартфоны']

    elif group_by == 'Category':
        return task.categories_order if task.categories_order else []

    elif group_by == 'BannerType':
        if task.type_ == 'finance':
            if place == u'Поиск':
                return [u'Текстово-графические', u'Баннер на поиске']
            elif place == u'Сети':
                return [u'Текстово-графические', u'Графические', u'Смарт-баннеры',
                        u'Видеообъявления и видеодополнения']

        else:
            if place == u'Поиск':
                return [u'Текстово-графические', u'Динамические', u'Баннер на поиске']
            elif place == u'Сети':
                return [u'Текстово-графические', u'Графические', u'Смарт-баннеры']

    elif group_by == 'TargetingType':
        if place == u'Поиск':
            return [u'Фразы (прочее)', u'Фразы (навигационные)', u'Фразы (ДРФ)']

        elif place == u'Сети':
            return [u'Фразы', u'Ретаргетинг и подбор аудитории']


def prepare_grouped_table(df, column, formula, group_by, group_names=None):
    if not formula:
        df = calculate_shares(df, column)

    if group_names:
        df['%s_2' % group_by] = df[group_by].replace(group_names)

    return df
