# -*- coding: utf-8 -*-
#!/usr/bin/env python3
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
import logging
import pandas as pd
from textwrap import dedent
from yt import wrapper as yt
from client_analytics.weekly_pack_py3.weekly_pack.data import SECRET
from client_analytics.weekly_pack_py3.weekly_pack.utils import get_file

logger = logging.getLogger(__name__)
OTHER_VALUE = u'Другие'


def get_period():
    dt = datetime.today()
    monday = dt - timedelta(days=dt.weekday())
    return {
        'from_dt': (monday - relativedelta(weeks=70)).strftime('%Y-%m-%d'),
        'to_dt': (monday - relativedelta(days=1)).strftime('%Y-%m-%d'),
    }


def round_date(dt):
    dt = datetime.strptime(dt[:10], '%Y-%m-%d')
    return (dt - timedelta(days=dt.weekday())).strftime('%Y-%m-%d')


def flat_table_by_devices(df, value_=None):
    desktop_df = df[df['device'].isin([u'Десктоп'])].copy()
    desktop_df['os'] = desktop_df['os'].replace({u'Всего': OTHER_VALUE})

    mobile_df = make_col_flat(
        df=df[df['device'].isin([u'Мобильные устройства'])].copy(),
        value_=value_,
        col_name='os',
        group_cols=['dt', 'adv', 'place']
    )
    mobile_df['device'] = u'Мобильные устройства'

    devices_df = pd.concat([desktop_df, mobile_df]).reset_index(drop=True)
    devices_df = pd.DataFrame(devices_df.groupby(['dt', 'adv', 'place', 'os'], as_index=False).sum())
    other_df = get_other_devices(df[df['device'].isin([u'Всего'])].copy(), devices_df, value_)

    return pd.concat([desktop_df, mobile_df, other_df]).reset_index(drop=True)


def get_other_devices(total_df, devices_df, value_):
    total_df = make_col_flat(
        df=total_df,
        value_=value_,
        col_name='os',
        group_cols=['dt', 'adv', 'place']
    )

    group_cols = ['dt', 'adv', 'place', 'os']
    other_df = total_df.merge(
        devices_df.drop_duplicates(subset=group_cols),
        how='left', left_on=group_cols, right_on=group_cols, suffixes=('', '_other')
    )
    other_df[value_] = other_df[value_] - other_df['%s_other' % value_]
    other_df['device'] = OTHER_VALUE

    return other_df[['dt', 'adv', 'place', 'device', 'os', value_]].reset_index(drop=True)


def make_col_flat(df, value_, col_name, group_cols):
    """
    :param df:
    :param value_: название колонки для суммирования
    :param col_name: название колонки, в которой нужно выделить сущность OTHER_VALUE
    :param group_cols: список названий колонок, по которым нужно сгруппировать df
    :return:
    """

    total_df = pd.DataFrame(df[df[col_name].isin([u'Всего'])].groupby(group_cols, as_index=False).sum())
    other_df = pd.DataFrame(df[~df[col_name].isin([u'Всего'])].groupby(group_cols, as_index=False).sum())

    merged_df = total_df.merge(
        other_df.drop_duplicates(subset=group_cols),
        how='left', left_on=group_cols, right_on=group_cols, suffixes=('', '_other')
    )
    merged_df[value_] = merged_df[value_] - merged_df['%s_other' % value_]
    merged_df[col_name] = OTHER_VALUE

    merged_df = merged_df[group_cols + [col_name, value_]]

    return pd.concat([df[~df[col_name].isin([u'Всего'])], merged_df]).reset_index(drop=True)


def get_other_adv(df, value_):
    total_df = make_col_flat(
        df=df,
        value_=value_,
        col_name='adv',
        group_cols=['dt', 'place', 'device', 'os']
    )
    return total_df[total_df['adv'].isin([OTHER_VALUE])]


def get_shifted_value(row, df, col_name):
    shifted_date = datetime.strptime(row['dt'], '%Y-%m-%d')
    shifted_date = (shifted_date - timedelta(weeks=52)).strftime('%Y-%m-%d')

    try:
        shifted_value = df[
            df['dt'].isin([shifted_date]) &
            df['adv'].isin([row['adv']]) &
            df['place'].isin([row['place']]) &
            df['device'].isin([row['device']]) &
            df['os'].isin([row['os']])
        ][col_name].values[0]
        return shifted_value
    except:
        return 0


def get_cluster_shifted_value(row, df, col_name):
    shifted_date = datetime.strptime(row['dt'], '%Y-%m-%d')
    shifted_date = (shifted_date - timedelta(weeks=52)).strftime('%Y-%m-%d')

    try:
        shifted_value = df[
            df['dt'].isin([shifted_date]) &
            df['group'].isin([row['group']])
        ][col_name].values[0]
        return shifted_value
    except:
        return 0


def get_cluster_name(group_name):
    try:
        key_ = int(group_name[-1])
    except:
        return group_name

    if key_ == 0:
        return u'Сильно снизившие с небольшим возвратом (-50%)'
    elif key_ == 1:
        return u'Стабильные (0%)'
    elif key_ == 2:
        return group_name
    elif key_ == 3:
        return u'Резко снизившие (-40-60%)'
    elif key_ == 4:
        return u'Выросшие с возвратом (100%)'
    elif key_ == 5:
        return u'Умеренно снизившие с недельной сезонностью (-20%)'
    elif key_ == 6:
        return u'Умеренно снизившие (-20%)'


def get_query_text(query_name):
    with get_file('data', 'queries', '%s.sql' % query_name) as fd:
        return dedent(fd.read().decode('utf8')).strip()


def get_occ_query(type_, from_dt, to_dt):
    return dedent(
        """
            https://artmon.bsadm.yandex-team.ru/cgi-bin/data.cgi?module=OneCentClicks
            &period_start={from_dt}&period_start_hour=undefined
            &period_end={to_dt}&period_end_hour=undefined
            &compare_enabled=0
            &compare_start=2019-03-04&compare_start_hour=undefined
            &compare_end=2019-04-07&compare_end_hour=undefined
            &timegroup=undefined&periodicity=undefined
            &query=%7B%22filters%22%3A%7B%22YandexFilter%22%3A%22{type_}%22%2C%22absolute%22%3A1%2C%22rcl_bid%22%3A1%2C%22ecl_bid%22%3A1%7D%7D
            &filename_postfix=_2020-06-01_2020-06-07&output_format=tsv&dl=1
        """.format(from_dt=from_dt, to_dt=to_dt, type_=type_.replace(' ', '%2B'))
    ).replace('\n', '')


def write_table(target_path, schema, df):
    data = df.to_dict('records')
    yt_client = yt.YtClient(token=SECRET['token'], proxy='hahn')
    with yt_client.Transaction():
        if yt_client.exists(target_path):
            yt_client.remove(target_path)

        yt_client.write_table(yt_client.TablePath(target_path, schema=schema), data)

    logger.info(target_path)
