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.proofingApply.model.ProofingApplyProcess;
import com.huigou.topsun.proofing.domain.proofingApply.model.ProofingApplyProcessMaterial;
import com.huigou.topsun.proofing.domain.proofingApply.model.ProofingApplyTechnology;
import com.huigou.topsun.proofing.domain.proofingMake.model.*;
import com.huigou.topsun.proofing.domain.proofingMake.query.ProofingMakeQueryRequest;
import com.huigou.topsun.proofing.domain.vo.ProofingApplyAndLookedVo;
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.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
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;


    @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);
        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);
    }

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



