/*
 * @Author: Kane
 * @Date: 2023-03-17 15:17:44
 * @LastEditors: Kane
 * @FilePath: /task_schedule/src/utils/archievement.ts
 * @Description: 请求业绩数据相关的方法。
 *
 * Copyright (c) ${2022} by Kane, All Rights Reserved.
 */
import { service as instance } from "./api/request.ts";
import { API_URL } from "./api/config.ts";
import { type Department } from "../types/cpicxim/Department.ts";
import { type TelSaler } from "../types/cpicxim/TelSaler.ts";
import { type AxiosResponse } from "axios";

interface DepartmentArchievement // 定义业绩对象的结构
{
    success: boolean;
    message: string;
    total_archievement: number;
    mensual_archievement_list: number[];
    insurance_renewal_rate: string;
    insurance_renewal_rate_target: string;
    attaching_rate: string;
    attaching_rate_target: string;
    leading_reward_gainers: string[];
    advance_reward_gainers: string[];
    backward_list: string[];
}

interface CallerArchievement // 坐席业绩对象
{
    success: boolean;
    message: string;
    total_archievement: number;
    moto_premium_present_month: number;
    mensual_archievement_list: number[];
    insurance_renewal_rate: string;
    attaching_rate: string;
}

interface MenusalArchievementItem // 每月业绩清单的项目
{
    month: number;
    premium: string;
}

/**
 * 获取部门业绩数据，并调用回调函数进行渲染。
 * @param departmentInfo 作为请求参数的部门参数对象
 * @param render 用于给组件更新数据的回调函数，用DepartmentArchievement对象调用；
 */
function queryDepartmentArchievement( departmentInfo: Department, render: any ): void
{
    // 默认的部门业绩对象
    const archievement: DepartmentArchievement = {
        success: false,
        message: "",
        total_archievement: 0,
        mensual_archievement_list: [],
        insurance_renewal_rate: "",
        insurance_renewal_rate_target: "",
        attaching_rate: "",
        attaching_rate_target: "",
        leading_reward_gainers: [],
        advance_reward_gainers: [],
        backward_list: [],
    };

    instance.request({
        method: "post",
        url: API_URL.URL_DEPARTMENT_ARCHIEVEMENT,
        data: departmentInfo,
    })
        // 请求结束，将请求的结果写入业绩对象，然后调用功能渲染函数。
        .then(( response ) =>
        {
            const data = response.data ?? {};

            archievement.success = data.success ?? false;
            archievement.message = data.message ?? "服务器没有返回调用结果消息，请检查日志！";
            archievement.total_archievement = data.total_archievement;
            archievement.mensual_archievement_list = [];
            archievement.insurance_renewal_rate = data.insurance_renewal_rate ?? "0.0";
            archievement.insurance_renewal_rate_target = data.insurance_renewal_rate_target ?? "0.0";
            archievement.attaching_rate = data.attaching_rate ?? "0.0";
            archievement.attaching_rate_target = data.attaching_rate_target ?? "0.0";
            archievement.leading_reward_gainers = data.leading_reward_gainers ?? [];
            archievement.advance_reward_gainers = data.advance_reward_gainers ?? [];
            archievement.backward_list = data.backward_list ?? [];

            // 转换每月业绩数据，用month排序以后，保留premium。
            data.mensual_archievement_list.sort(( a: any, b: any ) => a.month - b.month );
            data.mensual_archievement_list.forEach(( item: any ) =>
            {
                archievement.mensual_archievement_list.push( item.premium ); // eslint-disable-line
            });

            console.log( "每月业绩", archievement );

            // 调用渲染函数
            if ( render !== undefined )
            {
                render( archievement );
            }
        })
        // 请求失败，将失败原因写入业绩对象，调用渲染函数
        .catch(( error ) =>
        {
            archievement.success = false;
            archievement.message = String( error );

            // 调用渲染函数
            if ( render !== undefined )
            {
                render( archievement );
            }

            console.log( `queryDepartmentArchievement:查询部门${departmentInfo.departmentCode}业绩失败，原因${error}` );
        });
}

/**
 * 查询坐席的业绩，并调用渲染函数.
 * 1、请求坐席业绩的数据
 * 2、对每月业绩清单进行检查，如果有缺少则用0代替，检查的结果是12个月的清单，让调用者自己截断；
 * 3、将检查后的清单，写入到业绩对象中，只写金额；
 * 4、即使请求失败，也将失败的message写入业绩对象，调用渲染函数；
 * @param callerInfo 坐席的信息参数，用于请求业绩；
 * @param render 渲染函数，用业绩对象CallerArchievement作为参数；
 */
function queryCallerArchievement( callerInfo: TelSaler, render: any ): void
{
    const caller = {
        callerCode: callerInfo.telSalerCode,
        callName: callerInfo.telSalerName,
    };

    // 默认的业绩对象
    const callArchievement: CallerArchievement = {
        success: false,
        message: "",
        total_archievement: 0,
        moto_premium_present_month: 0,
        mensual_archievement_list: [],
        insurance_renewal_rate: "0.0",
        attaching_rate: "0.0",
    };

    // 发送请求
    instance.request({
        method: "post",
        url: API_URL.URL_CALLER_ARCHIEVEMENT,
        data: caller,
    })
        // 请求完成时
        .then(( response: AxiosResponse<any, any> ) =>
        {
            const data = response.data ?? {};

            console.log( "个人业绩数据", data );

            callArchievement.success = data.success ?? false;
            callArchievement.message = data.message ?? "服务器没有返回调用结果消息，请检查日志！";
            callArchievement.total_archievement = data.total_archievement ?? 0;
            callArchievement.moto_premium_present_month = data.motoPremiumPresentMonth ?? 0;
            callArchievement.mensual_archievement_list = [];
            callArchievement.insurance_renewal_rate = data.insurance_renewal_rate ?? "0.0";
            callArchievement.attaching_rate = data.attaching_rate ?? "0.0";

            // 检查业绩清单有没有缺漏，缺漏的用0补上
            const checkedList = checkMensualArchievement( data.mensual_archievement_list ); // eslint-disable-line

            // 排序一下
            checkedList.sort(( a: MenusalArchievementItem, b: MenusalArchievementItem ): number =>
            {
                return a.month - b.month;
            });

            // 将排序后的每月业绩写到业绩对象中
            checkedList.forEach(( item: MenusalArchievementItem ): void =>
            {
                const premium = Number( item.premium );

                callArchievement.mensual_archievement_list.push( premium );
            });

            // 调用渲染函数
            if ( render !== undefined )
            {
                render( callArchievement );
            }

            console.log( `queryCallerArchievement查询结果${data}` );
        })
        // 请求失败，将失败的原因保存到message属性，调用渲染函数
        .catch(( error: any ) =>
        {
            callArchievement.success = false;
            callArchievement.message = String( error );

            // 调用渲染函数
            if ( render !== undefined )
            {
                render( callArchievement );
            }

            console.log( `queryCallerArchievement:查询坐席${callerInfo.telSalerCode}业绩失败，原因${error}` );
        });
}

/**
 * 检查服务器返回的每月业绩数组，检查是否有缺漏，缺少的月份业绩用0代替。
 * 检查的结果是12个月的清单，由调用者自己进行截断。
 * @param mensualArchievementList MenusalArchievementItem类型的数组，为业绩清单
 * @returns 返回MenusalArchievementItem数组，为检查过的清单
 */
function checkMensualArchievement( mensualArchievementList: MenusalArchievementItem[]): MenusalArchievementItem[]
{
    const checkedList: MenusalArchievementItem[] = [];
    const itemMap = new Map();

    itemMap.set( 1, "0" );
    itemMap.set( 2, "0" );
    itemMap.set( 3, "0" );
    itemMap.set( 4, "0" );
    itemMap.set( 5, "0" );
    itemMap.set( 6, "0" );
    itemMap.set( 7, "0" );
    itemMap.set( 8, "0" );
    itemMap.set( 9, "0" );
    itemMap.set( 10, "0" );
    itemMap.set( 11, "0" );
    itemMap.set( 12, "0" );

    mensualArchievementList.forEach(( item: MenusalArchievementItem ): void =>
    {
        itemMap.set( item.month, item.premium );
    });

    itemMap.forEach(( value, key, map ) =>
    {
        const item: MenusalArchievementItem = {
            month: key,
            premium: value,
        };

        checkedList.push( item );
    });

    return checkedList;
}

export {
    queryDepartmentArchievement,
    queryCallerArchievement,
    type DepartmentArchievement,
    type CallerArchievement
};
