/*
*  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.businessdata.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.youchain.basicdata.domain.BillType;
import com.youchain.basicdata.domain.Item;
import com.youchain.basicdata.domain.Point;
import com.youchain.basicdata.domain.Stock;
import com.youchain.basicdata.repository.BillTypeRepository;
import com.youchain.basicdata.repository.ItemRepository;
import com.youchain.basicdata.service.BillTypeService;
import com.youchain.basicdata.service.ItemService;
import com.youchain.basicdata.service.StockService;
import com.youchain.businessdata.domain.Asn;
import com.youchain.businessdata.domain.AsnDetail;
import com.youchain.businessdata.repository.AsnRepository;
import com.youchain.businessdata.repository.TaskRepository;
import com.youchain.businessdata.service.AsnService;
import com.youchain.utils.*;
import lombok.RequiredArgsConstructor;
import com.youchain.businessdata.repository.AsnDetailRepository;
import com.youchain.businessdata.service.AsnDetailService;
import com.youchain.businessdata.service.dto.AsnDetailDto;
import com.youchain.businessdata.service.dto.AsnDetailQueryCriteria;
import com.youchain.businessdata.service.mapstruct.AsnDetailMapper;
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.sql.Timestamp;
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 hjl
* @date 2023-08-14
**/
@Service
@RequiredArgsConstructor
public class AsnDetailServiceImpl implements AsnDetailService {

    private final AsnDetailRepository asnDetailRepository;
    private final AsnDetailMapper asnDetailMapper;
    private final AsnService asnService;
    private final AsnRepository asnRepository;
    private final EntityManager entityMapper;
    private final TaskRepository taskRepository;
    private final ItemRepository itemRepository;
    private final ItemService itemService;
    private final StockService stockService;
    private final BillTypeRepository billTypeRepository;

    @Override
    public Map<String,Object> queryAll(AsnDetailQueryCriteria criteria, Pageable pageable){
        Page<AsnDetail> page = asnDetailRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable);
        return PageUtil.toPage(page.map(asnDetailMapper::toDto));
    }

    @Override
    public List<AsnDetailDto> queryAll(AsnDetailQueryCriteria criteria){
        return asnDetailMapper.toDto(asnDetailRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));
    }

    @Override
    @Transactional
    public AsnDetailDto findById(Long id) {
        AsnDetail asnDetail = asnDetailRepository.findById(id).orElseGet(AsnDetail::new);
        ValidationUtil.isNull(asnDetail.getId(),"AsnDetail","id",id);
        return asnDetailMapper.toDto(asnDetail);
    }

    @Override
    @Transactional
    public AsnDetail getEntity(Long id) {
        AsnDetail asnDetail = asnDetailRepository.findById(id).orElseGet(AsnDetail::new);
        return asnDetail;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AsnDetailDto create(AsnDetail resources) {
        return asnDetailMapper.toDto(asnDetailRepository.save(resources));
    }

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

    @Override
    public void deleteAll(Long[] ids) {
        for (Long id : ids) {
            asnDetailRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<AsnDetailDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (AsnDetailDto asnDetail : all) {
            Map<String,Object> map = new LinkedHashMap<>();
            map.put("订单序号", asnDetail.getAsn());
            map.put("物料", asnDetail.getItem());
            map.put("容器", asnDetail.getStock());
            map.put("点位", asnDetail.getPoint());
            map.put("行号", asnDetail.getLineNo());
            map.put("MO票", asnDetail.getPo());
            map.put("状态", asnDetail.getStatus());
            map.put("订单数量", asnDetail.getOrderQty());
            map.put("收货数量", asnDetail.getReceivedQty());
            map.put("移位数量", asnDetail.getMoveQty());
            map.put("上架数量", asnDetail.getPutQty());
            map.put("重量", asnDetail.getWeight());
            map.put("体积", asnDetail.getVolume());
            map.put("备注", asnDetail.getRemark());
            map.put("批次号", asnDetail.getPropC1());
            map.put("序列号", asnDetail.getPropC2());
            map.put("属性3", asnDetail.getPropC3());
            map.put("属性4", asnDetail.getPropC4());
            map.put("属性5", asnDetail.getPropC5());
            map.put("属性6", asnDetail.getPropC6());
            map.put("生产日期", asnDetail.getPropD1());
            map.put("到期日期", asnDetail.getPropD2());
            map.put("仓库ID", asnDetail.getDept());
            map.put("来源名称", asnDetail.getSourceName());
            map.put("来源序号", asnDetail.getSourceId());
            map.put("创建人", asnDetail.getCreateBy());
            map.put("修改人", asnDetail.getUpdateBy());
            map.put("创建时间", asnDetail.getCreateTime());
            map.put("修改时间", asnDetail.getUpdateTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public  AsnDetail toEntity(AsnDetailDto detailDto) {
        return asnDetailMapper.toEntity(detailDto);
    }
    @Override
    public AsnDetail findByStock(String code){
        String hql="select d from AsnDetail d where d.stock.code='"+code+"' and d.status='"+ BizStatus.OPEN+"'";
        Query query=entityMapper.createQuery(hql);
        List<AsnDetail> ts=query.getResultList();
        if(ts.size()>0){
            return ts.get(0);
        }
        return  null;
    }

    public List<Object[]>  queryIn(String type,String date,String zoneType){
        String hql="";
        if(type.equals("Day")){
            hql="select sum(d.orderQty),sum(d.receivedQty) from AsnDetail d " +
                    " where DATE_FORMAT(d.createTime,'%Y-%m-%d')=DATE_FORMAT(now(),'%Y-%m-%d')";
        }else if(type.equals("Month")){
            hql="select sum(d.orderQty),sum(d.receivedQty) from AsnDetail d " +
                    " where DATE_FORMAT(d.createTime,'%Y-%m')=DATE_FORMAT(now(),'%Y-%m')";
        }else if(type.equals("InOutDay")){
            hql="select DATE_FORMAT(d.createTime,'%Y-%m-%d'),sum(d.receivedQty) from AsnDetail d " +
                    " where DATE_FORMAT(d.createTime,'%Y-%m-%d')>='"+date+"' " +
                    " group by DATE_FORMAT(d.createTime,'%Y-%m-%d')";
        }
        Query query=entityMapper.createQuery(hql);
        List<Object[]> ts=query.getResultList();
        return  ts;
    }


    @Override
    public AsnDetail createAsnDetail(AsnDetail asnDetail){
        Asn asn=asnRepository.findByRelatedBill1(asnDetail.getAsn().getRelatedBill1());
        asnDetail.setAsn(asn);
        asnDetail=asnDetailRepository.save(asnDetail);
        return  asnDetail;
    }

    @Override
    public boolean findByMo(String Mo) {
        String hql =" from AsnDetail ad where ad.po='"+Mo+"' ";
        Query query=entityMapper.createQuery(hql);
        List<AsnDetail> asnDetailList=query.getResultList();
        if(asnDetailList.size()>0){
            return true;
        }
        return false;
    }

    @Override
    public String importAsnApi(JSONObject jsonObject) {
        System.out.println("接收入库单："+jsonObject);
        String relatedBill1=jsonObject.getString("expectedReceiptId");//入库单号
        String erTime=jsonObject.getString("expectedReceiptDate");//操作时间
        String billTypeCode=jsonObject.getString("expectedReceiptType");//入库类型
        String structure=jsonObject.getString("owner");//货主

        List<BillType> billTypeList=billTypeRepository.findBySourceName(billTypeCode);
        if (billTypeList.size()<1){
            return "单据类型错误";
        }
        BillType billType=billTypeList.get(0);
        Timestamp er = Timestamp.valueOf(DateUtil.parseLocalDateTimeFormat(erTime, "yyyy-MM-dd HH:mm:ss"));
        Asn asn = asnService.addAsn(billType,relatedBill1,structure,"SAP推送",er);

        JSONArray erLineList = jsonObject.getJSONArray("erLine");
        for (int i = 0; i < erLineList.size(); i++) {
            JSONObject erLine=erLineList.getJSONObject(i);
            String itemCode=erLine.getString("productId");//料号
            Item item=itemRepository.findByCode(itemCode);
            if (item==null){
                return "没有查询到物料号："+itemCode;
            }
            String lineNo=erLine.getString("lineNumber");//行号
            String quantityExpected=erLine.getString("quantityExpected");//数量
            JSONArray attributeValueList=erLine.getJSONArray("attributeValue");
            Map<String,Object> attributeValue=new HashMap<>();
            for (int j = 0; j < attributeValueList.size(); j++) {
                JSONObject at=attributeValueList.getJSONObject(j);
                attributeValue.put(at.getString("name"),at.getString("value"));
            }

            AsnDetail asnDetail=new AsnDetail();
            List<AsnDetail> asnDetailList=asnDetailRepository.findByLineNo(asn.getId(),Long.valueOf(lineNo));
            if (asnDetailList.size()>0){
                asnDetail=asnDetailList.get(0);
            }else {
                asnDetail.setStatus(BizStatus.OPEN);
            }
            asnDetail.setItem(item);
            asnDetail.setLineNo(Long.valueOf(lineNo));
            asnDetail.setOrderQty(Double.valueOf(quantityExpected));
            asnDetail.setAsn(asn);
            asnDetail.setDept(UserUtils.getDept());
            asnDetail.setPropC1(attributeValue.get("ztBidName")+"");
            asnDetail.setPropC2(attributeValue.get("prodMtrlNo")+"");
            asnDetail.setPropC3(attributeValue.get("loadUnitId")+"");
            asnDetailRepository.save(asnDetail);
        }
        return null;
    }

    @Override
    public void receivingAsnDetail(AsnDetail asnDetail, Double qty) {
        asnDetail.setReceivedQty(asnDetail.getReceivedQty()+qty);
        if (asnDetail.getOrderQty()<=asnDetail.getReceivedQty()){
            asnDetail.setStatus(BizStatus.RECEIVED);
            List<AsnDetail> asnDetailList=asnDetailRepository.findByAsnId(asnDetail.getAsn().getId(),BizStatus.RECEIVING);
            if (asnDetailList.size()<2){
                Asn asn=asnDetail.getAsn();
                asn.setStatus(BizStatus.RECEIVED);
                asnRepository.save(asn);
            }
        }else {
            asnDetail.setStatus(BizStatus.RECEIVING);
        }

        asnDetailRepository.save(asnDetail);
    }
}
