package com.huigou.topsun.proofing.application.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.huigou.data.query.model.QueryDescriptor;
import com.huigou.topsun.product.domain.ProductLooked;
import com.huigou.topsun.product.domain.ProductPublishedConf;
import com.huigou.topsun.product.repository.ProductLookedRepository;
import com.huigou.topsun.product.repository.ProductPublishedConfRepository;
import com.huigou.topsun.proofing.application.ProofingMakeApplication;
import com.huigou.topsun.proofing.domain.proofingMake.model.*;
import com.huigou.topsun.proofing.domain.proofingMake.query.ProofingMakeQueryRequest;
import com.huigou.topsun.proofing.domain.vo.ProofingMakeVo;
import com.huigou.topsun.proofing.repository.proofingApply.ProofingApplyRepository;
import com.huigou.topsun.proofing.repository.proofingMake.*;
import com.huigou.topsun.util.MyBaseUtil;
import com.huigou.uasp.bmp.common.application.BaseApplication;
import com.huigou.util.SDO;
import lombok.SneakyThrows;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author 16508
 * @description 针对表【technology(工艺)】的数据库操作Service实现
 * @createDate 2023-11-22 11:04:03
 */
@Service
public class ProofingMakeApplicationImpl extends BaseApplication implements ProofingMakeApplication {

    @Autowired
    ProductLookedRepository productLookedRepository;

    @Autowired
    ProductPublishedConfRepository productPublishedConfRepository;
    @Autowired
    ProofingMakeRepository proofingMakeRepository;
    @Autowired
    ProofingApplyRepository proofingApplyRepository;
    @Autowired
    ProofingMakeLookedRepository proofingMakeLookedRepository;
    @Autowired
    ProofingMakePdPublishedConfRepository proofingMakePdPublishedConfRepository;
    @Autowired
    ProofingMakeTechnologyRepository proofingMakeTechnologyRepository;
    @Autowired
    ProofingMakeProcessRepository proofingMakeProcessRepository;
    @Autowired
    ProofingMakeProcessMaterialRepository proofingMakeProcessMaterialRepository;

    @Autowired
    ProofingMakeBomRepository proofingMakeBomRepository;


    @Override
    public Map<String, Object> slicedProofingMakeQuery(ProofingMakeQueryRequest query) {
        QueryDescriptor queryDescriptor = this.sqlExecutorDao.getQuery(QUERY_XML_FILE_PATH, "slicedProofingMakeList");
        return this.sqlExecutorDao.executeSlicedQuery(queryDescriptor, query);
    }

    /**
     * 编辑打样制造及相关信息
     *
     * @param sdo 打样制造及相关信息
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @SneakyThrows
    @Override
    public Map<String, Object> saveProofingMake(SDO sdo) {
        HashMap<String, Object> idMap = new HashMap<>();
        ProofingMakeBaseInfo proofingMakeBaseInfo = sdo.toObject(ProofingMakeBaseInfo.class);
        ProofingMakeLooked proofingMakeLooked = sdo.toObject(ProofingMakeLooked.class);
        ProofingMakePdPublishedConf proofingMakePdPublishedConf = sdo.toObject(ProofingMakePdPublishedConf.class);


        proofingMakeBaseInfo = proofingMakeRepository.save(proofingMakeBaseInfo);
        idMap.put("proofingMakeId", proofingMakeBaseInfo.getProofingMakeId());

        proofingMakeLooked.setProofingMakeId(proofingMakeBaseInfo.getProofingMakeId());
        proofingMakeLooked = proofingMakeLookedRepository.save(proofingMakeLooked);
        idMap.put("proofingMakeLookedId", proofingMakeLooked.getProofingMakeLookedId());

        proofingMakePdPublishedConf.setProofingMakeId(proofingMakeBaseInfo.getProofingMakeId());
        proofingMakePdPublishedConf = proofingMakePdPublishedConfRepository.save(proofingMakePdPublishedConf);
        idMap.put("proofingMakePdPublishedConfId", proofingMakePdPublishedConf.getProofingMakePdPublishedConfId());

        String technologyJSON = sdo.getString("technology");
        String processJSON = sdo.getString("process");
        String processMaterialJSON = sdo.getString("processMaterial");
        ObjectMapper objectMapper = new ObjectMapper();
        ProofingMakeTechnology proofingMakeTechnology = objectMapper.readValue(technologyJSON, ProofingMakeTechnology.class);
        List<ProofingMakeProcess> ProcessList = objectMapper.readValue(processJSON, new TypeReference<List<ProofingMakeProcess>>() {
        });
        List<ProofingMakeProcessMaterial> processMaterialList = objectMapper.readValue(processMaterialJSON, new TypeReference<List<ProofingMakeProcessMaterial>>() {
        });

        /*
         * 将样品的相关工艺工序等删除
         */
        List<ProofingMakeTechnology> technologiesToDelete = proofingMakeTechnologyRepository.findAllByProofingMakeId(proofingMakeBaseInfo.getProofingMakeId());
        if (!technologiesToDelete.isEmpty()) {
            ProofingMakeTechnology technologyToDelete = technologiesToDelete.get(0);
            String proofingMakeTechnologyId = technologyToDelete.getProofingMakeTechnologyId();

            List<ProofingMakeProcessMaterial> proofingMakeTechnologyList = proofingMakeProcessMaterialRepository.findAllByProofingMakeTechnologyId(proofingMakeTechnologyId);
            proofingMakeProcessMaterialRepository.deleteInBatch(proofingMakeTechnologyList);

            List<ProofingMakeProcess> processesToDelete = proofingMakeProcessRepository.findAllByProofingMakeTechnologyId(proofingMakeTechnologyId);
            proofingMakeProcessRepository.deleteInBatch(processesToDelete);

            proofingMakeTechnologyRepository.delete(technologyToDelete);
        }

        proofingMakeTechnology.setProofingMakeId(proofingMakeBaseInfo.getProofingMakeId());
        proofingMakeTechnology = proofingMakeTechnologyRepository.save(proofingMakeTechnology);

        for (ProofingMakeProcess proofingMakeProcess : ProcessList) {
            proofingMakeProcess.setProofingMakeProcessId(null);
            proofingMakeProcess.setProofingMakeTechnologyId(proofingMakeTechnology.getProofingMakeTechnologyId());
            proofingMakeProcessRepository.save(proofingMakeProcess);
        }
        for (ProofingMakeProcessMaterial proofingMakeProcessMaterial : processMaterialList) {
            proofingMakeProcessMaterial.setProofingMakeProcessMaterialId(null);
            proofingMakeProcessMaterial.setProofingMakeTechnologyId(proofingMakeTechnology.getProofingMakeTechnologyId());
            proofingMakeProcessMaterialRepository.save(proofingMakeProcessMaterial);
        }

        String productId = proofingMakeBaseInfo.getProductId();
        //编辑产品信息
        ProductLooked productLooked = sdo.toObject(ProductLooked.class);
        productLooked.setProductId(productId);
        ProductPublishedConf productPublishedConf = sdo.toObject(ProductPublishedConf.class);
        productPublishedConf.setProductId(productId);
        ProductLooked looked = productLookedRepository.findByProductId(productLooked.getProductId());
        productLooked.setProductLookedId(looked == null ? null : looked.getProductLookedId().toString());
        productLookedRepository.save(productLooked);

        ProductPublishedConf publishedConf = productPublishedConfRepository.findByProductId(productPublishedConf.getProductId());
        productPublishedConf.setProductPublishedConfId(publishedConf == null ? null : publishedConf.getProductPublishedConfId().toString());
        productPublishedConfRepository.save(productPublishedConf);

        // 保存BOM信息
        // 获取前端传来的BOM列表
        String bomJson = sdo.getString("bom");

        // 判断是否为新增还是修改
        ProofingMakeBom proofingMakeBom1 = new ProofingMakeBom();
        proofingMakeBom1.setProofingMakeId(idMap.get("proofingMakeId").toString());
        List<ProofingMakeBom> makeBomList = proofingMakeBomRepository.findAll(Example.of(proofingMakeBom1));
        if (!makeBomList.isEmpty()) {
            // 修改 -- 删除
            makeBomList.forEach(proofingApplyBom -> proofingMakeBomRepository.delete(proofingApplyBom.getProofingMakeBomId()));
        }
        List<ProofingMakeBom> proofingMakeBomList = objectMapper.readValue(bomJson, new TypeReference<List<ProofingMakeBom>>() {
        });
        // 封装保存
        proofingMakeBomList.forEach(proofingMakeBom -> {
            proofingMakeBom.setProofingMakeId(idMap.get("proofingMakeId").toString());
            // 保存
            proofingMakeBomRepository.save(proofingMakeBom);
//            proofingMakeBom.setProductMaterialName(null);
        });

        // 给SAP返回BOM-JSON数据
        String returnJson = getReturnJson(proofingMakeBomList);

        return idMap;
    }

    @Override
    public ProofingMakeVo getProofingMakeVoById(String proofingMakeId) {
        ProofingMakeVo proofingMakeVo = new ProofingMakeVo();
        ProofingMakeBaseInfo proofingMake = proofingMakeRepository.findOne(proofingMakeId);
        if (proofingMake == null) return null;
        ProofingMakeLooked proofingMakeLooked = proofingMakeLookedRepository.findByProofingMakeId(proofingMakeId);
        ProofingMakePdPublishedConf proofingMakePdPublishedConf = proofingMakePdPublishedConfRepository.findByProofingMakeId(proofingMakeId);
        MyBaseUtil.mergeObjects(proofingMakeVo,
                proofingMake,
                proofingMakeLooked,
                proofingMakePdPublishedConf);
        return proofingMakeVo;
    }

    /**
     * 映射打样制造和打样申请 除前缀不一样的字段
     *
     * @param vo
     * @throws IllegalAccessException
     */
    public Map<String, Object> mappingReplacementMap(ProofingMakeVo vo) throws IllegalAccessException {
        Map<String, Object> proofingMake = new HashMap<>();

        Class<?> proofingApplyClass = vo.getClass();
        Field[] fields = proofingApplyClass.getDeclaredFields();

        for (Field field : fields) {
            field.setAccessible(true);
            String name = field.getName();
            if (!name.equals("proofingApplyId") && !name.equals("proofingApplyNo") && !name.equals("proofingApplyApplicationStatus")) {
                Object value = field.get(vo);
                String proofingMakeName = name.replaceFirst("^proofingApply", "proofingMake");
                proofingMake.put(proofingMakeName, value);
            } else {
                Object value = field.get(vo);
                proofingMake.put(name, value);
            }
        }
        return proofingMake;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void deleteProofingMakeById(String id) {
        ProofingMakeBaseInfo proofingMakeBaseInfo = proofingMakeRepository.findOne(id);
        proofingMakeBaseInfo.setIsDelete("1");
        proofingMakeRepository.save(proofingMakeBaseInfo);
    }

    /**
     * 返回JSON数据
     *
     * @return
     */
    public String getReturnJson(List<ProofingMakeBom> bomJson) {
        List<ProofingMakeBom> proofingMakeBoms = new ArrayList<>();
        bomJson.forEach(bom -> {
            ProofingMakeBom proofingMakeBom = new ProofingMakeBom();
            BeanUtils.copyProperties(bom, proofingMakeBom);
            proofingMakeBom.setProductMaterialName(null);
            proofingMakeBoms.add(proofingMakeBom);
        });
        ObjectMapper objectMapper = new ObjectMapper();
        String json = null;
        try {
            json = objectMapper.writeValueAsString(proofingMakeBoms);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        String returnJson = json.replaceAll("materialId", "IDNRK")
                .replaceAll("materialNumber", "MENGE")
                .replaceAll("materialUnit", "MEINS")
                .replaceAll("materialJson", "POTX2")
                .replaceAll("\"materialName\":null,", "");

        return returnJson;
    }

    @Override
    @Transactional
    public void deleteProofingMakeByIds(List<String> ids) {
        ids.forEach(this::deleteProofingMakeById);
    }
}




