package com.brilliance.isc.common.util;

import com.brilliance.isc.annotation.ForceRecalculate;
import com.brilliance.isc.bo.*;
import com.brilliance.isc.common.component.PtsptaToolComponent;
import com.brilliance.isc.common.context.BopContext;
import com.brilliance.isc.common.context.SettleContext;
import com.brilliance.isc.common.context.SpringEnvContext;
import com.brilliance.isc.common.sysmod.SysmodService;
import com.brilliance.isc.common.transaction.help.TransactionHelpService;
import com.brilliance.isc.common.transaction.help.TransactionServiceSet;
import com.brilliance.isc.common.transaction.vo.BaseTransactionVo;
import com.brilliance.isc.common.trnmod.vo.TrnmodVo;
import com.brilliance.isc.common.vo.AbstractCommonVo;
import com.brilliance.isc.common.vo.BizInfoVo;
import com.brilliance.isc.common.vo.PtsptaVo;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.util.*;

public class BopUtils {
    public static PtsptaVo getPtsptaByRol(String rol) {
        PtsptaToolComponent ptsptaToolComponent = SpringEnvContext.getBean(PtsptaToolComponent.class);
        PtsptaVo ptsptaVo = ptsptaToolComponent.getPtsFromListByRol(BopContext.getPtsList(), rol);
        if (ptsptaToolComponent.ptsIsRolSet(ptsptaVo)) {
            ptsptaToolComponent.fillPtsptaAllProperties(ptsptaVo);
            return ptsptaVo;
        }
        return new PtsptaVo();
    }

    public static Pts getPtsByRol(String rol) {
        return Optional.ofNullable(getPtsptaByRol(rol).getPts()).orElseGet(Pts::new);
    }

    public static Pta getPtaByRol(String rol) {
        return Optional.ofNullable(getPtsptaByRol(rol).getPta()).orElseGet(Pta::new);
    }

    public static Adr getAdrByRol(String rol) {
        return Optional.ofNullable(getPtsptaByRol(rol).getAdr()).orElseGet(Adr::new);
    }


    public static void loadSettleSession(AbstractCommonVo requestVo) {
        String transName = Utils.getFieldValue(requestVo, "transName");
        String userId = Utils.getFieldValue(requestVo, "userId");
        BizInfoVo rec = Utils.getFieldValue(requestVo, "rec");
        List<PtsptaVo> ptsList = Utils.getFieldValue(requestVo, "ptsList");
        SettleContext settleContext = SpringEnvContext.getBean(SettleContext.class);
        settleContext.loadSettleSession(transName, userId, rec, ptsList);
    }

    public static String judgeGIType(String transName, String hndtyp) {
        String flg = "";
        if (StringUtils.equals(transName, "GITSET")) {
            switch (hndtyp) {
                case "OL":
                case "OC":
                    flg = "GI";
                    break;
                case "FI":
                case "FA":
                case "OT":
                    flg = "GE";
                    break;
            }
        } else {
            flg = transName.substring(0, 2);
        }
        return flg;
    }

    public static Map<String, Object> backupModifiedFields(AbstractCommonVo vo) {
        Map<String, Object> fieldBackup = new HashMap<>();
        Set<String> modifySet = vo.getModifySet();
        for (String fieldName : modifySet) {
            try {
                Field field = vo.getClass().getDeclaredField(fieldName);
                field.setAccessible(true);
                fieldBackup.put(fieldName, field.get(vo));
            } catch (NoSuchFieldException | IllegalAccessException e) {
//                e.printStackTrace();
            }
        }
        Field[] declaredFields = vo.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            if (AbstractCommonVo.class.isAssignableFrom(field.getType())) {
                try {
                    field.setAccessible(true);
                    if (field.get(vo) != null) {
                        Map<String, Object> modifiedFields = backupModifiedFields((AbstractCommonVo) field.get(vo));
                        fieldBackup.put(field.getName(), modifiedFields);
                    }
                } catch (IllegalAccessException e) {
//                    e.printStackTrace();
                }
            }
        }
        return fieldBackup;
    }

    public static void restoreModifiedFields(AbstractCommonVo vo, Map<String, Object> modifiedFields) {
        for (Map.Entry<String, Object> entry : modifiedFields.entrySet()) {
            try {
                Field field = vo.getClass().getDeclaredField(entry.getKey());
                field.setAccessible(true);
                if (AbstractCommonVo.class.isAssignableFrom(field.getType())) {
                    Map<String, Object> map = Utils.convertObjectToMap(entry.getValue());
                    restoreModifiedFields((AbstractCommonVo) field.get(vo), map);
                } else if (!field.isAnnotationPresent(ForceRecalculate.class)) {
                    field.set(vo, entry.getValue());
                }
            } catch (NoSuchFieldException | IllegalAccessException e) {
//                e.printStackTrace();
            }
        }
    }

    public static void saveSpt(String transName) {
        //确定transName
        Spt spt = new Spt();
        spt.setDelflg("X");
        spt.setFrm(transName);
        TransactionHelpService transactionHelpService = SpringEnvContext.getBean(TransactionHelpService.class);
        TransactionServiceSet transactionStoreSet = transactionHelpService.getTransactionStoreSet();
        TrnmodVo trnmod = transactionStoreSet.getTrnmodVo();
        spt.setCreobjtyp("TRN");
        spt.setCreobjinr(trnmod.getTrn().getInr());
        spt.setUsr(SettleContext.getUserSession().getUsr().getExtkey());
        spt.setOrdinr(trnmod.getTrn().getOrdinr());
        Bch wrkBch = Optional.ofNullable(SettleContext.getUserSession().getWrkbch()).orElseGet(Bch::new);
        spt.setBchkeyinr(wrkBch.getInr());
        spt.setBranchinr(wrkBch.getInr());
        Object rec = transactionStoreSet.getRec();
        SysmodService sysmodService = SpringEnvContext.getBean(SysmodService.class);
        String objName = sysmodService.internalSetObjNam(rec, null);
        BaseTransactionVo transactionVo = transactionStoreSet.getTransactionVo();
        sysmodService.sptSaveEntry(spt, rec, "BOP", transactionVo, objName);
    }
}
