package pwc.taxtech.atms.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.io.Files;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import pwc.taxtech.atms.CommonIT;
import pwc.taxtech.atms.OrgKV;
import pwc.taxtech.atms.common.message.LogMessage;
import pwc.taxtech.atms.common.util.DateUtils;
import pwc.taxtech.atms.constant.enums.NationalEconomicIndustryEnum;
import pwc.taxtech.atms.dao.*;
import pwc.taxtech.atms.dto.organization.DDSyncOrgInfo;
import pwc.taxtech.atms.dto.organization.OrgSyncData;
import pwc.taxtech.atms.entity.*;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Auther: Gary J Li
 * @Date: 26/02/2019 11:56
 * @Description:
 */
public class DataInitTest extends CommonIT {

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

    @Autowired
    protected DistributedIdService idService;

    @Resource
    private OrganizationMapper organizationMapper;

    @Resource
    private OrganizationExtraMapper organizationExtraMapper;

    @Resource
    private OrganizationEmployeeMapper organizationEmployeeMapper;

    @Resource
    private OrganizationAccountingRateMapper organizationAccountingRateMapper;

    @Resource
    private OrganizationApprovedLevyInfoMapper organizationApprovedLevyInfoMapper;

    @Resource
    private OrganizationInvoiceMapper organizationInvoiceMapper;

    @Resource
    private OrganizationReturnRateMapper organizationReturnRateMapper;

    @Resource
    private OrganizationTaxOfficerMapper organizationTaxOfficerMapper;

    @Resource
    private OrganizationTaxRuleMapper organizationTaxRuleMapper;

    @Resource
    private OrganizationTaxpayerQualificationMapper organizationTaxpayerQualificationMapper;

    @Resource
    private EquityInformationMapper equityInformationMapper;

    @Resource
    private OperationLogEquityMapper operationLogEquityMapper;

    @Test
    public void importOrgJson(){
        String input = "";
        try {
            File targetFile = new File("src/main/resources/orgImport/company_info.json");
            input = FileUtils.readFileToString(targetFile, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        JSONObject object = JSONObject.parseObject(input);
        Map<String, Object> orgs = object.getInnerMap();
        Map<String, Object> failList = new HashMap<>();
        StringBuilder failMsg = new StringBuilder();

        orgs.forEach((orgK, orgV) -> {
            try {
                String orgName = orgK;
                String orgId = UUID.randomUUID().toString();
                Map<String, Object> infos = (Map) orgV;
                //根据股东及出资信息匹配的
                List<EquityInformation> equityInfos = Lists.newArrayList();
                //根据股东信息匹配的
                List<EquityInformation> equityInfos1 = Lists.newArrayList();

                infos.forEach((infoK, infoV) -> {
                    if (infoV instanceof JSONArray) {
                        List<Map<String, Object>> list = (List) infoV;
                        if ("股东及出资信息".equals(infoK)) {
                            if (list.size() > 0) {
                                Long equityId = idService.nextId();
                                for (int i = 0; i < list.size(); i++) {
                                    EquityInformation equityInfo = new EquityInformation();
                                    equityInfo.setId(equityId);
                                    equityInfo.setOrganizationId(orgId);
                                    equityInfo.seteNum(i + 1);
                                    list.get(i).forEach((eK, eV) -> {
                                        if ("eNum".equals(OrgKV.Map.get(eK))) {

                                        } else if ("investmentRadio".equals(OrgKV.Map.get(eK))) {
                                            String investmentRadio = (String) eV;
                                            if (StringUtils.isNotEmpty(investmentRadio) && !StringUtils.equals("-", investmentRadio)) {
                                                equityInfo.setInvestmentRadio(Float.valueOf((investmentRadio.replace("%", ""))));
                                            }
                                            if (equityInfo.getPayableContributionProportion()==null&&StringUtils.isNotEmpty(investmentRadio) && !StringUtils.equals("-", investmentRadio)) {
                                                equityInfo.setPayableContributionProportion(Float.valueOf((investmentRadio.replace("%", ""))));
                                            }
                                        } else if ("payableCapitalContributionAmount".equals(OrgKV.Map.get(eK))) {
                                            String payableCapitalContributionAmount = ((String) eV).trim();
                                            if(payableCapitalContributionAmount.contains(",")){
                                                double res = Arrays.asList(payableCapitalContributionAmount.split(",")).stream().mapToDouble(Double::parseDouble).sum();
                                                equityInfo.setPayableCapitalContributionAmount((long) res);
                                            }else{
                                                equityInfo.setPayableCapitalContributionAmount("-".equals(payableCapitalContributionAmount) ?0:(long) Double.parseDouble(payableCapitalContributionAmount));
                                            }
                                        } else if ("investorName".equals(OrgKV.Map.get(eK))) {
                                            String investorName = (String) eV;
                                            if (investorName.contains("公司")) {
                                                equityInfo.setInvestorEconomicNature("公司");
                                            } else {
                                                equityInfo.setInvestorEconomicNature("个人");
                                            }
                                            equityInfo.setInvestorName(investorName);
                                            equityInfo.setPayableShareholderName(investorName);
                                        } else if ("investmentAmount".equals(OrgKV.Map.get(eK))) {
                                            String investmentAmountStr = ((String) eV).trim();
                                            if(OrgKV.Map.get(eK).contains("美元")){
                                                equityInfo.setPayableCapitalContributionCurrency("美元");
                                                equityInfo.setInvestmentCurrency("美元");
                                            }else{
                                                equityInfo.setPayableCapitalContributionCurrency("人民币");
                                                equityInfo.setInvestmentCurrency("人民币");
                                            }
                                            if(investmentAmountStr.contains(",")){
                                                double res = Arrays.asList(investmentAmountStr.split(",")).stream().mapToDouble(Double::parseDouble).sum();
                                                equityInfo.setInvestmentAmount((long) res);
                                            }else{
                                                equityInfo.setInvestmentAmount("-".equals(investmentAmountStr) ?0:(long) Double.parseDouble(investmentAmountStr));
                                            }
                                            if(equityInfo.getPayableCapitalContributionAmount()==null){
                                                if(investmentAmountStr.contains(",")){
                                                    double res = Arrays.asList(investmentAmountStr.split(",")).stream().mapToDouble(Double::parseDouble).sum();
                                                    equityInfo.setPayableCapitalContributionAmount((long) res);
                                                }else{
                                                    equityInfo.setPayableCapitalContributionAmount("-".equals(investmentAmountStr) ?0:(long) Double.parseDouble(investmentAmountStr));
                                                }
                                            }
                                        } else if (null != OrgKV.Map.get(eK)) {
                                            setProperty(equityInfo, OrgKV.Map.get(eK), eV);
                                        }
                                    });
                                    equityInfos.add(equityInfo);
                                }
                                equityInfos.forEach(ei -> {
                                    // 逐条insert   失败的记录
                                    if (equityInformationMapper.insertSelective(ei) < 1) {
                                        failList.putIfAbsent(orgK, orgV);
                                    }
                                });
                            }
                        } else if ("股东信息".equals(infoK) && equityInfos.isEmpty()) {
                            if (list.size() > 0) {
                                Long equityId = idService.nextId();
                                for (int i = 0; i < list.size(); i++) {
                                    EquityInformation equityInfo = new EquityInformation();
                                    equityInfo.setId(equityId);
                                    equityInfo.setOrganizationId(orgId);
                                    equityInfo.seteNum(i + 1);
                                    list.get(i).forEach((eK, eV) -> {
                                        if ("eNum".equals(OrgKV.Map.get(eK))) {

                                        } else if ("investmentRadio".equals(OrgKV.Map.get(eK))) {
                                            String investmentRadio = (String) eV;
                                            if (StringUtils.isNotEmpty(investmentRadio) && !StringUtils.equals("-", investmentRadio)) {
                                                equityInfo.setInvestmentRadio(Float.valueOf((investmentRadio.replace("%", ""))));
                                            }
                                            if (equityInfo.getPayableContributionProportion()==null&&StringUtils.isNotEmpty(investmentRadio) && !StringUtils.equals("-", investmentRadio)) {
                                                equityInfo.setPayableContributionProportion(Float.valueOf((investmentRadio.replace("%", ""))));
                                            }
                                        } else if ("payableCapitalContributionAmount".equals(OrgKV.Map.get(eK))) {
                                            String payableCapitalContributionAmount = ((String) eV).trim();
                                            if(payableCapitalContributionAmount.contains(",")){
                                                double res = Arrays.asList(payableCapitalContributionAmount.split(",")).stream().mapToDouble(Double::parseDouble).sum();
                                                equityInfo.setPayableCapitalContributionAmount((long) res);
                                            }else{
                                                equityInfo.setPayableCapitalContributionAmount("-".equals(payableCapitalContributionAmount) ?0:(long) Double.parseDouble(payableCapitalContributionAmount));
                                            }
                                        } else if ("investorName".equals(OrgKV.Map.get(eK))) {
                                            String investorName = (String) eV;
                                            if (investorName.contains("公司")) {
                                                equityInfo.setInvestorEconomicNature("公司");
                                            } else {
                                                equityInfo.setInvestorEconomicNature("个人");
                                            }
                                            equityInfo.setInvestorName(investorName);
                                            equityInfo.setPayableShareholderName(investorName);
                                        } else if ("investmentAmount".equals(OrgKV.Map.get(eK))) {
                                            String investmentAmountStr = ((String) eV).trim();
                                            if(OrgKV.Map.get(eK).contains("美元")){
                                                equityInfo.setPayableCapitalContributionCurrency("美元");
                                                equityInfo.setInvestmentCurrency("美元");
                                            }else{
                                                equityInfo.setPayableCapitalContributionCurrency("人民币");
                                                equityInfo.setInvestmentCurrency("人民币");
                                            }
                                            if(investmentAmountStr.contains(",")){
                                                double res = Arrays.asList(investmentAmountStr.split(",")).stream().mapToDouble(Double::parseDouble).sum();
                                                equityInfo.setInvestmentAmount((long) res);
                                            }else{
                                                equityInfo.setInvestmentAmount("-".equals(investmentAmountStr) ?0:(long) Double.parseDouble(investmentAmountStr));
                                            }
                                            if(equityInfo.getPayableCapitalContributionAmount()==null){
                                                if(investmentAmountStr.contains(",")){
                                                    double res = Arrays.asList(investmentAmountStr.split(",")).stream().mapToDouble(Double::parseDouble).sum();
                                                    equityInfo.setPayableCapitalContributionAmount((long) res);
                                                }else{
                                                    equityInfo.setPayableCapitalContributionAmount("-".equals(investmentAmountStr) ?0:(long) Double.parseDouble(investmentAmountStr));
                                                }
                                            }
                                        } else if (null != OrgKV.Map.get(eK)) {
                                            setProperty(equityInfo, OrgKV.Map.get(eK), eV);
                                        }
                                    });
                                    equityInfos1.add(equityInfo);
                                }
                                equityInfos1.forEach(ei -> {
                                    // 逐条insert   失败的记录
                                    if (equityInformationMapper.insertSelective(ei) < 1) {
                                        failList.putIfAbsent(orgK, orgV);
                                    }
                                });
                            }
                        } else if ("变更记录".equals(infoK)) {
                            List<OperationLogEquity> logs = Lists.newArrayList();
                            list.forEach(l -> {
                                OperationLogEquity log = new OperationLogEquity();
                                log.setId(UUID.randomUUID().toString());
                                l.forEach((eK, eV) -> {
                                    if (OrgKV.Map.get(eK).equals("createTime")) {
                                        log.setCreateTime(DateUtils.strToDate((String) eV));
                                    } else if (OrgKV.Map.get(eK).equals("eNum")) {

                                    } else {
                                        setProperty(log, OrgKV.Map.get(eK), eV);
                                    }
                                });
                                log.setModuleName("InitEquityChange");
                                log.setOperationAction("InitEquityChange");
                                log.setOperationObject(orgName);
                                log.setOperationContent(LogMessage.InitOrganizationEquity);
                                log.setOperationUser("admin");
                                logs.add(log);
                            });
                            logs.forEach(l -> {
                                // 逐条insert   失败的记录
                                if (operationLogEquityMapper.insertSelective(l) < 1) {
                                    failList.putIfAbsent(orgK, orgV);
                                }
                            });
                        }

                    } else if (infoV instanceof JSONObject) {
                        // todo 工商信息 organization organization_extra
                        Map<String, Object> details = (Map) infoV;
                        Organization org = new Organization();
                        OrganizationExtra orgEx = new OrganizationExtra();
                        OrganizationEmployee orgEmp = new OrganizationEmployee();


                        org.setId(orgId);
                        org.setName(orgName);

                        orgEx.setId(idService.nextId());
                        orgEx.setOrganizationId(orgId);

                        orgEmp.setId(idService.nextId());
                        orgEmp.setOrganizationId(orgId);

                        details.forEach((dK, dV) -> {
                            if (null != OrgKV.Map.get(dK)) {
                                switch (OrgKV.Map.get(dK)) {
                                    case "regStatus":
                                        // todo开业转换为存续
                                        String regStatusStr = (String) dV;
                                        regStatusStr = regStatusStr.contains("在业") || regStatusStr.contains("开业") || regStatusStr.contains("存续") ? "存续" : regStatusStr;
                                        org.setRegStatus(regStatusStr);
                                        orgEx.setTaxRegStatus(regStatusStr);
                                        break;
                                    case "businessScope":
                                        org.setBusinessScope((String) dV);
                                        break;
                                    case "registrationCapital":
                                        org.setRegistrationCapital((String) dV);
                                        break;
                                    case "paidInCapital":
                                        org.setPaidInCapital((String) dV);
                                        break;
                                    case "englishName":
                                        org.setEnglishName((String) dV);
                                        break;
                                    case "registerAddress":
                                        org.setRegisterAddress((String) dV);
                                        break;
                                    case "registrationType":
                                        org.setRegistrationType((String) dV);
                                        break;
                                    case "foundationDate":
                                        org.setFoundationDate(DateUtils.strToDate((String) dV));
                                        break;
                                    case "taxPayerNumber":
                                        org.setTaxPayerNumber((String) dV);
                                        orgEx.setUnifiedSocialCreditCode((String) dV);
                                        break;
                                    case "nationalEconomicIndustry":
                                        org.setNationalEconomicIndustry(NationalEconomicIndustryEnum.Map.get((String) dV));
                                        break;
                                    case "employeesNumEnd":
                                        orgEmp.setEmployeesNumEnd("-".equals((String) dV) ? 0 : Integer.valueOf((String) dV));
                                        orgEmp.setStatisticalMonth(new Date());
                                        break;
                                    case "legalCode":
                                        org.setLegalCode((String) dV);
                                        break;
                                    default:
                                        break;
                                }
                            }
                        });
                        if (organizationMapper.insertSelective(org) < 0) {
                            failList.putIfAbsent(orgK, orgV);
                        }
                        if (organizationExtraMapper.insertSelective(orgEx) < 0) {
                            failList.putIfAbsent(orgK, orgV);
                        }
                        if (organizationEmployeeMapper.insertSelective(orgEmp) < 0) {
                            failList.putIfAbsent(orgK, orgV);
                        }
                        insertExtraList(orgId);
                    }
                });
            } catch (Exception e) {
                logger.error(String.format("机构:[%s]导入异常",orgK),e);
                failMsg.append(e.getMessage()+"\n");
                failList.putIfAbsent(orgK, orgV);
            }
        });
        String failedStr = JSON.toJSONString(failList);
        FileWriter writer;
        FileWriter writer1;
        try {
            writer = new FileWriter("src/main/resources/orgImport/company_info_failed.json");
            writer.write(failedStr);
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            writer1 = new FileWriter("src/main/resources/orgImport/company_info_msg.txt");
            writer1.write(failMsg.toString());
            writer1.flush();
            writer1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(String.format("成功条数[%s]", orgs.size()));
        System.out.println(String.format("失败条数[%s]", failList.size()));
    }

    private void insertExtraList(String orgId) {
        organizationAccountingRateMapper.insertSelective(new OrganizationAccountingRate(idService.nextId(),orgId));
        organizationApprovedLevyInfoMapper.insertSelective(new OrganizationApprovedLevyInfo(idService.nextId(),orgId));
        organizationInvoiceMapper.insertSelective(new OrganizationInvoice(idService.nextId(),orgId));
        organizationReturnRateMapper.insertSelective(new OrganizationReturnRate(idService.nextId(),orgId));
        organizationTaxOfficerMapper.insertSelective(new OrganizationTaxOfficer(idService.nextId(),orgId));
        organizationTaxRuleMapper.insertSelective(new OrganizationTaxRule(idService.nextId(),orgId));
        organizationTaxpayerQualificationMapper.insertSelective(new OrganizationTaxpayerQualification(idService.nextId(),orgId));
    }

    @Test
    public void syncOrg(){
        /**
         * 1、taxPayNums http 滴滴oa接口同步机构的信息
         * 2、逐条update,记录更新失败或未更新上的taxPayNum
         * 3、失败的再次处理
         */
        String input = "";
        try {
            File targetFile = new File("src/main/resources/orgImport/ddOrgJson3.json");
//            File targetFile = new File("src/main/resources/orgImport/failedJson.json");
            input = FileUtils.readFileToString(targetFile, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
        DDSyncOrgInfo ddSyncOrgInfo = JSONObject.parseObject(input,DDSyncOrgInfo.class);
        List<OrgSyncData> orgSyncDatas = ddSyncOrgInfo.getData();
//        List<OrgSyncData> orgSyncDatas = JSONArray.parseArray(input,OrgSyncData.class);
        orgSyncDatas.forEach(osd -> {
            OrganizationExample example = new OrganizationExample();
            example.createCriteria().andNameEqualTo(osd.getNameCN());
            Organization o = new Organization();
            o.setClientCode(osd.getCode());
            o.setCode(osd.getCode());
            o.setEnterpriseAccountCode(String.valueOf(osd.getSobId()));
            o.setEnterpriseAccountName(osd.getSobName());
            o.setCurrencyCode(osd.getCurrencyCode());
            o.setLegalEntity(osd.getLegalEntity());
            o.setLegalPersonName(osd.getLegalRepresentative());
            o.setAddress(osd.getAddress());
            o.setCreateTime(osd.getGmtCreate());
            o.setUpdateTime(osd.getGmtModified());
            o.setPsCode(osd.getPsCode());
            RegionExample regionExample = new RegionExample();
            regionExample.createCriteria().andShortNameEqualTo(osd.getCompanyLocation());
            List<Region> regions = regionMapper.selectByExample(regionExample);
            if (regions.size() > 0) {
                o.setRegionId(regions.get(0).getId());
            }
            organizationMapper.updateByExampleSelective(o, example);
        });
    }

    @Test
    public void testOrg(){
        String input = "";
        try {
//            File targetFile = new File("src/main/resources/orgImport/ddOrgJson.json");
            File targetFile = new File("src/main/resources/orgImport/failedJson.json");
            input = FileUtils.readFileToString(targetFile, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
        }
//        DDSyncOrgInfo ddSyncOrgInfo = JSONObject.parseObject(input,DDSyncOrgInfo.class);
//        List<OrgSyncData> orgSyncDatas = ddSyncOrgInfo.getData();
        List<OrgSyncData> orgSyncDatas = JSONArray.parseArray(input,OrgSyncData.class);



    }

    private void setProperty(Object obj, String propertyName, Object value) {
        try{
            Class c = obj.getClass();
            Field f = c.getDeclaredField(propertyName);
            f.setAccessible(true);
            f.set(obj, value);
        }catch (NoSuchFieldException nsfe){
            logger.error(String.format("类[%s]无[%s],应赋值[%s]",obj.getClass().getSimpleName(),propertyName,value.toString()));
        }catch (Exception e){
            e.printStackTrace();
        }

    }

}