package com.ruoyi.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.system.common.ReturnResult;
import com.ruoyi.system.domain.ActDispensing;
import com.ruoyi.system.mapper.ActSuppliesAccountMapper;
import com.ruoyi.system.model.doc.CustomDocRequestModel;
import com.ruoyi.system.service.IActSuppliesAccountService;
import com.ruoyi.system.utils.AccSubjectReqParamHandler;
import com.ruoyi.system.utils.AuxiliaryAccRuleHandler;
import com.ruoyi.system.yyinterface.VoucherUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.IntStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class ActSuppliesAccountServiceImpl implements IActSuppliesAccountService {
    private static final JSONObject REQUEST_HTTP_BODY = new JSONObject();
    private static final Map<String, Function<List<ActDispensing>, List<ActDispensing>>> MAP = new HashMap<>();

    static {
        REQUEST_HTTP_BODY.put("accsubjectchart", "1896891590924304390");
        REQUEST_HTTP_BODY.put("pk_org", "1685820920723669151");
        MAP.put("其他", ActSuppliesAccountServiceImpl::getActDispensings);
        MAP.put("011706", ActSuppliesAccountServiceImpl::getActDispensing);
    }

    private static Logger logger = LoggerFactory.getLogger(ActSuppliesAccountServiceImpl.class);

    @Autowired
    private ActSuppliesAccountMapper actSuppliesAccountMapper;

    public List<ActDispensing> options(List<ActDispensing> actDispensings) {
        for (int i = 0; i < actDispensings.size(); i++) {
            if (((ActDispensing) actDispensings.get(i)).getDepartment().equals("") || ((ActDispensing) actDispensings.get(i)).getDepartment() == null) {
                ActDispensing actDispensing1 = this.actSuppliesAccountMapper.selectActSuppliesAccpuntByName(((ActDispensing) actDispensings.get(i)).getName());
                if (actDispensing1 != null) {
                    ((ActDispensing) actDispensings.get(i)).setAccountingCode(actDispensing1.getAccountingCode());
                    ((ActDispensing) actDispensings.get(i)).setAccountingNameA(actDispensing1.getAccountingNameA() + ',' + actDispensing1.getAccountingIdA());
                    ((ActDispensing) actDispensings.get(i)).setAccountingNameB(actDispensing1.getAccountingNameB() + ',' + actDispensing1.getAccountingIdB());
                    ((ActDispensing) actDispensings.get(i)).setAccountingNameC(actDispensing1.getAccountingNameC() + ',' + actDispensing1.getAccountingIdC());
                }
            } else {
                ActDispensing actDispensing1 = this.actSuppliesAccountMapper.selectActSuppliesAccpuntByName(((ActDispensing) actDispensings.get(i)).getName() + '-' + ((ActDispensing) actDispensings.get(i)).getDepartment() + '-' + ((ActDispensing) actDispensings.get(i)).getMaterial());
                if (actDispensing1 != null) {
                    ((ActDispensing) actDispensings.get(i)).setAccountingCode(actDispensing1.getAccountingCode());
                    ((ActDispensing) actDispensings.get(i)).setAccountingNameA(actDispensing1.getAccountingNameA() + ',' + actDispensing1.getAccountingIdA());
                    ((ActDispensing) actDispensings.get(i)).setAccountingNameB(actDispensing1.getAccountingNameB() + ',' + actDispensing1.getAccountingIdB());
                    ((ActDispensing) actDispensings.get(i)).setAccountingNameC(actDispensing1.getAccountingNameC() + ',' + actDispensing1.getAccountingIdC());
                }
            }
        }
        List<ActDispensing> actDispensing = this.actSuppliesAccountMapper.selectActSuppliesAccpuntByCode();
        for (int j = 0; j < actDispensing.size(); j++) {
            ((ActDispensing) actDispensing.get(j)).setAccountingNameA(((ActDispensing) actDispensing.get(j)).getAccountingNameA() + ',' + ((ActDispensing) actDispensing.get(j)).getAccountingIdA());
            ((ActDispensing) actDispensing.get(j)).setAccountingNameB(((ActDispensing) actDispensing.get(j)).getAccountingNameB() + ',' + ((ActDispensing) actDispensing.get(j)).getAccountingIdB());
            ((ActDispensing) actDispensing.get(j)).setAccountingNameC(((ActDispensing) actDispensing.get(j)).getAccountingNameC() + ',' + ((ActDispensing) actDispensing.get(j)).getAccountingIdC());
            actDispensings.add(actDispensing.get(j));
        }
        return actDispensings;
    }

    public List<ActDispensing> getAccountFromYon(List<ActDispensing> actDispensings) {
        Optional<List<ActDispensing>> optional = Optional.ofNullable(actDispensings);
        if (!optional.isPresent()) {
            return null;
        }
        String s = actDispensings.get(0).getMining().equals("011706") ? "011706" : "其他";
        Function<List<ActDispensing>, List<ActDispensing>> function = MAP.get(s);
        List<ActDispensing> apply = function.apply(actDispensings);
        return apply;
    }

    /**
     * 中润调用友接口拿数据方法
     *
     * @param actDispensings
     * @return
     */
    private static List<ActDispensing> getActDispensing(List<ActDispensing> actDispensings) {
        for (ActDispensing actDispensing : actDispensings) {
            JSONObject object = new JSONObject();
            object.put("accsubjectchart", "1896891590924304390");
            object.put("pk_org", "1685820920723669151");
            object.put("codes", actDispensing.getR());
            ReturnResult returnResult = VoucherUtils.callVoucherQuery(object, "/yonbip/fi/fipub/accsubject/querysubjectapi");
            JSONObject o = (JSONObject) returnResult.getData().get(0);
            JSONObject data = o.getJSONObject("accsubjectchart");
            JSONObject accSubjects = data.getJSONObject("accSubjects");
            for (Map.Entry<String, Object> stringObjectEntry : accSubjects.entrySet()) {
                JSONArray jsonObject = (JSONArray) stringObjectEntry.getValue();
                Optional<JSONObject> code = IntStream.range(0, jsonObject.size())
                        .mapToObj(jsonObject::getJSONObject)
                        .filter(v -> actDispensing.getR().equals(v.getString("code")))
                        .findFirst();
                if (code.isPresent()) {
                    JSONArray bodies = code.get().getJSONArray("bodies");
                    for (int i = 0; i < bodies.size(); i++) {
                        JSONObject json = (JSONObject) bodies.get(i);
                        String name = json.getString("dimensionext_name");
                        if ("物料基本分类".equals(name)) {
                            actDispensing.setAccountingIdA("物料基本分类,FM060305");
                        }
                        if ("财务核算部门".equals(name)) {
                            ReturnResult cw0027 = getReturnResult("CW0027_yql", "/yonbip/digitalModel/customerdoc/list");
                            JSONObject obj = (JSONObject) cw0027.getData().get(0);
                            JSONArray recordList = obj.getJSONArray("recordList");
                            Optional<JSONObject> first = IntStream.range(0, recordList.size())
                                    .mapToObj(recordList::getJSONObject)
                                    .filter(v -> actDispensing.getMaterial().equals(v.getJSONObject("name").getString("zh_CN")))
                                    .findFirst();
                            if (first.isPresent()) {
                                actDispensing.setAccountingIdB("财务核算部门," + first.get().getString("code"));
                            }
                        }
                    }
                }
            }
            actDispensing.setAccountingCode(actDispensing.getR());
        }
        ActDispensing actDispensing = new ActDispensing();
        actDispensing.setAccountingCode("2241005");
        actDispensings.add(actDispensing);
        ActDispensing actDispensing1 = new ActDispensing();
        actDispensing1.setAccountingCode("1403002");
        actDispensings.add(actDispensing1);
        return actDispensings;
    }

    private static ReturnResult getReturnResult(String value, String url) {
        JSONObject object = new JSONObject();
        object.put("pageIndex", "1");
        object.put("pageSize", "1000");
        object.put("custdocdefcode", value);
        return VoucherUtils.callVoucherQuery(object, url);
    }

    /**
     * 其他矿调用友接口拿数据方法（以前的）
     *
     * @param actDispensings
     * @return
     */
    private static List<ActDispensing> getActDispensings(List<ActDispensing> actDispensings) {
        JSONObject accSubjects = getAccSubjects();
        CustomDocRequestModel docRequest = new CustomDocRequestModel();
        docRequest.setPageIndex(Long.valueOf(1L));
        docRequest.setPageSize(Long.valueOf(500L));
        for (ActDispensing dispensing : actDispensings) {
            String nameZhCn = AuxiliaryAccRuleHandler.handleAuxiliaryAccounting(dispensing.getMining(), dispensing.getName());
            String displayName = AccSubjectReqParamHandler.paramHandler(dispensing.getName(), dispensing.getMaterial(), dispensing.getDepartment());
            JSONObject accRes = getCellByName(displayName, accSubjects);
            if (accRes == null) continue;
            dispensing.setAccountingCode(accRes.getString("code"));
            JSONArray res = accRes.getJSONArray("res");
            String dispensingDepartment = dispensing.getDepartment();
            dispensing.setAccountingNameA(null + "," + null);
            dispensing.setAccountingNameB(null + "," + null);
            dispensing.setAccountingNameC(null + "," + null);
            Map<String, String> mapNameCode = new HashMap<>();
            for (Object jsonObject : res) {
                JSONObject accObject = (JSONObject) jsonObject;
                String dimensionextName = accObject.getString("dimensionext_name");
                String dimensionextCode = accObject.getString("dimensionext_code");
                String codeFromCustomDoc = null;
                if ("物料基本分类".equals(dimensionextName)) {
                    if ("原煤".equals(dispensingDepartment)) {
                        codeFromCustomDoc = "MT01";
                    } else if ("选煤".equals(dispensingDepartment)) {
                        codeFromCustomDoc = "MT03";
                    } else if ("选混煤".equals(dispensingDepartment)) {
                        codeFromCustomDoc = "MT0303";
                    } else if ("洗煤".equals(dispensingDepartment)) {
                        codeFromCustomDoc = "MT02";
                    }
                } else {
                    docRequest.setCustdocdefcode(dimensionextCode + "_yql");
                    JSONArray customDoc = getCustomDoc(docRequest);
                    codeFromCustomDoc = getCodeFromCustomDoc(customDoc, nameZhCn);
                }
                mapNameCode.put(dimensionextName, codeFromCustomDoc);
            }
            Iterator<Map.Entry<String, String>> it = mapNameCode.entrySet().iterator();
            if (it.hasNext()) {
                Map.Entry<String, String> entry = it.next();
                dispensing.setAccountingNameA((String) entry.getKey() + "," + (String) entry.getValue());
            }
            if (it.hasNext()) {
                Map.Entry<String, String> entry = it.next();
                dispensing.setAccountingNameB((String) entry.getKey() + "," + (String) entry.getValue());
            }
            if (it.hasNext()) {
                Map.Entry<String, String> entry = it.next();
                dispensing.setAccountingNameC((String) entry.getKey() + "," + (String) entry.getValue());
            }
            logger.error(dispensing.toString());
        }
        ActDispensing actDispensing = new ActDispensing();
        actDispensing.setAccountingCode("2241005");
        actDispensings.add(actDispensing);
        ActDispensing actDispensing2 = new ActDispensing();
        actDispensing2.setAccountingCode("1403002");
        actDispensings.add(actDispensing2);
        return actDispensings;
    }

    public static JSONArray getCustomDoc(CustomDocRequestModel customDocRequestModel) {
        ReturnResult customDocument = VoucherUtils.callVoucherQuery(customDocRequestModel, "/yonbip/digitalModel/customerdoc/list");
        JSONObject customDocumentJsonObj = (JSONObject) JSON.toJSON(customDocument.getData().get(0));
        return customDocumentJsonObj.getJSONArray("recordList");
    }

    public static JSONObject getCellByName(String filterNameZHCN, JSONObject accSubjects) {
        JSONObject cell = getAccSubject(accSubjects, filterNameZHCN);
        if (filterNameZHCN == null || "".equals(filterNameZHCN) || cell == null || cell.size() == 0) {
            return null;
        }
        if ("专项储备_煤炭生产安全费_本年减少_费用性支出".equals(filterNameZHCN) || "研发支出_费用化支出_材料及低值易耗品".equals(filterNameZHCN) || "在建工程_内部投资工程".equals(filterNameZHCN))
            return filterBodiesWithSpecified(cell);
        return filterBodiesWithExtNameEnding(cell);
    }

    private static JSONObject getAccSubject(JSONObject accSubjects, String filterNameZHCN) {
        for (String key : accSubjects.keySet()) {
            JSONArray accSubject = accSubjects.getJSONArray(key);
            for (Object o : accSubject) {
                JSONObject cell = (JSONObject) o;
                if (cell.getString("displayname").equals(filterNameZHCN))
                    return cell;
            }
        }
        return null;
    }

    private static JSONObject filterBodiesWithExtNameEnding(JSONObject cell) {
        JSONArray bodies = cell.getJSONArray("bodies");
        JSONArray res = new JSONArray();
        String code = cell.getString("code");
        if (bodies.size() > 0)
            for (int i = 0; i < bodies.size(); i++) {
                JSONObject body = bodies.getJSONObject(i);
                String extName = body.getString("ext_name");
                if (extName.endsWith("@0") || extName.contains("物料基本分类") || extName.contains("产品成本来源类别")) {
                    JSONObject filteredBody = new JSONObject();
                    filteredBody.put("dimensionext", body.getString("dimensionext"));
                    filteredBody.put("dimensionext_name", body.getString("dimensionext_name"));
                    filteredBody.put("dimensionext_code", body.getString("dimensionext_code"));
                    res.add(filteredBody);
                }
            }
        JSONObject result = new JSONObject();
        result.put("code", code);
        result.put("res", res);
        return result;
    }

    private static JSONObject filterBodiesWithSpecified(JSONObject cell) {
        JSONArray bodies = cell.getJSONArray("bodies");
        JSONArray res = new JSONArray();
        String code = cell.getString("code");
        if (bodies.size() > 0)
            for (int i = 0; i < bodies.size(); i++) {
                JSONObject body = bodies.getJSONObject(i);
                JSONObject filteredBody = new JSONObject();
                filteredBody.put("dimensionext", body.getString("dimensionext"));
                filteredBody.put("dimensionext_name", body.getString("dimensionext_name"));
                filteredBody.put("dimensionext_code", body.getString("dimensionext_code"));
                res.add(filteredBody);
            }
        JSONObject result = new JSONObject();
        result.put("code", code);
        result.put("res", res);
        return result;
    }

    private static String getCodeFromCustomDoc(JSONArray customDoc, String nameZhCn) {
        String code = null;
        for (Object o : customDoc) {
            JSONObject object = (JSONObject) o;
            JSONObject nameObject = object.getJSONObject("name");
            String zh_CN = nameObject.getString("zh_CN");
            if (zh_CN.equals(nameZhCn)) {
                code = object.getString("code");
                break;
            }
        }
        return code;
    }

    public JSONArray getAuxiliary() {
        ReturnResult accounting = VoucherUtils.invokeByGet("", "", "/yonbip/fi/fipub/multidimension_ext/getapimultidimension");
        return (JSONArray) JSON.toJSON(accounting.getData());
    }

    public static JSONObject getAccSubjects() {
        ReturnResult accSubject = VoucherUtils.callVoucherQuery(REQUEST_HTTP_BODY, "/yonbip/fi/fipub/accsubject/querysubjectapi");
        JSONArray jsonArray = new JSONArray(accSubject.getData());
        return jsonArray
                .getJSONObject(0)
                .getJSONObject("accsubjectchart")
                .getJSONObject("accSubjects");
    }
}
