/*
 *  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.JSON;
import com.youchain.basicdata.domain.Area;
import com.youchain.basicdata.domain.Item;
import com.youchain.basicdata.domain.Point;
import com.youchain.basicdata.repository.AreaRepository;
import com.youchain.basicdata.repository.BomAccountRepository;
import com.youchain.basicdata.repository.ItemRepository;
import com.youchain.basicdata.repository.PointRepository;
import com.youchain.businessdata.domain.*;
import com.youchain.businessdata.inputJson.buttenJson.XppRecordButton;
import com.youchain.businessdata.repository.AsnDetailRepository;
import com.youchain.businessdata.returnJson.RRkXpp;
import com.youchain.businessdata.service.InventoryLogService;
import com.youchain.businessdata.service.InventoryService;
import com.youchain.businessdata.service.dto.*;
import com.youchain.exception.BadRequestException;
import com.youchain.modules.system.domain.Job;
import com.youchain.modules.system.repository.JobRepository;
import com.youchain.utils.*;
import lombok.RequiredArgsConstructor;
import com.youchain.businessdata.repository.XppRecordRepository;
import com.youchain.businessdata.service.XppRecordService;
import com.youchain.businessdata.service.mapstruct.XppRecordMapper;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.SQLQuery;
import org.hibernate.transform.AliasToEntityMapResultTransformer;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Pageable;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.servlet.http.HttpServletResponse;

/**
 * @author baobinglin
 * @website https://eladmin.vip
 * @description 服务实现
 * @date 2024-01-04
 **/
@Slf4j
@Service
@RequiredArgsConstructor
public class XppRecordServiceImpl implements XppRecordService {

    private final XppRecordRepository xppRecordRepository;
    private final XppRecordMapper xppRecordMapper;
    private final ItemRepository itemRepository;
    private final AsnDetailRepository asnDetailRepository;
    private final PointRepository pointRepository;
    private final RedisUtils redisUtils;
    private final InventoryLogService inventoryLogService;
    private final EntityManager entityManager;
    private final BomAccountRepository bomAccountRepository;
    private final AreaRepository areaRepository;
    private final JobRepository jobRepository;
    private final InventoryService inventoryService;

    @Override
    public Map<String, Object> queryAll(XppRecordQueryCriteria criteria, Pageable pageable) {
        int pageNum=pageable.getPageNumber();//当前页
        int pageSize=pageable.getPageSize();//条数
        Query query = getQuery(criteria);
        int pageCount=query.getResultList().size();
        query.setFirstResult((pageNum)*pageSize);
        query.setMaxResults((pageNum+1)*pageSize);
        List<XppRecordViewDto> queryResultList = query.unwrap(SQLQuery.class)
                .setResultTransformer(
                        AliasToEntityMapResultTransformer.INSTANCE
                )
                .list();
        Map<String,Object> map=new HashMap<>();
        map.put("content",queryResultList);
        map.put("totalElements",pageCount);
        return map;
    }

    @Override
    public List<XppRecordViewDto> queryAll(XppRecordQueryCriteria criteria) {
        Query query = getQuery(criteria);
        List ts= query
                .unwrap(SQLQuery.class)
                .setResultTransformer(
                        AliasToEntityMapResultTransformer.INSTANCE
                )
                .list();
        List<XppRecordViewDto> list = JSON.parseArray(JSON.toJSONString(ts),XppRecordViewDto.class);
        return list;
    }

    @Override
    @Transactional
    public XppRecordDto findById(Long id) {
        XppRecord xppRecord = xppRecordRepository.findById(id).orElseGet(XppRecord::new);
        ValidationUtil.isNull(xppRecord.getId(), "XppRecord", "id", id);
        return xppRecordMapper.toDto(xppRecord);
    }

    @Override
    @Transactional
    public XppRecord getEntity(Long id) {
        XppRecord xppRecord = xppRecordRepository.findById(id).orElseGet(XppRecord::new);
        return xppRecord;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public XppRecordDto create(XppRecord resources) {
        redisUtils.del("xppRecordQueryCriteria");
        return xppRecordMapper.toDto(xppRecordRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(XppRecord resources) {
        redisUtils.del("xppRecordQueryCriteria");
        XppRecord xppRecord = xppRecordRepository.findById(resources.getId()).orElseGet(XppRecord::new);
        ValidationUtil.isNull(xppRecord.getId(), "XppRecord", "id", resources.getId());
        xppRecord.copy(resources);
        xppRecordRepository.save(xppRecord);
    }

    @Override
    public void deleteAll(Long[] ids) {
        redisUtils.del("xppRecordQueryCriteria");
        for (Long id : ids) {
            xppRecordRepository.deleteById(id);
        }
    }

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

    @Override
    public XppRecord collectFromPass(String ewm) {
        if (ewm.length() < 85) {
            throw new BadRequestException("二维码格式错误");
        }
        int i = 0;
        String gc = ewm.substring(i, i += 2);
        String pq = ewm.substring(i, i += 1);
        String pf = ewm.substring(i, i += 10);
        String ac = ewm.substring(i, i += 3);
        String jgnr = ewm.substring(i, i += 3);
        String zf = ewm.substring(i, i += 10);
        String ddbh = ewm.substring(i, i += 8);
        String nrzsr = ewm.substring(i, i += 8);
        String nrs = ewm.substring(i, i += 7);
        String gysdm = ewm.substring(i, i += 12);
        String nrcs = ewm.substring(i, i += 6);
        String zzkw = ewm.substring(i, i += 6);
        String cgkw = ewm.substring(i, i += 6);
        String fzh = ewm.substring(i, i += 3);
        Item item = itemRepository.findByCode(pf);
        if (item == null) {
            throw new BadRequestException("部品品番不存在");
        }
        XppRecord xppRecord = xppRecordRepository.findByCode(ewm);
        if (xppRecord == null) {
            xppRecord = new XppRecord();
            xppRecord.setEwm(ewm);
        } else {
            throw new BadRequestException("二维码已采集");
        }
        Long user_id=SecurityUtils.getCurrentUserId();
        List<Job> jobs=jobRepository.jobAreaCodes(user_id);
        if(jobs.size()>0){
            String areaCode= jobs.get(0).getAreaCode();
            Area area=areaRepository.getByCode(areaCode);
            if(area==null){
                throw new BadRequestException(pf+"维护岗位对应的库区");
            }
            xppRecord.setArea(area);
        }
//        Long areaId=bomAccountRepository.getItemAreaId(item.getId());
//        Area area=areaRepository.getById(areaId);
//        if(area==null){
//            throw new BadRequestException(pf+"找不到BOM对应的出库库区");
//        }
        xppRecord.setItem(item);
        xppRecord.setItemCode(pf);
        xppRecord.setAreaCode(pq);
        xppRecord.setAc(ac);
        xppRecord.setContents(jgnr);
        xppRecord.setZf(zf);
        xppRecord.setDdbh(ddbh);
        xppRecord.setNrs(Integer.valueOf(nrs));
        xppRecord.setRelaSupplier(gysdm.trim());
        xppRecord.setRelaCode(nrcs);
        xppRecord.setZPointCode(zzkw);
        xppRecord.setCPointCode(cgkw);
        xppRecord.setFzh(fzh);
        DateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        DateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Timestamp nrDate = null;
        try {
            nrDate = Timestamp.valueOf(sdf2.format(sdf.parse(nrzsr + "000000")));
        } catch (Exception e) {

        }
        xppRecord.setNrDate(nrDate);
        //采集时间
        xppRecord.setCjDate(new Timestamp(System.currentTimeMillis()));
        xppRecord.setStatus(BizStatus.RECEIVED);
        xppRecordRepository.save(xppRecord);
        return xppRecord;
    }

    @Override
    public AsnDetail addAsnDetail(XppRecord xpp) {
        AsnDetail asnDetail = new AsnDetail();
        asnDetail.setDept(UserUtils.getDept());
        asnDetail.setItem(xpp.getItem());
        asnDetail.setOrderQty(xpp.getNrs() + 0d);
        asnDetail.setPropD1(xpp.getNrDate());
        asnDetail.setPo(xpp.getDdbh());
        asnDetail.setStatus(BizStatus.RECEIVED);
        asnDetailRepository.save(asnDetail);
        xpp.setAsnDetailId(asnDetail);
        xpp.setStatus(BizStatus.RECEIVED);
        xppRecordRepository.save(xpp);
        return asnDetail;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void xppRecordQX(Long xppId) {
        //查数据
        XppRecord xppRecord = xppRecordRepository.getById(xppId);
        if (Objects.isNull(xppRecord)) {
            throw new BadRequestException("未查到现品票");
        }
        asnDetailRepository.delete(xppRecord.getAsnDetailId());
        xppRecordRepository.delete(xppRecord);
    }


    @Override
    public void xpphybf(XppRecordButton xppRecordButton) {//现品票还样部分
       //部分还样，需要补打现品票，新的现品票需要重
        XppRecord xppRecord = xppRecordRepository.getById(xppRecordButton.getXppRecordId());
        xppRecord.setStatus(BizStatus.RETENTION_IN);
        xppRecord.setHyData(new Timestamp(new Date().getTime()));
        //生成出库记录
        inventoryLogService.storeInventoryLog(BizStatus.RETENTION_IN, BizStatus.ADD, "现品票还样", null, xppRecord.getItemKey(), null, null, null, null,
                0d, xppRecord.getNrs() + 0d, null, xppRecord.getEwm(), BizStatus.RETENTION_IN, xppRecord.getId(), null, "现品票还样");
        this.update(xppRecord);
    }

    public List<PickDetail> queryPickDetailList(long picktickId) {
        String hql = " from PickDetail pd where pd.pickTicket.id=" + picktickId + " and pd.orderQty-pd.allocatedQty>0 ";
        Query query = entityManager.createQuery(hql);
        List<PickDetail> queryResultList = query.getResultList();
        return queryResultList;
    }

    public Query getQuery(XppRecordQueryCriteria criteria){
        String sql = "SELECT xpp.`id`, dictd.label rela_supplier,it.code item_code,it.name item_name,xpp.`status`, xpp.`nrs`, xpp.`ddbh`, xpp.`fzh`, \n" +
                "xpp.`nr_date` ,xpp.`cjr`,  xpp.`cj_date`,ik.prop_c1,it.extend_d3 srs,point.code inv_point_code, xpp.`ac`,xpp.contents, ott.bill_code bh_code,xpp.`bhr`, xpp.`fhr`, xpp.jsr, xpp.`zztlr`, xpp.`hctlr`,\n" +
                " xpp.`bh_date`, xpp.`fh_date`, xpp.js_date,jskw.`code` jskw, xpp.`zztl_date`,zzkw.code zzkw,  xpp.`tf_ly` tf_ly, xpp.`ly_data` ly_data, xpp.`hy_data` hy_data,xpp.be_fz,\n" +
                " xpp.`area_code`,xpp.`ewm`, xpp.`description`,xpp.ly_code\n" +
                " FROM `data_xpp_record` xpp \n" +
                "left join base_item it on it.id=xpp.item_id \n" +
                "left join data_item_key ik on ik.id=xpp.item_key_id\n" +
                "left join data_task_log otl on otl.id=ck_task_log_id\n" +
                "left join data_task ott on ott.id=otl.task_id\n" +
                "left join base_point point on point.id=xpp.inv_point_id\n" +
                "left join base_point jskw on jskw.id=xpp.jskw \n" +
                "left join base_point zzkw on zzkw.id=xpp.zzkw \n" +
                "left join sys_dict_detail dictd on  dictd.`value`=xpp.rela_supplier " +
                "where 1=1 ";
        if(criteria!=null) {
            if (criteria.getItemCode()!=null &&!criteria.getItemCode().equals("") ) {
                sql += " and it.code like '%" + criteria.getItemCode() + "%'";
            }
            if (criteria.getItemName()!=null &&!criteria.getItemName().equals("") ) {
                sql += " and it.name like '%" + criteria.getItemName() + "%'";
            }
            if (criteria.getRelaSupplier()!=null &&!criteria.getRelaSupplier().equals("") ) {
                sql += " and dictd.label like '%" + criteria.getRelaSupplier() + "%'";
            }
            if (criteria.getDdbh()!=null &&!criteria.getDdbh().equals("") ) {
                sql += " and xpp.ddbh like '%" + criteria.getDdbh() + "%'";
            }
            if (criteria.getCreateTime()!=null &&criteria.getCreateTime().size()>0 ) {
                sql += " and xpp.cj_date BETWEEN '"+criteria.getCreateTime().get(0)+"' and '"+criteria.getCreateTime().get(1)+"'";
                //sql += " and date_format(xpp.cj_date,'%Y-%m-%d %H:%i:%s')>='"+criteria.getCreateTime().get(0)+"' and date_format(xpp.cj_date,'%Y-%m-%d %H:%i:%s')<='"+criteria.getCreateTime().get(1)+"'";
            }
            if (criteria.getBhTime()!=null &&criteria.getBhTime().size()>0 ) {
                sql += " and xpp.bh_date BETWEEN '"+criteria.getBhTime().get(0)+"' and '"+criteria.getBhTime().get(1)+"'";
                //sql += " and date_format(xpp.cj_date,'%Y-%m-%d %H:%i:%s')>='"+criteria.getCreateTime().get(0)+"' and date_format(xpp.cj_date,'%Y-%m-%d %H:%i:%s')<='"+criteria.getCreateTime().get(1)+"'";
            }
            if (criteria.getEwm()!=null &&!criteria.getEwm().equals("") ) {
                sql += " and xpp.ewm like '%" + criteria.getEwm() + "%'";
            }
            if (criteria.getStatus()!=null &&!criteria.getStatus().equals("") ) {
                sql += " and xpp.status='"+criteria.getStatus()+"'";
            }
            if (criteria.getBeLy()!=null ) {
                sql += " and xpp.tf_ly="+criteria.getBeLy();
            }
            if (criteria.getBeFz()!=null  ) {
                sql += " and xpp.be_fz="+criteria.getBeFz();
            }

            sql+=" order by xpp.id desc";

        }
        Query query = entityManager.createNativeQuery(sql);
        return query;
    }


    public RRkXpp xppAnalysis(XppRecord xppRecord) {
        RRkXpp xpp = new RRkXpp();
        xpp.setId(xppRecord.getId());
        xpp.setItemCode(xppRecord.getItem().getCode());
        xpp.setItemName(xppRecord.getItem().getName());
        xpp.setAc(xppRecord.getAc());
        xpp.setDdbh(xppRecord.getDdbh());
        xpp.setNrs(Integer.valueOf(xppRecord.getNrs()));
        if(xppRecord.getNrDate()!=null) {
            xpp.setNrzsr(DateUtil.dateYmd(xppRecord.getNrDate()));
        }
        xpp.setFzh(xppRecord.getFzh());
        xpp.setGys(xppRecord.getRelaSupplier());
        xpp.setCjsj(new Date());
        return xpp;
    }

    public void xppShipOut(Long id, Area area,Point srcPoint,Point zzkw,String type,String billCode,String des) {
        XppRecord xppRecord = xppRecordRepository.getById(id);
        if(!xppRecord.getStatus().equals(BizStatus.PUTAWAY)){
            throw new BadRequestException("现品票状态不正确");
        }
        ItemKey ik = xppRecord.getItemKey();
        if(type.equals(BizStatus.RETENTION_OUT)){

        }else {
            xppRecord.setStatus(BizStatus.SHIP_ALL);
            xppRecord.setFhDate(new Timestamp(new Date().getTime()));
            xppRecord.setFhr(SecurityUtils.getCurrentUsername());
        }
        this.update(xppRecord);
        String itemCode=xppRecord.getItem().getCode();
        Inventory inventory=inventoryService.getInventory(ik,area,srcPoint,zzkw,area.getDept(),type);
        if(inventory==null){
            throw new BadRequestException(itemCode+"该库位无该批次库存");
        }
        int invQty=(int)(inventory.getQuantity()- inventory.getQueuedQty());
        if(invQty<xppRecord.getNrs()){
            throw new BadRequestException(itemCode+"库存可用不足");
        }
        double srcQty=inventory.getQuantity();
        inventory.reduce(xppRecord.getNrs());
        inventoryService.update(inventory);

        inventoryLogService.storeInventoryLog(type, BizStatus.REDUCE, billCode, area, ik, srcPoint, srcPoint, null, null, srcQty, xppRecord.getNrs()+0d,null,xppRecord.getEwm(),
                BizStatus.ASN, xppRecord.getId(), inventory.getId(), des);
    }



}