# -*- coding: utf-8 -*-
import pandas as pd
from presentation.utils import get_pretty_period, pretty_period_from_date, pretty_date_from_date
from utils import fill_empty_df, fill_missed_dates


def calculate_bench_table(task, data_df, *opt):
    column, formula = opt

    if data_df.empty:
        df = pd.DataFrame(columns=[u'Date', 'Client%s' % column, 'Comp%s' % column, u'CompSum', u'CompMin', u'CompMax'])

    else:
        df = abs_bench_table(task, data_df.copy(), column) if formula is None else \
            rel_bench_table(task, data_df.copy(), column, formula)

    df = df.assign(CompMax=df.CompMax - df['Comp%s' % column],
                   CompMin=df['Comp%s' % column] - df.CompMin)

    return prepare_dyn_table(task, df)


def abs_bench_table(task, data_df, column, group_by='Date'):
    data_df = data_df.fillna(0.).groupby([group_by, 'Client'], as_index=False).sum()
    data_df = data_df[(data_df[task.filter_by['Clicks']] > 0) | (data_df[task.filter_by['Conversions']] > 0)]

    comp_df = data_df[data_df['Client'] != task.client].copy().groupby(group_by, as_index=True).count()
    df = (data_df.groupby(group_by, as_index=True)
          .agg({'Client%s' % column: {'Client%s' % column: pd.np.sum},
                'Comp%s' % column: {'CompSum': pd.np.sum,
                                    'CompMax': pd.np.nanmax,
                                    'CompMin': pd.np.nanmin}
                })
          )
    df.columns = df.columns.droplevel()
    df['Comp%s' % column] = df['CompSum'] / comp_df['Comp%s' % column]

    return df.reset_index()


def rel_bench_table(task, data_df, column, formula, group_by='Date'):
    data_df = data_df.fillna(0.).groupby([group_by, 'Client'], as_index=False).sum()
    data_df = data_df[(data_df[task.filter_by['Clicks']] > 0) | (data_df[task.filter_by['Conversions']] > 0)]

    if data_df.empty:
        df = pd.DataFrame(columns=[
            u'Date',
            'Client%s' % column,
            'Comp%s' % column, u'CompSum', u'CompMin', u'CompMax',
            'Client%s' % task.filter_by['Clicks'],
            'Client%s' % task.filter_by['Conversions'],
            'Comp%s' % task.filter_by['Clicks'],
            'Comp%s' % task.filter_by['Conversions']
        ])
    else:
        div_col, dev_col = formula['divinded'], formula['devider']
        data_df[column] = data_df[div_col] / data_df[dev_col]
        data_df['Comp%s' % column] = data_df.apply(lambda df_:
                                                   df_[column] if df_['Client'] != task.client else pd.np.nan,
                                                   axis=1)

        data_df = data_df.replace([pd.np.inf, -pd.np.inf], pd.np.nan)

        df = (data_df.groupby(group_by, as_index=True)
              .agg({'Client%s' % div_col: {'Client%s' % div_col: pd.np.sum},
                    'Client%s' % dev_col: {'Client%s' % dev_col: pd.np.sum},
                    'Comp%s' % div_col: {'Comp%s' % div_col: pd.np.sum},
                    'Comp%s' % dev_col: {'Comp%s' % dev_col: pd.np.sum},
                    'Comp%s' % column: {'CompMax': pd.np.nanmax,
                                        'CompMin': pd.np.nanmin},

                    'Client%s' % task.filter_by['Clicks']: {'Client%s' % task.filter_by['Clicks']: pd.np.sum},
                    'Client%s' % task.filter_by['Conversions']: {
                        'Client%s' % task.filter_by['Conversions']: pd.np.sum},
                    'Comp%s' % task.filter_by['Clicks']: {'Comp%s' % task.filter_by['Clicks']: pd.np.sum},
                    'Comp%s' % task.filter_by['Conversions']: {
                        'Comp%s' % task.filter_by['Conversions']: pd.np.sum},
                    })
              )
        df.columns = df.columns.droplevel()

        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]

    return df.reset_index()


def calculate_comp_table(task, data_df, *opt, **kwargs):
    column, formula = opt

    if kwargs.get('filter_client', True):
        data_df = data_df.copy()[data_df['Client'] != task.client]
        if data_df.empty:
            return pd.DataFrame()

    if formula is None:
        df = pd.pivot_table(data_df, values=column, index='Date', columns='Client', aggfunc=pd.np.sum)

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

        df = pd.pivot_table(data_df, values=[div_col, dev_col], index='Date', columns='Client', aggfunc=pd.np.sum)
        df = df[div_col] / df[dev_col]
        df = df.replace(to_replace=[pd.np.nan, pd.np.inf, -pd.np.inf], value='')

    return prepare_dyn_table(task, df.reset_index())


def prepare_dyn_table(task, df):
    df = fill_missed_dates(task, df)
    df = df.replace(to_replace=[pd.np.nan, pd.np.inf, -pd.np.inf], value=0)

    df['PrettyDate'] = df['Date'].apply(lambda col: pretty_date_from_date(col, task.time_detail))
    df['Date'] = df['Date'].apply(lambda col: col.strftime('%Y-%m-%d'))
    return df


def calculate_yoy_table(task, data_df, *opt):
    column, formula = opt

    period_1, period_2 = task.periods.get('period_1'), task.periods.get('period_2')
    pretty_period_1 = get_pretty_period(period_1['first_date'], period_1['last_date'], task.time_detail, short=True)
    pretty_period_2 = get_pretty_period(period_2['first_date'], period_2['last_date'], task.time_detail, short=True)

    empty_yoy_table = fill_empty_df({
        'Period': [pretty_period_1, pretty_period_2],
        'Client%s' % column: [0, 0], 'Comp%s' % column: [0, 0],
        'CompMax': [0, 0], 'CompMin': [0, 0],
        'Client%s' % task.filter_by['Clicks']: [0, 0],
        'Client%s' % task.filter_by['Conversions']: [0, 0],
        'Comp%s' % task.filter_by['Clicks']: [0, 0],
        'Comp%s' % task.filter_by['Conversions']: [0, 0]
    })
    if data_df.empty:
        return empty_yoy_table

    data_df['Period'] = data_df.apply(
        lambda df_: unicode(pretty_period_from_date(df_['Date'], period_1, period_2, task.time_detail)), axis=1)
    data_df = data_df[data_df['Period'].isin([pretty_period_1, pretty_period_2])]

    if data_df.empty:
        return empty_yoy_table

    df = abs_bench_table(task, data_df.copy(), column, group_by='Period') if formula is None else \
        rel_bench_table(task, data_df.copy(), column, formula, group_by='Period')

    df = df.replace(to_replace=[pd.np.nan, pd.np.inf, -pd.np.inf], value=0)
    if df.empty:
        return empty_yoy_table

    for period in [pretty_period_1, pretty_period_2]:
        if period not in df.Period.values:
            period_df = pd.DataFrame({
                'Period': [period],
                'Client%s' % column: [0], 'Comp%s' % column: [0],
                'CompMax': [0], 'CompMin': [0],
                'Client%s' % task.filter_by['Clicks']: [0],
                'Client%s' % task.filter_by['Conversions']: [0],
                'Comp%s' % task.filter_by['Clicks']: [0],
                'Comp%s' % task.filter_by['Conversions']: [0]
            })
            df = df.append(period_df)

    df = df.set_index('Period').loc[[pretty_period_1, pretty_period_2], :].reset_index()
    return df
