package com.dsk.system.dskService;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.dsk.acc.openapi.client.util.CommonUtils;
import com.dsk.common.constant.CacheConstants;
import com.dsk.common.core.domain.R;
import com.dsk.common.core.domain.model.*;
import com.dsk.common.core.page.TableDataInfo;
import com.dsk.common.core.redis.RedisCache;
import com.dsk.common.utils.DskOpenApiUtil;
import com.dsk.common.utils.EncodeIdUtil;
import com.dsk.system.domain.customer.vo.CustomerStatusListVo;
import com.dsk.system.service.ICustomerService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName enterpriseService
 * @Description TODO
 * @Author zhangyi
 * @Date 2023/5/15 12:00
 * @Version 1.0
 */
@Service
public class EnterpriseService {

    private static final Logger log = LoggerFactory.getLogger(EnterpriseService.class);

    @Autowired
    private DskOpenApiUtil dskOpenApiUtil;

    @Autowired
    ICustomerService iCustomerService;

    @Autowired
    private RedisCache redisCache;

    public R infoHeader(EnterpriseInfoHeaderBody body) throws Exception {
        if (body.isVaildCid()) return R.ok();
        Map<String, Object> companyMap = dskOpenApiUtil.requestBody("/api/jsk/enterprise/infoHeader", BeanUtil.beanToMap(body, false, false));
        Integer companyCode = MapUtils.getInteger(companyMap, "code", 300);
        if (200 != companyCode) return R.ok();

        Map companyData = MapUtils.getMap(companyMap, "data", null);
        companyData.put("uipId", null);
        companyData.put("claimStatus", 0);
        companyData.put("bratingSubjectLevel", null);
        String companyName = MapUtils.getString(companyData, "companyName", "");

        Map<String, Object> map = BeanUtil.beanToMap(body, false, false);
        map.put("cid", body.getCompanyId());

        Map<String, Object> uipMap = dskOpenApiUtil.requestBody("/operate/enterprise/financial", map);
        Integer uipCode = MapUtils.getInteger(uipMap, "code", 300);
        if (200 != uipCode) return R.ok(companyData);

        Map uipData = MapUtils.getMap(uipMap, "data", new HashMap<>());
        String uipId = MapUtils.getString(uipData, "uipId", null);
        companyData.put("uipId", uipId);
        if (!ObjectUtil.isEmpty(uipId)) {
            ArrayList<String> uipIds = new ArrayList<>();
            uipIds.add(uipId);
            companyData.put("claimStatus", CollectionUtils.isEmpty(iCustomerService.selectStatusList(uipIds)) ? 0 : 1);
        } else {
            Integer status = iCustomerService.status(companyName);
            if (ObjectUtil.isNotEmpty(status)) {
                companyData.put("claimStatus", status.equals(0) ? 1 : 0);
            }
        }

        Map<String, Object> bondCreditRatingMap = dskOpenApiUtil.requestBody("/operate/enterprise/bondCreditRating", map);
        Integer bondCreditRatingCode = MapUtils.getInteger(bondCreditRatingMap, "code", 300);
        if (200 != bondCreditRatingCode) return R.ok(companyData);

        List<Map<String, Object>> bondCreditRatingList = (List<Map<String, Object>>)MapUtils.getObject(bondCreditRatingMap, "data", new ArrayList<>());
        if (CollectionUtils.isEmpty(bondCreditRatingList)) return R.ok(companyData);

        companyData.put("bratingSubjectLevel", MapUtils.getString(bondCreditRatingList.get(0), "bratingSubjectLevel", null));

        return R.ok(companyData);
    }

    public R statistic(EnterpriseStatisticBody body) throws Exception {
        if (body.isVaildCid()) return R.ok();
        Map<String, Object> statisticMap = dskOpenApiUtil.requestBody("/api/jsk/enterprise/statistic", BeanUtil.beanToMap(body, false, false));

        Integer statisticMapCode = MapUtils.getInteger(statisticMap, "code", 300);
        if (200 != statisticMapCode) throw new RuntimeException();

        Map statisticMapData = MapUtils.getMap(statisticMap, "data", null);
        if (MapUtils.isEmpty(statisticMapData)) return R.ok();

        Map performance = MapUtils.getMap(statisticMapData, "performance");
        Map business = MapUtils.getMap(statisticMapData, "business");

        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("cid", body.getCompanyId());
        Map<String, Object> projectStatisticMap = dskOpenApiUtil.requestBody("/operate/enterpriseProject/statistic", paramMap);
        Integer projectStatisticMapCode = MapUtils.getInteger(projectStatisticMap, "code", 300);
        if (200 != projectStatisticMapCode) return R.ok(statisticMapData);

        Map projectStatisticMapData = MapUtils.getMap(projectStatisticMap, "data", null);

        performance.put("specialDebt", MapUtils.getInteger(projectStatisticMapData, "specialDebt", 0));
        performance.put("bidPlan", MapUtils.getInteger(projectStatisticMapData, "bidPlan", 0));
        business.put("historySend", MapUtils.getInteger(projectStatisticMapData, "historySend", 0));

        statisticMapData.put("performance", performance);
        statisticMapData.put("business", business);

        return R.ok(statisticMapData);
    }

    public R bidDataGroup(EnterpriseBidDataGroupBody body) throws Exception {
        if (body.isVaildCid()) return R.ok();
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/bidDataGroup", BeanUtil.beanToMap(body, false, false));
        return BeanUtil.toBean(map, R.class);
    }

    public R projectTenderDataGroup(EnterpriseProjectTenderDataGroupBody body) throws Exception {
        if (body.isVaildCid()) return R.ok();
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/projectTenderDataGroup", BeanUtil.beanToMap(body, false, false));
        return BeanUtil.toBean(map, R.class);
    }

    //todo 新数据，待入库
    public TableDataInfo partners(EnterprisePartnersBody body) throws Exception {
        if (body.isVaildCid()) return new TableDataInfo(new ArrayList<>(), 0);
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/partners", BeanUtil.beanToMap(body, false, false));
        return dskOpenApiUtil.responsePage(map);
    }

    public TableDataInfo investment(EnterpriseInvestmentBody body) throws Exception {
        if (body.isVaildCid()) return new TableDataInfo(new ArrayList<>(), 0);
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/investment", BeanUtil.beanToMap(body, false, false));
        return dskOpenApiUtil.responsePage(map);
    }

    public TableDataInfo affiliates(EnterpriseAffiliatesBody body) throws Exception {
        if (body.isVaildCid()) return new TableDataInfo(new ArrayList<>(), 0);
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/affiliates", BeanUtil.beanToMap(body, false, false));
        return dskOpenApiUtil.responsePage(map);
    }

    public TableDataInfo dynamicPage(EnterpriseDynamicPageBody body) throws Exception {
        if (body.isVaildCid()) return new TableDataInfo(new ArrayList<>(), 0);
        Map<String, Object> map = dskOpenApiUtil.requestBody("/api/jsk/enterprise/dynamic", BeanUtil.beanToMap(body, false, false));
        //底层接口写死了pageSize为10，这里前端只要5条
//        return dskOpenApiUtil.responsePage(map);

        Integer code = MapUtils.getInteger(map, "code", 300);
        Map data = MapUtils.getMap(map, "data", null);
        if (200 != code) throw new RuntimeException();
        Integer count = MapUtils.getInteger(data, "totalCount", 0);
        List<Object> list = CommonUtils.assertAsArray(MapUtils.getObject(data, "list", ""));

        return new TableDataInfo(body.getPageSize() <= list.size() ? list.subList(0, body.getPageSize()) : list, count);
    }

    public R icInfo(EnterpriseIcInfoBody body) throws Exception {
        if (body.isVaildCid()) return R.ok();
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/icInfo", BeanUtil.beanToMap(body, false, false));
        return BeanUtil.toBean(map, R.class);
    }

    public TableDataInfo changeInfo(EnterpriseChangeInfoBody body) throws Exception {
        if (body.isVaildCid()) return new TableDataInfo(new ArrayList<>(), 0);
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/changeInfo", BeanUtil.beanToMap(body, false, false));
        return dskOpenApiUtil.responsePage(map);
    }

    public TableDataInfo keymembers(EnterpriseKeymembersBody body) throws Exception {
        if (body.isVaildCid()) return new TableDataInfo(new ArrayList<>(), 0);
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/keymembers", BeanUtil.beanToMap(body, false, false));
        return dskOpenApiUtil.responsePage(map);
    }

    public TableDataInfo bestStockPage(EnterpriseBestStockPageBody body) throws Exception {
        if (body.isVaildCid()) return new TableDataInfo(new ArrayList<>(), 0);
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/bestStockPage", BeanUtil.beanToMap(body, false, false));
        return dskOpenApiUtil.responsePage(map);
    }

    public R financial(EnterpriseFinancialBody body) throws Exception {
        if (body.isVaildCid()) return R.ok();
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/financial", BeanUtil.beanToMap(body, false, false));
        return BeanUtil.toBean(map, R.class);
    }

    public R getUipId(String companyName) throws Exception {
        Map<String, Object> params = new HashMap<>();
        params.put("companyName", companyName);
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/getUipId", params);
        return BeanUtil.toBean(map, R.class);
    }

    public TableDataInfo uipSerach(EnterpriseUipSearchBody body) throws Exception {
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/uipSerach", BeanUtil.beanToMap(body, false, false));
        Integer code = MapUtils.getInteger(map, "code", 300);
        if (200 != code) throw new RuntimeException();

        Map data = MapUtils.getMap(map, "data", null);
        List<Object> list = CommonUtils.assertAsArray(MapUtils.getObject(data, "list", ""));

        if (CollectionUtils.isEmpty(list)) {
            return new TableDataInfo(list, 0);
        }

        ArrayList<String> uipIds = new ArrayList<>();
        for (Object dataMap : list) {
            uipIds.add(MapUtils.getString(CommonUtils.assertAsMap(dataMap), "uipId"));
        }

        List<CustomerStatusListVo> claimStatusList = iCustomerService.selectStatusList(uipIds);

        //按照城投企业id合并两个list
        for (Object companyObj : list) {
            Map<String, Object> companyMap = CommonUtils.assertAsMap(companyObj);
            String uipId = MapUtils.getString(companyMap, "uipId");
            companyMap.put("bondBalance",MapUtils.getDouble(companyMap, "bondBalance")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "bondBalance")));
            companyMap.put("totalAssets",MapUtils.getDouble(companyMap, "totalAssets")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "totalAssets")));
            companyMap.put("belongNetAssets",MapUtils.getDouble(companyMap, "belongNetAssets")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "belongNetAssets")));
            companyMap.put("monetaryFunds",MapUtils.getDouble(companyMap, "monetaryFunds")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "monetaryFunds")));
            companyMap.put("landAssets",MapUtils.getDouble(companyMap, "landAssets")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "landAssets")));
            companyMap.put("restrictedAssets",MapUtils.getDouble(companyMap, "restrictedAssets")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "restrictedAssets")));
            companyMap.put("accountsReceivable",MapUtils.getDouble(companyMap, "accountsReceivable")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "accountsReceivable")));
            companyMap.put("otherReceivable",MapUtils.getDouble(companyMap, "otherReceivable")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "otherReceivable")));
            companyMap.put("econData_001",MapUtils.getDouble(companyMap, "econData_001")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "econData_001")));
            companyMap.put("govSubsidy",MapUtils.getDouble(companyMap, "govSubsidy")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "govSubsidy")));
            companyMap.put("specialPayable",MapUtils.getDouble(companyMap, "specialPayable")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "specialPayable")));
            companyMap.put("operatingIncome",MapUtils.getDouble(companyMap, "operatingIncome")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "operatingIncome")));
            companyMap.put("belongNetProfit",MapUtils.getDouble(companyMap, "belongNetProfit")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "belongNetProfit")));
            companyMap.put("roe",MapUtils.getDouble(companyMap, "roe")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "roe")));
            companyMap.put("netOperatingCashFlow",MapUtils.getDouble(companyMap, "netOperatingCashFlow")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "netOperatingCashFlow")));
            companyMap.put("netFinancingCashFlow",MapUtils.getDouble(companyMap, "netFinancingCashFlow")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "netFinancingCashFlow")));
            companyMap.put("netInvestmentCashFlow",MapUtils.getDouble(companyMap, "netInvestmentCashFlow")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "netInvestmentCashFlow")));
            companyMap.put("totalLiabilities",MapUtils.getDouble(companyMap, "totalLiabilities")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "totalLiabilities")));
            companyMap.put("uipInterestBearingDebt",MapUtils.getDouble(companyMap, "uipInterestBearingDebt")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "uipInterestBearingDebt")));
            companyMap.put("econData_002",MapUtils.getDouble(companyMap, "econData_002")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "econData_002")));
            companyMap.put("ofcb",MapUtils.getDouble(companyMap, "ofcb")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "ofcb")));
            companyMap.put("cashRatio",MapUtils.getDouble(companyMap, "cashRatio")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "cashRatio")));
            companyMap.put("cashFlowRatio",MapUtils.getDouble(companyMap, "cashFlowRatio")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "cashFlowRatio")));
            companyMap.put("cashDebtRatio",MapUtils.getDouble(companyMap, "cashDebtRatio")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "cashDebtRatio")));
            companyMap.put("creditBalance",MapUtils.getDouble(companyMap, "creditBalance")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "creditBalance")));
            companyMap.put("econData_003",MapUtils.getDouble(companyMap, "econData_003")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "econData_003")));
            companyMap.put("ebitdaIcr",MapUtils.getDouble(companyMap, "ebitdaIcr")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "ebitdaIcr")));
            companyMap.put("ppnBalanceProp",MapUtils.getDouble(companyMap, "ppnBalanceProp")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "ppnBalanceProp")));
            companyMap.put("econData_004",MapUtils.getDouble(companyMap, "econData_004")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "econData_004")));
            companyMap.put("econData_005",MapUtils.getDouble(companyMap, "econData_005")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "econData_005")));
            companyMap.put("econData_006",MapUtils.getDouble(companyMap, "econData_006")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "econData_006")));
            companyMap.put("nonStandardBalance",MapUtils.getDouble(companyMap, "nonStandardBalance")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "nonStandardBalance")));
            companyMap.put("nonStandardRatio",MapUtils.getDouble(companyMap, "nonStandardRatio")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "nonStandardRatio")));
            companyMap.put("guaranteeAmount",MapUtils.getDouble(companyMap, "guaranteeAmount")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "guaranteeAmount")));
            companyMap.put("guaranteeRatio",MapUtils.getDouble(companyMap, "guaranteeRatio")==null?null:String.format("%.2f", MapUtils.getDouble(companyMap, "guaranteeRatio")));

            companyMap.put("claimStatus", 0);
            for (CustomerStatusListVo vo : claimStatusList) {
                if (uipId.equals(vo.getUipId())) {
                    companyMap.put("claimStatus", 1);
                }
            }
        }

        return new TableDataInfo(list, MapUtils.getInteger(data, "totalCount", 0));
    }

    public static void main(String[] args) {
        String str = String.format("%1$.2f", 0.0456);
        System.out.println(str);

        String format = String.format("%.2f", null);
        System.out.println(format);
    }

    public R uipGroupData() throws Exception {
        String redisKey = CacheConstants.DATA_UIPGROUPDATA;

        Map<String, Object> cacheMap = redisCache.getCacheMap(redisKey);
        if (MapUtils.isNotEmpty(cacheMap)) {
            return R.ok(cacheMap);
        }

        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/uipGroupData", new HashMap<>());
        Integer code = MapUtils.getInteger(map, "code", 300);
        if (200 != code) throw new RuntimeException();

        Map data = MapUtils.getMap(map, "data", null);
        redisCache.setCacheMap(redisKey, data);
        redisCache.expire(redisKey, 24, TimeUnit.HOURS);

        return BeanUtil.toBean(map, R.class);
    }

    public R remark(EnterpriseRemarkBody vo) throws Exception {
        return R.ok(EncodeIdUtil.avDecode(EncodeIdUtil.binaryToUnicode(vo.mark)));
    }

    public R bondCreditRating(EnterpriseBondCreditRatingBody body) throws Exception {
        if (body.isVaildCid()) return R.ok();
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/bondCreditRating", BeanUtil.beanToMap(body, false, false));
        return BeanUtil.toBean(map, R.class);
    }
    public R getUipIdByCid(List<Integer> body) throws Exception {
        if (CollectionUtils.isEmpty(body)) return R.ok();
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("ids", body);
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/getUipIdByCid", paramMap);
        return BeanUtil.toBean(map, R.class);
    }


    public R financialData(EnterpriseFinancialDataBody body) throws Exception {
        if (body.isValidateCid()) {
            return R.ok();
        }
        String redisKey = CacheConstants.DATA_FINANCIAL + body.getCid();
        List cacheMap = redisCache.getCacheList(redisKey);
        if (ObjectUtil.isNotEmpty(cacheMap)) {
            return R.ok(cacheMap);
        }
        Map<String, Object> map = dskOpenApiUtil.requestBody("/operate/enterprise/financialData", BeanUtil.beanToMap(body, false, false));
        Integer code = MapUtils.getInteger(map, "code", 300);
        if (!code.equals(HttpStatus.OK.value())) {
            throw new RuntimeException();
        }
        Object data = map.get("data");
        if (ObjectUtil.isNotEmpty(data)) {
            redisCache.setCacheList(redisKey, (List)data);
            redisCache.expire(redisKey, 24, TimeUnit.HOURS);
        }
        return BeanUtil.toBean(map, R.class);
    }
}
