from yt.wrapper import ypath_join
from yt.wrapper.common import GB
from datacloud.dev_utils.yql.yql_helpers import execute_yql

from datacloud.money.yt_helpers import (
    ScoreToContract, DaysFiller, MoneyReducer, AggTypes,
    get_aggregate_query, select_last_days
)
from datacloud.money.money_log_table import MoneyLogTable
from datacloud.money.solomon_helpers import (
    post_results, get_daily_sensors, get_monthly_sensors,
    DAILY_SERVICE, MONTHLY_SERVICE
)

DAYS_TO_POST = 33


def formated_logs_to_money(yt_client, formated_logs, money_table, tmp_dir, tag):
    reqs_with_contract = yt_client.TablePath(
        ypath_join(tmp_dir, 'reqs_with_contract'),
        schema=[
            {'name': 'partner_id', 'type': 'string'},
            {'name': 'contract_id', 'type': 'string'},
            {'name': 'year', 'type': 'uint16'},
            {'name': 'month', 'type': 'uint8'},
            {'name': 'day', 'type': 'uint8'},
            {'name': 'ts', 'type': 'double'},
            {'name': 'status', 'type': 'string'},
            {'name': 'has_score', 'type': 'boolean'},
            {'name': 'request_id', 'type': 'string'},
            {'name': 'id_value', 'type': 'string'},
            {'name': 'response_time', 'type': 'double'},
        ]
    )
    yt_client.run_map(
        ScoreToContract(),
        formated_logs,
        reqs_with_contract,
        spec={'title': '[{}] Score to contract'.format(tag)}
    )
    yt_client.run_sort(
        reqs_with_contract,
        sort_by=['partner_id', 'contract_id', 'year', 'month', 'day', 'ts'],
        spec={'title': '[{}] Score to contract / sort after'.format(tag)}
    )

    days_table = ypath_join(tmp_dir, 'days_table')
    DaysFiller()(yt_client, days_table)

    yt_client.run_reduce(
        MoneyReducer(),
        [days_table, reqs_with_contract],
        money_table,
        reduce_by=['partner_id', 'contract_id', 'year', 'month'],
        spec={
            'title': '[{}] Calculate money in window'.format(tag),
            'memory_limit': 4 * GB  # TODO: [FIXME] [penguin-diver@]
        }
    )

    return money_table


def post_money(yt_client, money_table, tmp_dir, log_type='qloud_logs', days_to_post=DAYS_TO_POST):
    daily_table = ypath_join(tmp_dir, 'daily_table')
    execute_yql(get_aggregate_query(
        input_table=money_table,
        output_table=daily_table,
        agg_type=AggTypes.daily
    ), yt_client=yt_client, syntax_version=1)

    last_days_table = ypath_join(tmp_dir, 'last_days_table')
    execute_yql(select_last_days.format(
        input_table=daily_table,
        output_table=last_days_table,
        n=days_to_post
    ), yt_client=yt_client, syntax_version=1)

    money_log_table = MoneyLogTable(log_type=log_type, period_type='daily')
    post_results(yt_client, last_days_table, money_log_table, get_daily_sensors, DAILY_SERVICE, log_type)
    money_log_table.make_static_copy()

    monthly_table = ypath_join(tmp_dir, 'monthly_table')
    execute_yql(get_aggregate_query(
        input_table=money_table,
        output_table=monthly_table,
        agg_type=AggTypes.monthly
    ), yt_client=yt_client, syntax_version=1)

    money_log_table = MoneyLogTable(log_type=log_type, period_type='monthly')
    post_results(yt_client, monthly_table, money_log_table, get_monthly_sensors, MONTHLY_SERVICE, log_type)
    money_log_table.make_static_copy()
