#coding utf-8
import sys
import json
import datetime
import traceback
from threading import Timer
from tqdm import tqdm
from my_utils import RedisHelper, data_check, get_feature_data, send_msg_to_feishu
from my_config import set_config
from log import Log
config_, _ = set_config()
log_ = Log()
redis_helper = RedisHelper()

from feature import get_user_features
from lr_model import LrModel
from my_utils import exe_sql

def update_offline_score_user(dt):
    project = 'loghubods'
    sql = """
--odps sql
--********************************************************************--
--author:研发
--create time:2023-12-11 23:54:20
--********************************************************************--
with candidate_user as (
select
-- 基础特征_用户
mids AS u_id
,machineinfo_brand AS u_brand
,machineinfo_model AS u_device
,SPLIT(machineinfo_system,' ')[0] AS u_system
,machineinfo_system AS u_system_ver
,province as ctx_region
,city as ctx_city
,u_cycle_bucket_7days
,u_cycle_bucket_30days
,u_share_bucket_30days
,ceil(log2(u_1day_exp_cnt + 1)) as u_1day_exp_cnt
,ceil(log2(u_1day_click_cnt + 1)) as u_1day_click_cnt
,ceil(log2(u_1day_share_cnt + 1)) as u_1day_share_cnt
,ceil(log2(u_1day_return_cnt + 1)) as u_1day_return_cnt
,ceil(log2(u_3day_exp_cnt + 1)) as u_3day_exp_cnt
,ceil(log2(u_3day_click_cnt + 1)) as u_3day_click_cnt
,ceil(log2(u_3day_share_cnt + 1)) as u_3day_share_cnt
,ceil(log2(u_3day_return_cnt + 1)) as u_3day_return_cnt
,ceil(log2(u_7day_exp_cnt + 1)) as u_7day_exp_cnt
,ceil(log2(u_7day_click_cnt + 1)) as u_7day_click_cnt
,ceil(log2(u_7day_share_cnt + 1)) as u_7day_share_cnt
,ceil(log2(u_7day_return_cnt + 1)) as u_7day_return_cnt
,ceil(log2(u_3month_exp_cnt + 1)) as u_3month_exp_cnt
,ceil(log2(u_3month_click_cnt + 1)) as u_3month_click_cnt
,ceil(log2(u_3month_share_cnt + 1)) as u_3month_share_cnt
,ceil(log2(u_3month_return_cnt + 1)) as u_3month_return_cnt
,round(if(u_ctr_1day > 10.0, 10.0, u_ctr_1day) / 10.0, 6) as u_ctr_1day
,round(if(u_str_1day > 10.0, 10.0, u_str_1day) / 10.0, 6) as u_str_1day
,round(if(u_rov_1day > 10.0, 10.0, u_rov_1day) / 10.0, 6) as u_rov_1day
,round(if(u_ros_1day > 10.0, 10.0, u_ros_1day) / 10.0, 6) as u_ros_1day
,round(if(u_ctr_3day > 10.0, 10.0, u_ctr_3day) / 10.0, 6) as u_ctr_3day
,round(if(u_str_3day > 10.0, 10.0, u_str_3day) / 10.0, 6) as u_str_3day
,round(if(u_rov_3day > 10.0, 10.0, u_rov_3day) / 10.0, 6) as u_rov_3day
,round(if(u_ros_3day > 10.0, 10.0, u_ros_3day) / 10.0, 6) as u_ros_3day
,round(if(u_ctr_7day > 10.0, 10.0, u_ctr_7day) / 10.0, 6) as u_ctr_7day
,round(if(u_str_7day > 10.0, 10.0, u_str_7day) / 10.0, 6) as u_str_7day
,round(if(u_rov_7day > 10.0, 10.0, u_rov_7day) / 10.0, 6) as u_rov_7day
,round(if(u_ros_7day > 10.0, 10.0, u_ros_7day) / 10.0, 6) as u_ros_7day
,round(if(u_ctr_3month > 10.0, 10.0, u_ctr_3month) / 10.0, 6) as u_ctr_3month
,round(if(u_str_3month > 10.0, 10.0, u_str_3month) / 10.0, 6) as u_str_3month
,round(if(u_rov_3month > 10.0, 10.0, u_rov_3month) / 10.0, 6) as u_rov_3month
,round(if(u_ros_3month > 10.0, 10.0, u_ros_3month) / 10.0, 6) as u_ros_3month
from
loghubods.alg_recsys_user_info
where dt='{dt}'
and length(mids) > 0
and (u_3month_share_cnt > 0 or u_7day_click_cnt > 0 or u_3day_exp_cnt > 0)
)
SELECT
u_id as k,
*
from candidate_user
    """.format(dt=dt)
    # log_.info(sql)
    data = exe_sql(project, sql)
    print('sql done')
    # data.to_csv('./data/ad_out_sample_v2_item.{datetime}'.format(datetime=datetime), sep='\t')
    # data = pd.read_csv('./data/ad_out_sample_v2_item.{datetime}'.format(datetime=datetime), sep='\t', dtype=str)
    model_key = 'ad_out_v1'
    lr_model = LrModel('model/{}.json'.format(model_key))
    user_h_dict = {}
    k_col = 'u_id'
    key_name_prefix = f"{config_.KEY_NAME_PREFIX_AD_OUT_MODEL_SCORE_USER}{model_key}"
    print(key_name_prefix)
    mean_user_h = 0.0
    count_user_h = 0
    # 过期时间：一周
    expire_time = 7 * 24 * 3600
    with data.open_reader() as reader:
        for row in tqdm(reader):
            k = str(row['u_id'])
            user_features = get_user_features(row)
            user_h = lr_model.predict_h(user_features)
            # redis_helper.set_data_to_redis(f"{key_name_prefix}:{k}", user_h, expire_time)
            user_h_dict[k] = user_h
            mean_user_h += user_h
            count_user_h += 1
            # print(user_features)
            # print(user_h)
    mean_user_h = mean_user_h / count_user_h 
    user_h_dict['mean'] = mean_user_h 
    print(mean_user_h)
    print(count_user_h)
    k = 'mean'
    #redis_helper.set_data_to_redis(f"{key_name_prefix}:{k}", mean_user_h, expire_time)
    with open('{}.{}.json'.format(key_name_prefix, dt), 'w') as fout:
        json.dump(user_h_dict, fout, indent=2, ensure_ascii=False, sort_keys=True)


def timer_check(dt):
    try:
        project = config_.ad_model_data['ad_out_v1'].get('project')
        table = config_.ad_model_data['ad_out_v1'].get('table')
        now_date = datetime.datetime.today()
        yesterday_date = now_date - datetime.timedelta(days=1)
        now_dt = datetime.datetime.strftime(now_date, '%Y%m%d')
        yesterday_dt = datetime.datetime.strftime(yesterday_date, '%Y%m%d')
        log_.info(f"now_dt: {now_dt}")
        if dt is not None:
            yesterday_dt = dt
        log_.info(f"update_dt: {yesterday_dt}")
        now_min = datetime.datetime.now().minute
        # 查看当前更新的数据是否已准备好
        data_count = data_check(project=project, table=table, dt=yesterday_dt)
        if data_count > 0:
            log_.info('update_offline_score_user start! {}'.format(data_count))
            # 数据准备好，进行更新
            update_offline_score_user(dt=yesterday_dt)
            log_.info('update_offline_score_user end!')
        else:
            # 数据没准备好，5分钟后重新检查
            wait_seconds = 5 * 60
            log_.info('data not ready, wait {}s'.format(wait_seconds))
            Timer(wait_seconds, timer_check).start()

    except Exception as e:
        log_.error(f"用户广告跳出率预估离线user数据更新失败 exception: {e}, traceback: {traceback.format_exc()}")
        send_msg_to_feishu(
            webhook=config_.FEISHU_ROBOT['server_robot'].get('webhook'),
            key_word=config_.FEISHU_ROBOT['server_robot'].get('key_word'),
            msg_text=f"rov-offline{config_.ENV_TEXT} - 用户广告跳出率预估离线user数据更新失败\n"
                     f"exception: {e}\n"
                     f"traceback: {traceback.format_exc()}"
        )


if __name__ == "__main__":
    dt = None
    if len(sys.argv) > 1:
        dt = sys.argv[1]
        log_.info('## 手动更新:{}'.format(dt))
    else:
        log_.info('## 自动更新')
    timer_check(dt)


