package com.gic.haoban.manage.web.controller.data;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import com.gic.api.base.commons.Page;
import com.gic.api.base.commons.ServiceResponse;
import com.gic.clerk.api.dto.ClerkListDTO;
import com.gic.clerk.api.service.ClerkService;
import com.gic.commons.util.DataApiUtils;
import com.gic.commons.util.EntityUtil;
import com.gic.commons.util.GlobalVar;
import com.gic.commons.util.HttpClient;
import com.gic.commons.util.data.CrossDateUtils;
import com.gic.commons.webapi.reponse.RestResponse;
import com.gic.enterprise.api.dto.EnterpriseSettingDTO;
import com.gic.enterprise.api.dto.EnterpriseSourceChannelDTO;
import com.gic.enterprise.api.dto.data.DataIndexEvaluateLogDTO;
import com.gic.enterprise.api.dto.data.DataIndexExplainDTO;
import com.gic.enterprise.api.enums.PlatformChannelEnum;
import com.gic.enterprise.api.enums.PlatformEnum;
import com.gic.enterprise.api.service.EnterpriseChannelApiService;
import com.gic.enterprise.api.service.EnterpriseService;
import com.gic.enterprise.api.service.data.DataIndexApiService;
import com.gic.enterprise.service.CustomSettingApiService;
import com.gic.haoban.manage.web.qo.data.*;
import com.gic.haoban.manage.web.utils.DateFillUtils;
import com.gic.haoban.manage.web.utils.StoreAuthUtils;
import com.gic.haoban.manage.web.vo.data.DataMemberExtendVO;
import com.gic.haoban.manage.web.vo.data.SalesStructureVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据调用通用接口
 * @Author guojx
 * @Date 2023/11/14 10:56
 */
@Controller
@RequestMapping("data")
@Slf4j
public class DataController {
    @Autowired
    private StoreAuthUtils storeAuthUtils;
    @Autowired
    private DataIndexApiService dataIndexApiService;
    @Autowired
    private CustomSettingApiService customSettingApiService;
    @Autowired
    private EnterpriseChannelApiService enterpriseChannelApiService;
    @Autowired
    private EnterpriseService enterpriseService;
    @Autowired
    private ClerkService clerkService;

    private String isProd() {
        Config config = ConfigService.getConfig("COMMON.gic-properties");
        String env = config.getProperty("environment.value", "") ;
        return env;
    }

    /**
     * 获取销售和会员的导购列表数据
     * 返回字段具体看数据组接口文档：http://yapi.gicdev.com/project/5177/interface/api/179038
     * http://yapi.gicdev.com/project/5177/interface/api/179362
     * @param qo
     * @return
     */
    @RequestMapping(value = "list-clerk-data")
    @ResponseBody
    public RestResponse listClerkData(@RequestBody ClerkListQO qo) {
        String params = qo.getParams();
        JSONObject jsonObject = JSONObject.parseObject(params);
        String enterpriseId = jsonObject.getString("enterpriseId");
        String storeId = jsonObject.getString("storeId");
        if (StringUtils.isBlank(enterpriseId) || StringUtils.isBlank(storeId)) {
            return RestResponse.failure("-1", "企业id或者门店id为空");
        }
        List<String> deleteList = new ArrayList<>();
        List<String> normalList = new ArrayList<>();
        List<String> allList = new ArrayList<>();
        List<ClerkListDTO> clerkList = clerkService.getClerkByStoreIdOfAllStatus(enterpriseId, storeId);
        if (CollectionUtils.isNotEmpty(clerkList)) {
            for (ClerkListDTO dto : clerkList) {
                Integer status = dto.getStatus();
                allList.add(dto.getClerkId());
                if (status != null && status == 0) {
                    deleteList.add(dto.getClerkId());
                } else {
                    normalList.add(dto.getClerkId());
                }
            }
        }
        if (CollectionUtils.isEmpty(deleteList)) {
            deleteList.add("no_delete_clerk_id");
        }
        if (CollectionUtils.isEmpty(normalList)) {
            deleteList.add("no_normal_clerk_id");
        }
        if (CollectionUtils.isEmpty(allList)) {
            deleteList.add("no_clerk_id");
        }
        Integer clerkType = qo.getQueryDataType();
        boolean isSale = clerkType == 1;
        Integer pageNum = jsonObject.getInteger("pageNum");
        String apolloKey = qo.getApolloKey();

        boolean isFirstPage = pageNum == 1;
        if (isSale) {
            jsonObject.put("storeGroup", 9);
        } else {
            jsonObject.put("groupType", 9);
        }
        jsonObject.put("clerkId", normalList.stream().collect(Collectors.joining(",")));
        Map<String, Object> res = DataApiUtils.http(jsonObject.toJSONString(), apolloKey);
        Page page = DataApiUtils.getPageData(res);
        List<JSONObject> pageList = DataApiUtils.getPageList(res);
        if (CollectionUtils.isEmpty(pageList)) {
            pageList = new ArrayList<>();
        }
        if (isFirstPage) {
            if (isSale) {
                jsonObject.put("storeGroup", 7);
            } else {
                jsonObject.put("groupType", 8);
            }
            jsonObject.put("clerkId", allList.stream().collect(Collectors.joining(",")));
            JSONObject total = getTotalJson(jsonObject, apolloKey);
            if (total != null) {
                pageList.add(0, total);
            }
        }
        int totalPage = page.getTotalCount() % page.getPageSize() != 0 ? page.getTotalCount() / page.getPageSize() + 1 : page.getTotalCount() / page.getPageSize();
        boolean isLastPage = totalPage == pageNum;
        if (isLastPage) {
//                最后一页添加离职导购数据
            jsonObject.put("clerkId", deleteList.stream().collect(Collectors.joining(",")));
            if (isSale) {
                jsonObject.put("storeGroup", 7);
            } else {
                jsonObject.put("groupType", 8);
            }
            JSONObject deleteTotal = getTotalJson(jsonObject, apolloKey);
            if (deleteTotal != null) {
                deleteTotal.put("clerkName", "离职导购（汇总）");
                pageList.add(deleteTotal);
            }
        }

        return RestResponse.successResult(page);
    }

    /**
     * 会员封装数据
     * @param qo
     * @return
     */
    @RequestMapping(value = "get-member-data")
    @ResponseBody
    public RestResponse<List<DataMemberExtendVO>> getMemberData(@RequestBody DataMemberExtendQO qo) {
        if (StringUtils.isBlank(qo.getEnterpriseId())) {
            return RestResponse.failure("-1", "企业id不能为空");
        }
        String params = qo.getParams();
        JSONObject jsonObject = JSONObject.parseObject(params);
        if (jsonObject == null) {
            jsonObject = new JSONObject();
        }
        jsonObject.put("enterpriseId", qo.getEnterpriseId());
        List<String> storeIdList = new ArrayList<>();
        String storeId = qo.getStoreId();
        if (StringUtils.isBlank(storeId)) {
            storeIdList = storeAuthUtils.queryClerkStoreIds(qo.getClerkId(), qo.getWxEnterpriseId());
        } else {
            storeIdList.add(storeId);
        }
        if (CollectionUtils.isNotEmpty(storeIdList)) {
            //区经有全部门店权限
            jsonObject.put("storeId", storeIdList.stream().collect(Collectors.joining(",")));
        }
        qo.setParams(jsonObject.toJSONString());
        Map<String, String> head = new HashMap<>();
        head.put("Content-Type", "application/json");
        String mainHost = GlobalVar.ctxPropertiesMap.get("gicweb_service_host");
        mainHost = mainHost.replace("gicweb", "");
        //是否是开发环境
        boolean isDev = mainHost.contains("gicdev");
        if (isDev) {
            //http://gicdev.demogic.com/
            mainHost = GlobalVar.ctxPropertiesMap.get("gicweb_service_host_old");
        }
        String url = mainHost + "api-report/data-extend/get-member-data";

        JSONObject httpJson = new JSONObject();
        httpJson.put("params", jsonObject.toJSONString());
        httpJson.put("dateType", qo.getDateType());
        httpJson.put("realFlag", qo.getRealFlag());
        httpJson.put("totalMemberFlag", qo.getTotalMemberFlag());
        httpJson.put("channelCodeList", qo.getChannelCodeList());
        Map<String, Object> res = HttpClient.getWinxinResByJson(url, httpJson.toJSONString(), head);

        RestResponse rest = JSONObject.parseObject(JSONObject.toJSONString(res), RestResponse.class);
        if (isSuccess(rest)) {
            List<DataMemberExtendVO> list = JSONObject.parseArray(JSON.toJSONString(rest.getResult()), DataMemberExtendVO.class);
            rest.setResult(list);
        }
        return rest;
    }

    /**
     * 销售结构接口
     * @param qo
     * @return
     */
    @RequestMapping(value = "sales-structure")
    @ResponseBody
    public RestResponse<List<SalesStructureVO>> salesStructure(@RequestBody SalesStructureQO qo) {
        Integer salesStructureType = qo.getSalesStructureType();
        String apolloKey = "data_sales_perf_mbr_type_overview";
        switch (salesStructureType) {
            case 1:
                apolloKey = "data_sales_perf_mbr_type_overview";
                break;
            case 2:
                apolloKey = "data_sales_perf_birth_type_overview";
                break;
            case 3:
                apolloKey = "data_sales_perf_grade_type_overview";
                break;
            default:
        }
        JSONObject jsonParam = new JSONObject();
        jsonParam.put("enterpriseId", qo.getEnterpriseId());
        if (StringUtils.isNotBlank(qo.getStartDate())) {
            jsonParam.put("startDate", qo.getStartDate());
        }
        if (StringUtils.isNotBlank(qo.getEndDate())) {
            jsonParam.put("endDate", qo.getEndDate());
        }
        getAuthStore(qo.getStoreId(), qo.getClerkId(), qo.getWxEnterpriseId(), jsonParam);
        jsonParam.put("groupType", 1);
        Map<String, Object> res = DataApiUtils.http(jsonParam.toJSONString(), apolloKey);
        List<JSONObject> list = DataApiUtils.getDataList(res);
        if (list == null) {
            list = new ArrayList<>();
        } else {
            if (list.size() > 0) {
                list.get(0).put("mbrType", "合计");
            }
        }
        jsonParam.put("groupType", 2);
        res = DataApiUtils.http(jsonParam.toJSONString(), apolloKey);
        List<JSONObject> childList = DataApiUtils.getDataList(res);
        if (CollectionUtils.isNotEmpty(childList)) {
            list.addAll(childList);
        }
        List<SalesStructureVO> voList = JSONObject.parseArray(JSON.toJSONString(list), SalesStructureVO.class);
        if (voList.size() > 1) {
            SalesStructureVO total = voList.get(0);
            Double payAmt = total.getPayAmt();
            Integer csmeNum = total.getCsmeNum();
            Integer effOrderCnt = total.getEffOrderCnt();
            for (int i = 1; i < voList.size(); i ++) {
                SalesStructureVO vo = voList.get(i);
                if (payAmt != null && payAmt > 0) {
                    vo.setPayAmtRate(divide(vo.getPayAmt(),payAmt));
                }
                if (csmeNum != null && csmeNum > 0) {
                    vo.setCsmeNumRate(divide(vo.getCsmeNum(),csmeNum));
                }
                if (effOrderCnt != null && effOrderCnt > 0) {
                    vo.setEffOrderCntRate(divide(vo.getEffOrderCnt(),effOrderCnt));
                }
            }
        }
        return RestResponse.successResult(voList);
    }

    public static String divide(Object a, Object b) {
        if (a == null) {
            return "0.00";
        }
        BigDecimal bd = new BigDecimal(a.toString());
        bd = bd.multiply(new BigDecimal(100));
        bd = bd.divide(new BigDecimal(b.toString()), 2, BigDecimal.ROUND_HALF_UP);
//        bd = bd.setScale(2, BigDecimal.ROUND_HALF_UP);
        return bd.toString();
    }



    private void getAuthStore(String storeId, String clerkId, String wxEnterpriseId, JSONObject jsonObject) {
        List<String> storeIdList = new ArrayList<>();
        if (StringUtils.isBlank(storeId)) {
            storeIdList = storeAuthUtils.queryClerkStoreIds(clerkId, wxEnterpriseId);
        } else {
            storeIdList.add(storeId);
        }
        if (CollectionUtils.isNotEmpty(storeIdList)) {
            //区经有全部门店权限
            jsonObject.put("storeId", storeIdList.stream().collect(Collectors.joining(",")));
        }
    }

    /**
     * 数据统一调用接口
     * 参数与返回字段查询数据组的yapi的对应文档
     * @param qo
     * @return
     */
    @RequestMapping(value = "handle")
    @ResponseBody
    public RestResponse handle(@RequestBody HandleQO qo) {
        String params = qo.getParams();
        JSONObject jsonObject = JSONObject.parseObject(params);
        if (jsonObject == null) {
            jsonObject = new JSONObject();
        }
        if (StringUtils.isNotBlank(qo.getEnterpriseId())) {
            jsonObject.put("enterpriseId", qo.getEnterpriseId());
        }
        String storeIdParam = jsonObject.getString("storeId");
        boolean hasStoreId = StringUtils.isNotBlank(storeIdParam);
        if (!hasStoreId) {
            getAuthStore(qo.getStoreId(), qo.getClerkId(), qo.getWxEnterpriseId(), jsonObject);
        }
        String apolloKey = qo.getApolloKey();

        boolean notNeedStoreIdParam = "data_store_rank_index_info".equals(apolloKey);
        if (notNeedStoreIdParam && !hasStoreId) {
            jsonObject.remove("storeId");
        }

        Map<String, Object> res = DataApiUtils.http(jsonObject.toJSONString(), apolloKey);

        boolean isNeedFill = (apolloKey.contains("data_mbr_scale_stat_new_custm_overview")
                || apolloKey.contains("data_sales_perf_anal_cont_custm_overview")
        || apolloKey.contains("month") || apolloKey.contains("day") ||
                apolloKey.contains("week"))
        && jsonObject.containsKey("storeGroup") &&
                ((apolloKey.contains("data_sales") &&
                        (jsonObject.getInteger("storeGroup") == 3 || jsonObject.getInteger("storeGroup") == 4
                         || jsonObject.getInteger("storeGroup") == 5))
                || (apolloKey.contains("data_mbr") && (jsonObject.getInteger("storeGroup") == 2
                        || jsonObject.getInteger("storeGroup") == 5)));
        if (isNeedFill) {
            log.info("需要补零");
            List<JSONObject> resultList = DataApiUtils.getDataList(res);
            if (CollectionUtils.isEmpty(resultList)) {
                resultList = new ArrayList<>();
            }
            List<String> dateTypeList = null;
            if (apolloKey.contains("day")) {
                dateTypeList = DateFillUtils.getDay(jsonObject.getString("bizDate"));
            } else if (apolloKey.contains("month")) {
                //data_sales_perf_anal_cont_clerk_month_overview
                //data_sales_perf_anal_cont_month_overview
                //data_mbr_scale_stat_month_clerk_overview
                //data_mbr_scale_stat_new_month_overview
                //data_mbr_scale_stat_new_month_clerk_overview
                boolean isYearMonthQuery = jsonObject.getInteger("storeGroup") == 5;
                if (isYearMonthQuery) {
                    dateTypeList = DateFillUtils.getMonthOfYear(jsonObject.getString("startDate").substring(0, 4));
                } else {
                    dateTypeList = DateFillUtils.getMonth(jsonObject.getString("startDate").substring(0, 7));
                }
            } else if (apolloKey.contains("week")) {
                dateTypeList = DateFillUtils.getWeek(jsonObject.getString("startDate"));
            } else if (apolloKey.contains("custm")) {
                dateTypeList = DateFillUtils.getCustom(jsonObject.getString("startDate"), jsonObject.getString("endDate"));
            }
            if (CollectionUtils.isNotEmpty(dateTypeList)) {
                List<JSONObject> fillList = new ArrayList<>();
                Map<String, JSONObject> fillMap = resultList.stream().collect(Collectors.toMap(e -> e.getString("bizDate"), e -> e));

                for (String dateTemp : dateTypeList) {
                    if (fillMap.get(dateTemp) != null) {
                        fillList.add(fillMap.get(dateTemp));
                    } else {
                        JSONObject fillJson = new JSONObject();
                        fillJson.put("bizDate", dateTemp);
                        fillList.add(fillJson);
                    }
                }
                return RestResponse.successResult(fillList);
            }

        }

        return RestResponse.successResult(res.get("data"));
    }

    /**
     * 指标字典列表
     * @param indexCode 可以多个，英文逗号隔开
     * @return
     */
    @RequestMapping("list-data-index-explain")
    @ResponseBody
    public RestResponse<List<DataIndexExplainVO>> listDataIndexExplain(String indexCode) {
        List<DataIndexExplainDTO> list = dataIndexApiService.listDataIndexExplain();
        if (StringUtils.isNotBlank(indexCode)) {
            List<String> indexCodeList = Arrays.stream(indexCode.split(",")).collect(Collectors.toList());
            list = list.stream().filter(e -> indexCodeList.contains(e.getIndexCode())).collect(Collectors.toList());
        }
        return RestResponse.successResult(EntityUtil.changeEntityListNew(DataIndexExplainVO.class, list));
    }

    /**
     * 评价指标
     * @param qo
     * @return
     */
    @RequestMapping("evaluate-data-index")
    @ResponseBody
    public RestResponse saveDataIndexEvaluate(@RequestBody DataIndexQO qo) {
        DataIndexEvaluateLogDTO log = EntityUtil.changeEntityNew(DataIndexEvaluateLogDTO.class, qo);
        log.setAccountId(qo.getClerkId());
        log.setSourceType(1);
        dataIndexApiService.saveDataIndexEvaluateLog(log);
        return RestResponse.successResult();
    }

    /**
     * 渠道字典数据
     * 说明：channelCode （渠道code，数据接口需要传的）
     * channelNameIntegral 会员类型的名称
     * channelNameOrder 订单业绩的名称
     * @param enterpriseId
     * @return
     */
    @RequestMapping("list-channel-data")
    @ResponseBody
    public RestResponse listChannelData(String enterpriseId) {
        Page<JSONObject> page = customSettingApiService
                .page("tab_gic_channel_platform_dict", "", 1, 1000).getResult();
        PlatformChannelEnum[] values = PlatformChannelEnum.values();
        Set<String> hasAuthSet = new HashSet<>();
        for (PlatformChannelEnum value : values) {
            boolean enable = true;
            hasAuthSet.add(value.getChannelCode());
            // 微信渠道，pos渠道，其他渠道默认开通
            if(PlatformEnum.WECHAT.equals(value.getBelongPlatform()) || PlatformEnum.POS.equals(value.getBelongPlatform()) || PlatformEnum.OTHER.equals(value.getBelongPlatform())){
                continue;
            }else if(PlatformChannelEnum.C_WEIMOB==value){
                //渠道查询判断是否开通
                EnterpriseSettingDTO enterpriseSettingDTO = enterpriseService.getEnterpriseSettingByEnterpriseId(enterpriseId);

                if (enterpriseSettingDTO == null || enterpriseSettingDTO.getEnterpriseSettingId() == null) {
                    enable = false;
                }
                //没开通微盟
                if (enterpriseSettingDTO.getBackgroundMode() == 0) {
                    enable = false;
                }
            }else{
                // 抖音天猫渠道
                ServiceResponse<EnterpriseSourceChannelDTO> response =  enterpriseChannelApiService.getEnterpriseSourceChannel(enterpriseId, value.getChannelCodeOld(), 1);
                if(!response.isSuccess() || response.getResult()==null){
                    enable = false;
                }
            }
            if (!enable) {
                hasAuthSet.remove(value.getChannelCode());
            }
        }
        if (page != null) {
            List<JSONObject> list = page.getResult();
            List<JSONObject> result = new ArrayList<>();
            for (JSONObject json : list) {
                if ("c_wechat_work".equals(json.getString("channelCode"))
                        || "c_wechat_gh".equals(json.getString("channelCode"))
                || !hasAuthSet.contains(json.getString("channelCode"))) {
                    continue;
                }
                json.put("dataChannelPre", channelMap().get(json.getString("channelCode")));
                result.add(json);
            }
            return RestResponse.successResult(result);
        }
        return RestResponse.successResult(new ArrayList<>());
    }

    private static Map<String, String> channelMap() {
        Map<String, String> map = new HashMap<>();
        map.put("c_pos", "pos");
        map.put("c_other", "else");
        map.put("c_douyin_hyt", "dy");
        map.put("c_tmall_hyt", "tmall");
        map.put("c_wechat_mini", "wct");
        map.put("c_weimob", "weimob");
        return map;
    }


    private JSONObject getTotalJson(JSONObject param, String apolloKey) {
        Map<String, Object> totalRes = DataApiUtils.http(param.toJSONString(), apolloKey);
        List<JSONObject> totalList = DataApiUtils.getPageList(totalRes);
        if (CollectionUtils.isEmpty(totalList)) {
            return null;
        }
        JSONObject total = totalList.get(0);
        return total;
    }

    protected boolean isSuccess(RestResponse response) {
        if ("0".equals(response.getCode())) {
            return true;
        }
        return false;
    }
}
