# -*- encoding: utf8 -*-

import pandas as pd
from sqlalchemy import create_engine
import numpy as np

pd.options.mode.chained_assignment = None

'''
1、ref_amount=  拆分后的本金+利息+服务费+罚息-所有的减免金额+remain_income
2、collection_relief= 减免本金+减免利息+减免服务费+减免罚息
3、collection_relief= 催收减免+红包减免
4、红包使用前提是 有减免 >0
5、如果红包使用了一半，则不使用红包，这种情况需要查看数据是什么原因造成的，
6、注意这个版本适用 201704之后的拆分，
'''

engine_audit = create_engine(
    'mysql+mysqldb://bo.wang:#mn89453YU9io80@172.16.3.201:3306/new_transaction?charset=utf8', echo=True)

chunksize = 5000


# TODO '根据具体情况选择plan_id'
# sql_plan_id = '''
# SELECT t2.id plan_id FROM red_packet_detail t1 LEFT JOIN user_repayment_plan t2 ON t1.ref_id=t2.ref_id AND t1.term_no=t2.term_no WHERE xyqb_repaid_at>="2017-10-01" AND xyqb_repaid_at<"2017-11-10"
# '''

# sql_plan_id = '''
# SELECT t1.plan_id  FROM `xjd_repay_plan_repay_record_ref` t1
# JOIN `user_repayment_plan` t2 ON t1.plan_id = t2.id
# WHERE   t2.xyqb_repaid_at >= '2017-10-01 00:00:00' AND t2.xyqb_repaid_at < '2017-11-05 00:00:00' AND t1.ref_amount > 0
# '''


sql_plan_id = '''
SELECT t2.id plan_id FROM  user_repayment_plan t2 WHERE  id IN (17939003,18001511,17999693,19348913,17992793,17992907,17990615,17939735,17995541,17917967,17996099,13183085,17818535,14951401,16775621,16793909,18538103,15048301,17317973,16862699,16779713,16947229,16853759,16723967,17356583,16960183,16647695,20435587,16023121,14459209,16135315,18239129,15815947,18478739,18481649)
'''

#
# sql_plan_id = '''
# SELECT t1.plan_id  FROM `xjd_repay_plan_repay_record_ref` t1
# JOIN `user_repayment_plan` t2 ON t1.plan_id = t2.id
# WHERE t2.xyqb_repaid_at >= '2017-06-01 00:00:00' AND t2.xyqb_repaid_at < '2017-07-01 00:00:00' AND t1.ref_amount > 0 AND t1.repay_channel in (13)
# '''


sql_update = """
    update xjd_repay_plan_repay_record_ref set principle = %s, interest = %s, service_fee = %s, punish = %s, collection_relief = %s, remain_income = %s,
    mitigate_principle = %s, mitigate_interest = %s, mitigate_service_fee = %s, mitigate_collection_relief = %s,red_package_fee=%s,mitigate_all=%s where id = %s
    """
columns = ['id', 'plan_id', 'ref_amount', 'principle', 'interest', 'service_fee', 'should_punish', 'red_package_fee',
           'repay_status','re_principle', 're_interest', 're_service_fee', 're_punish', 're_relief', 're_remain',
           'mitigate_prin', 'mitigate_inst', 'mitigate_fee', 'mitigate_punish', 'mitigate_all']
up_columns = ['re_principle', 're_interest', 're_service_fee', 're_punish', 're_relief', 're_remain', 'mitigate_prin',
              'mitigate_inst', 'mitigate_fee', 'mitigate_punish', 'red_package_fee', 'mitigate_all', 'id']


def split_money_3(df):
    df['re_principle'] = 0
    df['re_interest'] = 0
    df['re_service_fee'] = 0
    df['re_punish'] = 0
    df['re_relief'] = 0
    df['re_remain'] = 0
    df['mitigate_prin'] = 0
    df['mitigate_inst'] = 0
    df['mitigate_fee'] = 0
    df['mitigate_punish'] = 0
    df['red_package_fee'] = 0
    df['mitigate_all'] = 0

    left_prin = round(df['principle'].values[0], 2)
    left_inst = round(df['interest'].values[0], 2)
    left_fee = round(df['service_fee'].values[0], 2)
    left_punish = round(df['should_punish'].values[0], 2)
    left_red_packet = round(df['red_package'].values[0], 2)
    for index, row in df.iterrows():
        ref_amount = round(row['ref_amount'], 2)
        # 分配本金
        if left_prin > 0:
            if ref_amount <= left_prin:
                df.loc[index, 're_principle'] = ref_amount
                left_prin -= ref_amount
                continue
            else:
                df.loc[index, 're_principle'] = left_prin
                ref_amount -= left_prin
                left_prin = 0
        # 分配利息
        if left_inst > 0:
            if ref_amount <= left_inst:
                df.loc[index, 're_interest'] = ref_amount
                left_inst -= ref_amount
                continue
            else:
                df.loc[index, 're_interest'] = left_inst
                ref_amount -= left_inst
                left_inst = 0
        # 分配服务费
        if left_fee > 0:
            if ref_amount <= left_fee:
                df.loc[index, 're_service_fee'] = ref_amount
                left_fee -= ref_amount
                continue
            else:
                df.loc[index, 're_service_fee'] = left_fee
                ref_amount -= left_fee
                left_fee = 0
        # 分配罚息
        if left_punish > 0:
            if ref_amount <= left_punish:
                df.loc[index, 're_punish'] = ref_amount
                left_punish -= ref_amount
                continue
            else:
                df.loc[index, 're_punish'] = left_punish
                ref_amount -= left_punish
                left_punish = 0
        # 多出来的放到剩余金额里
        df.loc[index, 're_remain'] = ref_amount
    # 修改最后一条记录的金额
    df.loc[index, 're_principle'] = round(df['principle'].values[0], 2) - round(sum(df['re_principle'].values[:-1]), 2)
    df.loc[index, 're_interest'] = round(df['interest'].values[0], 2) - round(sum(df['re_interest'].values[:-1]), 2)
    df.loc[index, 're_service_fee'] = round(df['service_fee'].values[0], 2) - round(
        sum(df['re_service_fee'].values[:-1]), 2)
    df.loc[index, 're_punish'] = round(df['should_punish'].values[0], 2) - round(sum(df['re_punish'].values[:-1]), 2)
    sum_amount = df.loc[index, 're_principle'] + df.loc[index, 're_interest'] + df.loc[index, 're_service_fee'] + \
                 df.loc[index, 're_punish']

    sum_prin = sum(df['re_principle'])
    sum_inst = sum(df['re_interest'])
    sum_fee = sum(df['re_service_fee'])
    sum_punish = sum(df['re_punish'])
    sum_total = sum(df['ref_amount'])
    if sum_amount > df.loc[index, 'ref_amount']:  # 有减免
        df.loc[index, 're_relief'] = round(sum_amount - df.loc[index, 'ref_amount'], 2)
        df.loc[index, 'mitigate_prin'] = round(max(sum_prin - sum_total, 0), 2)
        df.loc[index, 'mitigate_inst'] = round(max(sum_prin + sum_inst - df.loc[index, 'mitigate_prin'] - sum_total, 0),
                                               2)
        df.loc[index, 'mitigate_fee'] = round(max(
            sum_prin + sum_inst + sum_fee - df.loc[index, 'mitigate_prin'] - df.loc[index, 'mitigate_inst'] - sum_total,
            0), 2)
        df.loc[index, 'mitigate_punish'] = round(max(
            sum_prin + sum_inst + sum_fee + sum_punish - df.loc[index, 'mitigate_prin'] - df.loc[
                index, 'mitigate_inst'] - df.loc[index, 'mitigate_fee'] - sum_total, 0), 2)
        df.loc[index, 're_remain'] = 0
        # 红包 使用前提有减免
        if df.loc[index, 're_relief'] > 0:
            if df.loc[index, 're_relief'] < left_red_packet:
                df.loc[index, 'red_package_fee'] = 0
            else:
                df.loc[index, 'red_package_fee'] = left_red_packet
        df.loc[index, 'mitigate_all'] = df.loc[index, 'mitigate_prin'] + df.loc[index, 'mitigate_inst'] + df.loc[index, 'mitigate_fee'] + df.loc[index, 'mitigate_punish'] - df.loc[index, 'red_package_fee']
    elif sum_amount < df.loc[index, 'ref_amount']:  # 没有减免
        df.loc[index, 're_relief'] = 0
        df.loc[index, 're_remain'] = round(df.loc[index, 'ref_amount'] - sum_amount, 2)
    else:  # 没有减免
        df.loc[index, 're_relief'] = 0
        df.loc[index, 're_remain'] = 0
    return df


def split_money_0(df):
    df['re_principle'] = 0
    df['re_interest'] = 0
    df['re_service_fee'] = 0
    df['re_punish'] = 0
    df['re_relief'] = 0
    df['re_remain'] = 0

    left_prin = round(df['principle'].values[0], 2)
    left_inst = round(df['interest'].values[0], 2)
    left_fee = round(df['service_fee'].values[0], 2)
    left_punish = round(df['should_punish'].values[0], 2)
    for index, row in df.iterrows():
        ref_amount = round(row['ref_amount'], 2)
        # 分配本金
        if left_prin > 0:
            if ref_amount <= left_prin:
                df.loc[index, 're_principle'] = ref_amount
                left_prin -= ref_amount
                continue
            else:
                df.loc[index, 're_principle'] = left_prin
                ref_amount -= left_prin
                left_prin = 0
        # 分配利息
        if left_inst > 0:
            if ref_amount <= left_inst:
                df.loc[index, 're_interest'] = ref_amount
                left_inst -= ref_amount
                continue
            else:
                df.loc[index, 're_interest'] = left_inst
                ref_amount -= left_inst
                left_inst = 0
        # 分配服务费
        if left_fee > 0:
            if ref_amount <= left_fee:
                df.loc[index, 're_service_fee'] = ref_amount
                left_fee -= ref_amount
                continue
            else:
                df.loc[index, 're_service_fee'] = left_fee
                ref_amount -= left_fee
                left_fee = 0
        # 分配罚息
        if left_punish > 0:
            if ref_amount <= left_punish:
                df.loc[index, 're_punish'] = ref_amount
                left_punish -= ref_amount
                continue
            else:
                df.loc[index, 're_punish'] = left_punish
                ref_amount -= left_punish
                left_punish = 0
        # 多出来的放到剩余金额里
        df.loc[index, 're_remain'] = ref_amount
    return df




# 注意退款的情况
sql_xjd_ref = '''select id, plan_id, ref_amount from xjd_repay_plan_repay_record_ref where plan_id in %s and ref_amount > 0 '''

# sql_xjd_ref = '''SELECT
# 	id,
# 	plan_id,
# 	ref_amount
# FROM
# 	xjd_repay_plan_repay_record_ref t1
# JOIN new_transaction.repay_record_online t2 ON t1.record_id = t2.id
# AND t1.repay_channel = t2.pay_approach
# WHERE
# 	plan_id IN % s
# AND ref_amount > 0  '''

sql_user_repayment_plan = '''
select id plan_id, ref_id,term_no,principle, interest, service_fee, should_punish ,repay_status,xyqb_repaid_at from user_repayment_plan where id in %s
'''
#红包数据
sql3 = """
select ref_id,term_no,amount red_amount from red_packet_detail where ref_id in %s
"""

df_gen = pd.read_sql(sql=sql_plan_id, con=engine_audit, chunksize=chunksize)
i = 0
for df_plan_id in df_gen:
    print '--------------------> %s <----------------------------' % (i,)
    i += 1
    # if i < 76:
    #    continue
    plan_ids = df_plan_id['plan_id'].astype(str).tolist()
    df_xjd_ref = pd.read_sql(sql=sql_xjd_ref % (str(tuple(plan_ids)).replace(',)', ')'),), con=engine_audit)
    df_user_repayment_plan = pd.read_sql(sql=sql_user_repayment_plan % (str(tuple(plan_ids)).replace(',)', ')'),), con=engine_audit)

    df_user_repayment_plan.fillna(0, inplace=True)
    df_user_repayment_plan['repay_status'] = df_user_repayment_plan['repay_status'].astype(int)
    df_repayment_ref_merge = pd.merge(df_xjd_ref, df_user_repayment_plan, on='plan_id')
    df_count = df_repayment_ref_merge.groupby('plan_id')['id'].agg(['count']).reset_index()
    df_repayment_ref_merge = pd.merge(df_repayment_ref_merge, df_count, on='plan_id')

    #叠加红包数据
    ref_ids = df_repayment_ref_merge['ref_id'].astype(str).tolist()
    df_3 = pd.read_sql(sql=sql3 % (str(tuple(ref_ids)).replace(',)', ')'),), con=engine_audit)
    df_repayment_ref_merge['ref_id'] = df_repayment_ref_merge['ref_id'].astype(int)
    df_repayment_ref_merge['term_no'] = df_repayment_ref_merge['term_no'].astype(int)
    df_3['ref_id'] = df_3['ref_id'].astype(int)
    df_3['term_no'] = df_3['term_no'].astype(int)
    df_repayment_ref_merge = pd.merge(df_repayment_ref_merge, df_3, on=['ref_id', 'term_no'], how='left')
    df_repayment_ref_merge.fillna(0, inplace=True)
    df_repayment_ref_merge['red_package'] = df_repayment_ref_merge['red_amount']
    # =====================红包获取end===============


    # 'principle, interest, service_fee, should_punish,red_package '
    df_repayment_ref_merge['principle'] = np.round(df_repayment_ref_merge['principle'], 2)
    df_repayment_ref_merge['interest'] = np.round(df_repayment_ref_merge['interest'], 2)
    df_repayment_ref_merge['service_fee'] = np.round(df_repayment_ref_merge['service_fee'], 2)
    df_repayment_ref_merge['xyqb_repaid_at'] = pd.to_datetime(df_repayment_ref_merge['xyqb_repaid_at']).apply(lambda x: x.date())


    df_repayment_ref_merge['re_principle'] = 0
    df_repayment_ref_merge['re_interest'] = 0
    df_repayment_ref_merge['re_service_fee'] = 0
    df_repayment_ref_merge['re_punish'] = 0
    df_repayment_ref_merge['re_relief'] = 0
    df_repayment_ref_merge['re_remain'] = 0
    df_repayment_ref_merge['mitigate_prin'] = 0
    df_repayment_ref_merge['mitigate_inst'] = 0
    df_repayment_ref_merge['mitigate_fee'] = 0
    df_repayment_ref_merge['mitigate_punish'] = 0
    df_repayment_ref_merge['red_package_fee'] = 0
    df_repayment_ref_merge['mitigate_all'] = 0

    # count=1的可以直接拆
    # count>1的需要合并拆
    df_repay_success_single = df_repayment_ref_merge.ix[(df_repayment_ref_merge['repay_status'] == 3) & (df_repayment_ref_merge['count'] == 1)]
    df_repay_success_multi = df_repayment_ref_merge.ix[(df_repayment_ref_merge['repay_status'] == 3) & (df_repayment_ref_merge['count'] > 1)]
    df_repay_no_success_single = df_repayment_ref_merge.ix[(df_repayment_ref_merge['repay_status'] != 3) & (df_repayment_ref_merge['count'] == 1)]
    df_repay_no_success_multi = df_repayment_ref_merge.ix[(df_repayment_ref_merge['repay_status'] != 3) & (df_repayment_ref_merge['count'] > 1)]

    if len(df_repay_success_single) > 0:  # 直接拆
        # 实还本金
        df_repay_success_single['re_principle'] = df_repay_success_single['principle']
        # 实还利息
        df_repay_success_single['re_interest'] = df_repay_success_single['interest']
        # 实还服务费
        df_repay_success_single['re_service_fee'] = df_repay_success_single['service_fee']
        # 实还罚息
        df_repay_success_single['re_punish'] = df_repay_success_single['should_punish'].apply(lambda x: np.round(x, 2))
        # 实还本金+利息+服务费+罚息-还款 的差值
        df_repay_success_single['diff'] = df_repay_success_single['ref_amount'] - (df_repay_success_single['re_principle'] + df_repay_success_single['re_interest'] + df_repay_success_single['re_service_fee'] + df_repay_success_single['re_punish'])
        # 还款少了 催收减免 多了 放到remain
        df_repay_success_single['re_relief'] = df_repay_success_single['diff'].apply(lambda x: np.round(-x, 2) if x < 0 else 0)
        df_repay_success_single['re_remain'] = df_repay_success_single['diff'].apply(lambda x: np.round(x, 2) if x > 0 else 0)
        # 本金减免
        df_repay_success_single['mitigate_prin'] = df_repay_success_single.apply(lambda x: max(np.round(x['re_principle'] - x['ref_amount'], 2), 0),axis=1)
        # 利息减免
        df_repay_success_single['mitigate_inst'] = df_repay_success_single.apply(lambda x: max(x['re_principle'] + x['re_interest'] - x['mitigate_prin'] - x['ref_amount'], 0), axis=1)
        # 服务费减免
        df_repay_success_single['mitigate_fee'] = df_repay_success_single.apply(lambda x: max(
            round(x['re_principle'] + x['re_interest'] + x['re_service_fee'] - x['mitigate_prin'] - x['mitigate_inst'] - x['ref_amount'],2), 0), axis=1)
        # 罚息减免
        df_repay_success_single['mitigate_punish'] = df_repay_success_single.apply(lambda x: max(
            round(x['re_principle'] + x['re_interest'] + x['re_service_fee'] + x['re_punish'] - x['mitigate_prin'] - x[
                'mitigate_inst'] - x['mitigate_fee'] - x['ref_amount'],2), 0), axis=1)
        # #######红包使用前提是：：：减免 > 0 ，没有红包余额的概念#################
        #红包金额减免
        df_repay_success_single.ix[((df_repay_success_single['re_relief'] > 0) & (df_repay_success_single['red_package'] <= df_repay_success_single['re_relief'])), 'red_package_fee'] = \
            (df_repay_success_single.ix[((df_repay_success_single['re_relief'] > 0) & (df_repay_success_single['red_package'] <= df_repay_success_single['re_relief']))])['red_package']
        #催收减免
        df_repay_success_single['mitigate_all'] = np.round(df_repay_success_single['mitigate_prin'] + df_repay_success_single['mitigate_inst'] + df_repay_success_single['mitigate_fee'] + df_repay_success_single['mitigate_punish'] - df_repay_success_single['red_package_fee'],2)
    if len(df_repay_no_success_single) > 0:
        df_repay_no_success_single['re_principle'] = df_repay_no_success_single.apply(lambda x: x['principle'] if x['ref_amount'] > x['principle'] else x['ref_amount'], axis=1)
        df_repay_no_success_single['ref_amount'] = np.round(df_repay_no_success_single['ref_amount'] - df_repay_no_success_single['principle'], 2)
        df_repay_no_success_single.ix[df_repay_no_success_single['ref_amount'] > 0, 're_interest'] = df_repay_no_success_single.ix[df_repay_no_success_single['ref_amount'] > 0].apply(
            lambda x: x['interest'] if x['ref_amount'] > x['interest'] else x['ref_amount'],
            axis=1)
        df_repay_no_success_single['ref_amount'] = np.round(df_repay_no_success_single['ref_amount'] - df_repay_no_success_single['interest'], 2)

        df_repay_no_success_single.ix[df_repay_no_success_single['ref_amount'] > 0, 're_service_fee'] = df_repay_no_success_single.ix[df_repay_no_success_single['ref_amount'] > 0].apply(
            lambda x: x['service_fee'] if x['ref_amount'] > x['service_fee'] else x['ref_amount'],
            axis=1)
        df_repay_no_success_single['ref_amount'] = np.round(df_repay_no_success_single['ref_amount'] - df_repay_no_success_single['service_fee'], 2)

        df_repay_no_success_single.ix[df_repay_no_success_single['ref_amount'] > 0, 're_punish'] = df_repay_no_success_single.ix[df_repay_no_success_single['ref_amount'] > 0].apply(
            lambda x: x['should_punish'] if x['ref_amount'] > x['should_punish'] else x['ref_amount'],
            axis=1)
        df_repay_no_success_single['ref_amount'] = np.round(df_repay_no_success_single['ref_amount'] - df_repay_no_success_single['should_punish'], 2)

        df_repay_no_success_single.ix[df_repay_no_success_single['ref_amount'] > 0, 're_remain'] = df_repay_no_success_single.ix[df_repay_no_success_single['ref_amount'] > 0, 'ref_amount']

    print '-------------------> len(df_repayment_ref_merge): %s <------------------------------------' % (len(df_repayment_ref_merge),)
    print '-------------------> len(df_repay_success_single): %s, len(df_repay_success_multi): %s <------------------------------------' % (len(df_repay_success_single), len(df_repay_success_multi))
    print '-------------------> len(df_repay_no_success_single): %s, len(df_repay_no_success_multi): %s <------------------------------------' % (len(df_repay_no_success_single), len(df_repay_no_success_multi))

    result_3 = pd.DataFrame(columns=columns)
    str1 = df_repay_success_multi.plan_id.unique()
    for i in str1:
        df_repayment_ref_merge = df_repay_success_multi.ix[df_repay_success_multi.plan_id == i]
        b = split_money_3(df_repayment_ref_merge)
        result_3 = result_3.append(b)
    # result_3.to_csv("df_3_2.csv", index=False, columns=columns)
    # df_3_1.to_csv("df_3_1.csv", index=False, columns=columns)

    print '-------------------> split 3, len(result_3): %s <------------------------------------' % (
        len(result_3),)
    result_0 = pd.DataFrame(columns=columns)
    str1 = df_repay_no_success_multi.plan_id.unique()
    for i in str1:
        df_repayment_ref_merge = df_repay_no_success_multi.ix[df_repay_no_success_multi.plan_id == i]
        b = split_money_0(df_repayment_ref_merge)
        result_0 = result_0.append(b)
    # result_0.to_csv("df_0_2.csv", index=False, columns=columns)
    # df_0_1.to_csv("df_0_1.csv", index=False, columns=columns)
    print '-------------------> split 0, len(result_0): %s <------------------------------------' % (
        len(result_0),)

    # result_3.fillna(0, inplace=True)
    # df_3_1.fillna(0, inplace=True)
    # df_0_1.fillna(0, inplace=True)
    # result_0.fillna(0, inplace=True)
    df_list = result_3[up_columns].values.tolist()
    df_list.extend(df_repay_success_single[up_columns].values.tolist())
    df_list.extend(result_0[up_columns].values.tolist())
    df_list.extend(df_repay_no_success_single[up_columns].values.tolist())
    if len(df_list) > 0:
        engine_audit.execute(sql_update, df_list)
    print '-------------------> update len(df_list): %s <------------------------------------' % (
        len(df_list),)
