/*
*  Copyright 2019-2020 Zheng Jie
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package com.youchain.basicdata.service.impl;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import com.youchain.basicdata.domain.BigItem;
import com.youchain.basicdata.domain.BomAccount;
import com.youchain.basicdata.domain.BomAccountLog;
import com.youchain.basicdata.domain.Item;
import com.youchain.basicdata.service.BomAccountLogService;
import com.youchain.basicdata.service.PointService;
import com.youchain.basicdata.service.dto.TableConfigDto;
import com.youchain.basicdata.service.dto.TableConfigQueryCriteria;
import com.youchain.modules.system.domain.Dict;
import com.youchain.modules.system.domain.DictDetail;
import com.youchain.modules.system.service.dto.DictDto;
import com.youchain.modules.system.service.dto.DictQueryCriteria;
import com.youchain.modules.system.service.impl.DictDetailServiceImpl;
import com.youchain.modules.system.service.impl.DictServiceImpl;
import com.youchain.utils.*;
import lombok.RequiredArgsConstructor;
import com.youchain.basicdata.repository.BomAccountRepository;
import com.youchain.basicdata.service.BomAccountService;
import com.youchain.basicdata.service.dto.BomAccountDto;
import com.youchain.basicdata.service.dto.BomAccountQueryCriteria;
import com.youchain.basicdata.service.mapstruct.BomAccountMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.*;
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.servlet.http.HttpServletResponse;

/**
* @website https://eladmin.vip
* @description 服务实现
* @author baobinglin
* @date 2024-01-02
**/
@Service
@Slf4j
@RequiredArgsConstructor
@CacheConfig(cacheNames = "bomAccount")
public class BomAccountServiceImpl implements BomAccountService {

    private final BomAccountRepository bomAccountRepository;
    private final BomAccountMapper bomAccountMapper;
    private final PointService pointService;
    private final EntityManager entityManager;
    private final RedisUtils redisUtils;
    private final BomAccountLogService bomAccountLogService;

    @Override
    @Cacheable(key = "'queryALL1:' + #p0")
    public Map<String,Object> queryAll(BomAccountQueryCriteria criteria, Pageable pageable){
        Page<BomAccount> page = bomAccountRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(bomAccountMapper::toDto));
    }

    @Override
    @Cacheable(key = "'queryALL2:' + #p0")
    public List<BomAccountDto> queryAll(BomAccountQueryCriteria criteria){
        return bomAccountMapper.toDto(bomAccountRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    @Cacheable(key = "'id:' + #p0")
    public BomAccountDto findById(Long id) {
        BomAccount bomAccount = bomAccountRepository.findById(id).orElseGet(BomAccount::new);
        ValidationUtil.isNull(bomAccount.getId(),"BomAccount","id",id);
        return bomAccountMapper.toDto(bomAccount);
    }

    @Override
    @Transactional
    public BomAccount findByEntity(Long id) {
        BomAccount bomAccount = bomAccountRepository.findById(id).orElseGet(BomAccount::new);
        ValidationUtil.isNull(bomAccount.getId(),"BomAccount","id",id);
        return bomAccount;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public BomAccountDto create(BomAccount resources) {
        resources.setDept(UserUtils.getDept());
        BomAccount ba=bomAccountRepository.save(resources);
        delCaches();
        return bomAccountMapper.toDto(ba);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(BomAccount resources) {
        BomAccount bomAccount = bomAccountRepository.findById(resources.getId()).orElseGet(BomAccount::new);
        ValidationUtil.isNull( bomAccount.getId(),"BomAccount","id",resources.getId());
        bomAccount.copy(resources);
        bomAccountRepository.save(bomAccount);
        delCaches();
    }

    @Override
    public void deleteAll(Long[] ids) {
        for (Long id : ids) {
            bomAccountLogService.copyBomAccount(id,"del");
            bomAccountRepository.deleteById(id);
        }
        delCaches();

    }
    public void delCaches(){

        Set<Object> keys=redisUtils.getAllKey("*bomAccount*");
        for (Object key:keys) {
            log.error("key:"+key);
            redisUtils.del(key.toString());
        }


    }

    @Override
    public void download(List<BomAccountDto> all, HttpServletResponse response) throws Exception {
        List<Map<String, Object>>  list=ExcelDownUtils.CreateMap(all,"BomAccount");
        FileUtil.downloadExcel(list, response);
    }



    @Override
    public List<BigItem> queryBigItemByType(String stationType) {
        String hql = "select t.bigItem from BomAccount t where t.stationType = '" + stationType + "' group by t.bigItem";
        Query query = entityManager.createQuery(hql);
        List<BigItem> resultList = query.getResultList();
        if (!resultList.isEmpty()){
            return resultList;
        }
        return  null;
    }


    @Override
    @Cacheable(key = "'areaid:' + #p0")
    public List<BomAccountDto> queryByArea(Long areaId) {
//        String hql = "from BomAccount ba where ba.rArea.id = " + areaId+" group by ba.item.id,ba.zPoint.id";
        String hql = "from BomAccount ba where ba.rArea.id = " + areaId+" and ba.id in (select max(t.id) from BomAccount t where t.rArea.id = " + areaId + " group by t.item.id,t.zPoint.id)";
        Query query = entityManager.createQuery(hql);
        List<BomAccount> resultList = query.getResultList();
        long ed=System.currentTimeMillis();
        return  bomAccountMapper.toDto(resultList);
    }

    @Override
    public List queryItemByArea(Long areaId) {
        String hql = "select max(t.id),t.item.id,max(t.item.code),max(t.item.name),t.zPoint.id,max(t.zPoint.code),max(t.rArea.id),max(t.rArea.code) from BomAccount t where t.rArea.id = " + areaId + " group by t.item.id,t.zPoint.id";
        Query query = entityManager.createQuery(hql);
        List<Object[]> resultList = query.getResultList();
        JSONArray array=new JSONArray();
        if (resultList.size()>0){
            for(Object[] obj:resultList){
                HashMap<String,Object> d=new HashMap<>();
                d.put("id",obj[0]);
                d.put("itemId",obj[1]);
                d.put("itemCode",obj[2]);
                d.put("itemName",obj[3]);
                d.put("zzkwId",obj[4]);
                d.put("zzkwCode",obj[5]);
                d.put("rAreaId",obj[6]);
                d.put("rAreaCode",obj[7]);
                array.add(d);
            }
        }
        return  array;
    }

    public List<BomAccount> queryBomAccount(Long bigItemId,Long shAreaId,String gw) {
        String hql = "from BomAccount t where t.bigItem.id="+bigItemId+" and t.outType='单点' and t.item.enabled=true";
        if(shAreaId!=null){
            hql+=" and t.rArea.id = " + shAreaId;
        }
        if(gw!=null&&!gw.equals("")){
            hql+=" and t.rArea.workingStation = '" + gw+"'";
        }
        Query query = entityManager.createQuery(hql);
        List<BomAccount> resultList = query.getResultList();
        return  resultList;
    }

    @Override
    public List<Object[]> queryBomAccountList(String code,Long outAreaId, Long shAreaId,String bp_type,String type) {
        String hql =null;
        if(type.equals("0")){
             hql = "select t.cArea.id,t.bp_type from BomAccount t,PlanPickDetail  ptd " +
                    " where ptd.code='"+code+"' and t.bigItem.id=ptd.bigItem.id and t.outType='单点' and t.item.enabled=true and t.rArea.id = " + shAreaId +
                    " group by t.cArea.id,t.bp_type " +
                     " order by t.cArea.id";
        }else{
            hql = "select max(t.id),sum(t.singles*ptd.orderQuantity) from BomAccount t,PlanPickDetail  ptd " +
                    " where ptd.code='"+code+"' and t.bigItem.id=ptd.bigItem.id and t.outType='单点' and t.item.enabled=true and t.rArea.id = " + shAreaId +
                    " and t.cArea.id="+outAreaId +
                    " and t.bp_type='"+bp_type+"'" +
                    " group by t.zPoint.id,t.item.id";
        }
        Query query = entityManager.createQuery(hql);
        List<Object[]> resultList = query.getResultList();
        return  resultList;
    }

    public List<Object[]> bomAccountAreas(String code, Long shAreaId,String bp_type,String type) {
        String hql =null;
        if(type.equals("0")){
            hql = "select t.cArea.id,t.bp_type from BomAccount t,PlanPickDetail  ptd " +
                    " where ptd.code='"+code+"' and t.bigItem.id=ptd.bigItem.id and t.outType='单点' and t.item.enabled=true and t.rArea.id = " + shAreaId +
                    " group by t.cArea.id,t.bp_type " +
                    " order by t.cArea.id";
        }else{
            hql = "select t.cArea.id,max(t.id),sum(t.singles*ptd.orderQuantity) from BomAccount t,PlanPickDetail  ptd " +
                    " where ptd.code='"+code+"' and t.bigItem.id=ptd.bigItem.id and t.outType='单点' and t.item.enabled=true and t.rArea.id = " + shAreaId +
                    " and t.bp_type='"+bp_type+"'" +
                    " group by t.cArea.id,t.zPoint.id,t.item.id";
        }
        Query query = entityManager.createQuery(hql);
        List<Object[]> resultList = query.getResultList();
        return  resultList;
    }

    @Override
    public List<BomAccount> queryBomAccountList(BomAccount bomAccount) {
        String hql = "from BomAccount t where 1=1 and t.item.enabled=true";
        if (bomAccount.getBigItem() != null){
            hql += " and t.bigItem.id = " + bomAccount.getBigItem().getId();
        }else if (bomAccount.getStationType() != null){
            hql += " and t.stationType = '" + bomAccount.getStationType() + "'";
        }
        Query query = entityManager.createQuery(hql);
        List<BomAccount> resultList = query.getResultList();
        return resultList;
    }

    @Override
    public void updateBatch(Long areaId) {
        String sql="update base_bom_account bom set bom.pc_qty=0 where bom.r_area_id="+areaId;
        Query query=entityManager.createNativeQuery(sql);
        query.executeUpdate();
    }


}