# -*- coding: UTF-8 -*-
"""
@author:Zongxi.Li
@file:statement_service.py
@time:2021/02/01
"""
import json
import pandas as pd
import numpy as np

from datetime import datetime, date
from decimal import Decimal
from app.api.engine import tamp_order_engine, tamp_user_engine, tamp_diagnose_app_engine, TAMP_SQL
# from app.service.data_service_v2_1 import *
from app.service.customer import get_customer_list
from app.service.portfolio_diagnose import get_fund_name


class DateEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, (datetime, date)):
            return obj.__str__()
        if isinstance(obj, Decimal):
            return obj.__float__()
        return json.JSONEncoder.default(self, obj)


def get_order_info(user_id):
    with TAMP_SQL(tamp_diagnose_app_engine) as tamp_diagnose_app:
        tamp_diagnose_app_session = tamp_diagnose_app.session
        sql_user = """select f1.fund_id, f2.realname, f3.customer_name, f1.customer_id, f3.valueSex,f1.type,f1.order_type,f1.pay_date,f1.subscription_fee,f1.confirm_share_date,f1.confirm_share,f1.confirm_amount,f1.nav,f1.folio_name from tamp_diagnose_app.customer_order_view f1, tamp_user.user_info f2,tamp_diagnose_app.customer_view f3   where f2.id=f1.user_id and f3.id=f1.customer_id  and f1.delete_tag=0 and user_id='{}'""".format(
            user_id)
        cur = tamp_diagnose_app_session.execute(sql_user)
        data = cur.fetchall()
        order_df = pd.DataFrame(list(data),
                                columns=['fund_id', 'username', 'customer_name', 'customer_id', 'valueSex', 'type',
                                         'order_type',
                                         'pay_date',
                                         'subscription_fee', 'confirm_share_date', 'confirm_share',
                                         'confirm_amount', 'nav', 'folio_name'])
    return order_df


def get_provision_info(user_id):
    with TAMP_SQL(tamp_order_engine) as tamp_order, TAMP_SQL(tamp_user_engine) as tamp_user:
        tamp_order_session = tamp_order.session
        # sql = """select f1.ifa_id, f1.customer_id, f1.fund_id, f1.fund_nav,
        # f1.fund_nav_date, f1.predict_date, f1.pro_date, f1.manage_predict_fee, f1.permc_exc_predict_fee, f1.permc_rem_fee,
        # f1.recommend_ifa_id, f1.recommend_fee, f1.permc_recommend_fee, f1.incentive_fee_ratio, f1.retention_shares
        # from ifa_provision_day_info as f1 where f1.ifa_id='{}'""".format(user_id)
        sql = """SELECT * FROM `ifa_provision_day_info` WHERE `ifa_id` = '{}'""".format(user_id)
        cur = tamp_order_session.execute(sql)
        data = cur.fetchall()
        provision_df = pd.DataFrame(list(data),
                                columns=['id', 'ifa_id', 'customer_id', 'fund_id', 'order_id', 'fund_nav', 'fund_nav_date',
                                         'predict_date', 'pro_date','pro_type',
                                         'manage_predict_fee', 'permc_exc_predict_fee', 'permc_rem_predict_fee',
                                         'manage_fee', 'permc_exc_fee','permc_rem_fee', 'recommend_ifa_id',
                                         'recommend_fee','permc_recommend_fee', 'incentive_fee_ratio',
                                         'deduction','retention_shares','status'])
    return provision_df


def get_end_date(year, month):
    if month == 12:
        end_date = datetime(year=year + 1, month=1, day=1)
    else:
        end_date = datetime(year=year, month=month + 1, day=1)
    return end_date


def get_month_list(quarter, year):
    if quarter == 4:
        year = year - 1
    else:
        year = year

    month_list = range((quarter - 1) * 3 + 1, quarter * 3 + 1)
    return year, month_list


def type2note(type):
    type2note_dict = {1: "申购",
                      2: "追加",
                      3: "赎回",
                      4: "分红再投",
                      5: "现金分红"}
    return type2note_dict.get(type)


def cal_total_amount(df):
    purchase_amount = df[df['order_type'].isin([1, 2])]['confirm_amount'].sum()
    redem_amount = df[df['order_type'] == 3]['confirm_amount'].sum()
    total_amount = purchase_amount - redem_amount
    return total_amount


def num2chinese(number):
    num2chinese_dict = {1: '一',
                        2: '二',
                        3: '三',
                        4: '四'}
    return num2chinese_dict.get(number)


class Statement(object):
    def __init__(self, user_id, year, month):
        self.user_id = user_id
        self.year = year
        self.month = month
        self.quarter = (self.month - 1) // 3
        if self.quarter == 0:
            self.quarter = 4
        self.ifa_order = self.order_history()
        self.ifa_provision = self.provision_history()

    def order_history(self):
        ifa_order = get_order_info(self.user_id)
        end_date = get_end_date(self.year, self.month)
        order_history = ifa_order[ifa_order['pay_date'] < end_date]
        # ifa_order['fund_name'] = ifa_order['fund_id'].apply(lambda x: get_fund_name(x, fund_type=2).values[0][0])
        return order_history

    def provision_history(self):
        ifa_provision = get_provision_info(self.user_id)
        end_date = get_end_date(self.year, self.month)
        provision_history = ifa_provision[ifa_provision['predict_date'] < end_date.date()]
        return provision_history

    def process_provision(self):
        year, month_list = get_month_list(self.quarter, self.year)
        start_date = date(year=year, month=min(month_list), day=1)
        end_date = get_end_date(year, max(month_list))
        provision_quarterly = self.ifa_provision[
            (self.ifa_provision['predict_date'] >= start_date) &
            (self.ifa_provision['predict_date'] < end_date.date())]
        processed_provision = list(provision_quarterly.groupby([provision_quarterly.customer_id,
                                   provision_quarterly.fund_id]))
        return processed_provision

    def trade_record(self):
        ifa_cus_order_info = list(self.ifa_order.groupby(self.ifa_order.customer_id))

        trade_record_data = []
        for customer in ifa_cus_order_info:
            customer_df = customer[1]
            df_length = customer_df['fund_id'].count()
            detail = []

            for i in range(df_length):
                detail.append({'fund': customer_df['fund_id'].values[i],
                               'pay_date': np.datetime_as_string(customer_df['pay_date'].values[i], unit='D'),
                               'confirm_share_date': np.datetime_as_string(customer_df['confirm_share_date'].values[i],
                                                                           unit='D'),
                               'confirm_amount': customer_df['confirm_amount'].values[i],
                               'nav': customer_df['nav'].values[i],
                               'confirm_share': customer_df['confirm_share'].values[i],
                               'note': type2note(customer_df['order_type'].values[i])
                               })

            purchase_amount = customer_df[customer_df['order_type'].isin([1, 2])]['confirm_amount'].sum()
            redam_amount = customer_df[customer_df['order_type'] == 3]['confirm_amount'].sum()
            total_amount = purchase_amount - redam_amount
            trade_record_data.append({'customer': customer_df['customer_name'].values[0],
                                      'total_amount': Decimal(round(float(total_amount) / 10000.0, 2)),
                                      'detail': detail})

        if len(ifa_cus_order_info) == 0:
            trade_record_data = [{'customer': '',
                                  'total_amount': '',
                                  'detail': [{'fund': '',
                                              'pay_date': '',
                                              'confirm_share_date': '',
                                              'confirm_amount': '',
                                              'nav': '',
                                              'confirm_share': '',
                                              'note': ''}]}]
        return trade_record_data

    def month_remain(self):
        year, month_list = get_month_list(self.quarter, self.year)
        month_remain_data = {}
        month_detail = []
        quarter_amount = 0
        for month in month_list:
            end_date = get_end_date(year, month)
            order_history = self.ifa_order[self.ifa_order['pay_date'] < end_date]
            df_length = order_history['fund_id'].count()

            if df_length > 0:
                month_amount = cal_total_amount(order_history)
            else:
                month_amount = 0

            single_month = {'month': str(month) + '月', 'month_amount': month_amount}
            quarter_amount += month_amount
            month_detail.append(single_month)

        quarter = num2chinese(self.quarter)
        month_detail.append(
            {'month': quarter + '季度月均存量', 'month_amount': Decimal(round(float(quarter_amount) / 3.0, 2))})
        month_remain_data['month_detail'] = month_detail

        bonus_policy = []
        bonus_policy.append({'month_achieve': '达到1000万以上', 'bonus_policy_item': '标准管理费分成+0.1%'})
        month_remain_data['bonus_policy'] = bonus_policy

        bonus_image = 'https://tamp-pro.oss-cn-shanghai.aliyuncs.com/upload/CS_FILE_RECORD16081436133319.png'
        month_remain_data['bonus_image'] = bonus_image
        return month_remain_data

    def subscription_fee(self):
        year, month_list = get_month_list(self.quarter, self.year)

        subscription_data = {}
        customer_detail = []
        total_before_tax = 0
        total_after_tax = 0
        start_date = datetime(year=year, month=min(month_list), day=1)
        end_date = get_end_date(year, max(month_list))
        order_quarterly = self.ifa_order[(self.ifa_order['pay_date'] >= start_date) &
                                         (self.ifa_order['pay_date'] < end_date) &
                                         (self.ifa_order['order_type'] != 4)]
        ifa_cus_order_monthly = list(order_quarterly.groupby(order_quarterly.customer_id))

        for customer in ifa_cus_order_monthly:
            customer_df = customer[1]
            df_length = customer_df['fund_id'].count()
            before_tax = 0
            after_tax = 0
            detail = []
            for i in range(df_length):
                try:
                    tax_rate = get_tax_rate()
                except:
                    tax_rate = 0

                detail.append({'fund': customer_df['fund_id'].values[i],
                               'confirm_amount': customer_df['confirm_amount'].values[i],
                               'pay_date': np.datetime_as_string(customer_df['pay_date'].values[i], unit='D'),
                               'subscription_fee': customer_df['subscription_fee'].values[i],
                               'tax': customer_df['subscription_fee'].values[i] * tax_rate
                               })

                before_tax += customer_df['subscription_fee'].values[i]
                after_tax += customer_df['subscription_fee'].values[i] * (1 - tax_rate)

            customer_detail.append({'customer': customer_df['customer_name'].values[0],
                                    'before_tax': Decimal(round(float(before_tax), 2)),
                                    'after_tax': Decimal(round(float(after_tax), 2)),
                                    'detail': detail})
            total_before_tax += before_tax
            total_after_tax += after_tax

        subscription_data['total_before_tax'] = total_before_tax
        subscription_data['total_tax'] = total_before_tax - total_after_tax
        subscription_data['total_after_tax'] = total_after_tax
        subscription_data['customer_detail'] = customer_detail

        if len(ifa_cus_order_monthly) == 0:
            subscription_data['customer_detail'] = [{'customer': '',
                                                     'before_tax': '',
                                                     'after_tax': '',
                                                     'detail': [{'fund': '',
                                                                 'confirm_amount': '',
                                                                 'pay_date': '',
                                                                 'subscription_fee': '',
                                                                 'tax': ''}]}]
        return subscription_data

    def manage_fee(self):
        manage_data = {}
        total_before_tax = 0
        total_after_tax = 0
        customer_detail = []

        processed_provision = self.process_provision()
        for customer_fund in processed_provision:
            customer_fund_df = customer_fund[1]
            df_length = customer_fund_df['predict_date'].count()
            before_tax = 0
            after_tax = 0
            detail = []
            for i in range(df_length):
                try:
                    tax_rate = get_tax_rate()
                except:
                    tax_rate = 0
                detail.append({
                               'hold_share': customer_fund_df['retention_shares'].values[i],
                               'date': customer_fund_df['predict_date'].values[i].strftime('%Y-%m-%d'),
                               'manage_fee': customer_fund_df['manage_fee'].values[i],
                               'tax': customer_fund_df['manage_fee'].values[i] * tax_rate
                               })

                before_tax += customer_fund_df['manage_fee'].values[i]
                after_tax += customer_fund_df['manage_fee'].values[i] * (1 - tax_rate)

            customer_detail.append({'customer': customer_fund_df['customer_id'].values[0],
                                    'fund': customer_fund_df['fund_id'].values[0],
                                    'before_tax': round(float(before_tax), 2),
                                    'after_tax': round(float(after_tax), 2),
                                    'detail': detail})
            total_before_tax += before_tax
            total_after_tax += after_tax

        manage_data['total_before_tax'] = total_before_tax
        manage_data['total_tax'] = total_before_tax - total_after_tax
        manage_data['total_after_tax'] = total_after_tax
        manage_data['customer_detail'] = customer_detail

        if len(processed_provision) == 0:
            manage_data['customer_detail'] = [{'customer': '',
                                               'before_tax': '',
                                               'after_tax': '',
                                               'detail': [{'fund': '',
                                                           'confirm_amount': '',
                                                           'pay_date': '',
                                                           'manage_fee': '',
                                                           'tax': ''}]}]
        return manage_data

    def bill_month(self):
        return str(self.year) + '年' + str(self.month) + '月'

    def user_name(self):
        return "王菲女士"

    def summary(self):
        summary_data = {}
        summary_data['bill_month'] = self.bill_month()
        summary_data['user_name'] = self.user_name()
        summary_data['quarter'] = num2chinese(self.quarter)
        summary_data['trade_record'] = self.trade_record()
        summary_data['month_remain'] = self.month_remain()
        summary_data['subscription_fee'] = self.subscription_fee()
        summary_data['manage_fee'] = self.manage_fee()
        # summary_data['manage_fee'] = {'total_before_tax': Decimal('20000.00'),
        #                               'total_after_tax': Decimal('20000.00'),
        #                               'total_tax': Decimal('0.00'),
        #                               'customer_detail':
        #                                   [{'customer': "王小帅",
        #                                     'before_tax': 2000.01,
        #                                     'detail': [
        #                                         {'date': "2020-09-01",
        #                                          'hold_share': Decimal('2000.00'),
        #                                          'nav': Decimal(1.0083),
        #                                          'manage_fee_day': Decimal('10.00')}
        #                                     ]}]}
        summary_data['carry'] = {'total_before_tax': Decimal('20000.00'),
                                 'total_after_tax': Decimal('20000.00'),
                                 'total_tax': Decimal('0.00'),
                                 'fund_detail':
                                     [{'fund': "无量",
                                       'before_tax': 2000.01,
                                       'detail': [
                                           {'customer': "王小帅",
                                            'order_type': "申购",
                                            'confirm_date': "2020-09-01",
                                            'native_amount': Decimal('10000000.00'),
                                            'nav': Decimal(1.0083),
                                            'provision_date': "2020-09-01",
                                            'provision_carry': Decimal('10000000.00')}]}]}
        summary_data['incentive'] = {'total_before_tax': Decimal('20000.00'),
                                     'total_after_tax': Decimal('20000.00'),
                                     'total_tax': Decimal('0.00'),
                                     'customer_detail':
                                         [{
                                             'customer': '熊大',
                                             'fund': "无量",
                                             'before_tax': 2000.01,
                                             'detail': [
                                                 {
                                                     'date': "2020-09-01",
                                                     'hold_share': Decimal('10000000.00'),
                                                     'nav': Decimal(1.0083),
                                                     'incentive_day': Decimal(10.00)}]}]}
        summary_data['recommend_bonus'] = {'total_before_tax': Decimal('20000.00'),
                                           'total_after_tax': Decimal('20000.00'),
                                           'total_tax': Decimal('0.00'),
                                           'referral_detail':
                                               [{'referral': "王铁柱",
                                                 'customer': '熊大',
                                                 'fund': "无量",
                                                 'before_tax': 2000.01,
                                                 'detail': [
                                                     {
                                                         'date': "2020-09-01",
                                                         'hold_share': Decimal('10000000.00'),
                                                         'nav': Decimal(1.0083),
                                                         'recommend_bonus_day': Decimal(10.00)}]}]}

        summary_data['summary'] = {'total_after_tax': Decimal('1000000.00'),
                                   'detail': [{'item': "已结算申购费用", 'amount': Decimal('100000.00'), 'note': ''},
                                              {'item': "已结算管理费用", 'amount': Decimal('100000.00'), 'note': ''},
                                              {'item': "已结算业绩报酬费用", 'amount': Decimal('100000.00'), 'note': ''},
                                              {'item': "已结算业绩激励奖金", 'amount': Decimal('100000.00'), 'note': ''},
                                              {'item': "已结算推荐费", 'amount': Decimal('100000.00'), 'note': ''},
                                              {'item': "2020年三季度待结算佣金", 'amount': Decimal('100000.00'), 'note': ''}
                                              ]}
        return summary_data


if __name__ == '__main__':

    ret = Statement(user_id='USER_INFO15914346866762', year=2020, month=12).summary()
    print(json.dumps(ret, cls=DateEncoder, ensure_ascii=False))
