/*
 *  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 cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.youchain.basicdata.domain.Item;
import com.youchain.basicdata.repository.StockRepository;
import com.youchain.basicdata.service.dto.StockSmallDto;
import com.youchain.businessdata.ReturnJson.RPTaskList;
import com.youchain.businessdata.domain.*;
import com.youchain.businessdata.inputJson.IPTask;
import com.youchain.businessdata.repository.InventoryRepository;
import com.youchain.businessdata.repository.PickDetailRepository;
import com.youchain.businessdata.repository.TaskLogRepository;
import com.youchain.businessdata.service.InventoryLogService;
import com.youchain.businessdata.service.dto.InventoryDto;
import com.youchain.modules.system.domain.Dept;
import com.youchain.utils.*;
import lombok.RequiredArgsConstructor;
import com.youchain.businessdata.repository.TaskRepository;
import com.youchain.businessdata.service.TaskService;
import com.youchain.businessdata.service.dto.TaskDto;
import com.youchain.businessdata.service.dto.TaskQueryCriteria;
import com.youchain.businessdata.service.mapstruct.TaskMapper;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.SQLQuery;
import org.hibernate.transform.AliasToEntityMapResultTransformer;
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.security.PrivateKey;
import java.util.*;
import java.io.IOException;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.servlet.http.HttpServletResponse;

/**
 * @author houjianlan
 * @website https://eladmin.vip
 * @description 服务实现
 * @date 2023-08-16
 **/
@Service
@RequiredArgsConstructor
@Slf4j
public class TaskServiceImpl implements TaskService {

    private final TaskRepository taskRepository;
    private final TaskMapper taskMapper;
    private final InventoryRepository inventoryRepository;
    private final TaskLogRepository taskLogRepository;
    private final PickDetailRepository pickDetailRepository;
    private final InventoryLogService inventoryLogService;
    private final EntityManager entityMapper;

    private final StockRepository stockRepository;
    @Override
    public Map<String, Object> queryAll(TaskQueryCriteria criteria, Pageable pageable) {
        Page<Task> page = taskRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(taskMapper::toDto));
    }

    @Override
    public List<TaskDto> queryAll(TaskQueryCriteria criteria) {
        return taskMapper.toDto(taskRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public TaskDto findById(Long id) {
        Task task = taskRepository.findById(id).orElseGet(Task::new);
        ValidationUtil.isNull(task.getId(), "Task", "id", id);
        return taskMapper.toDto(task);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TaskDto create(Task resources) {
        return taskMapper.toDto(taskRepository.save(resources));
    }

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

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

    @Override
    public void download(List<TaskDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (TaskDto task : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("物料序号", task.getItem());
            map.put("物料序号", task.getItemKey());
            map.put("单据号", task.getBillCode());
            map.put("任务类型", task.getTaskType());
            map.put("收货明细序号", task.getAsnDetail());
            map.put("移位明细序号", task.getMoveDetailId());
            map.put("波次明细序号", task.getWaveDetailId());
            map.put("发货明细序号", task.getPickDetail());
            map.put("源容器", task.getSrcStock());
            map.put("目标容器", task.getDstStock());
            map.put("源点位", task.getSrcPoint());
            map.put("目标点位", task.getDstPoint());
            map.put("源容器编码", task.getSrcStockCode());
            map.put("目标容器编码", task.getDstStockCode());
            map.put("源点位编码", task.getSrcPointCode());
            map.put("目标点位编码", task.getDstPointCode());
            map.put("属性6", task.getInvStatus());
            map.put("任务状态", task.getTaskStatus());
            map.put("跳过", task.getBeSkip());
            map.put("退回", task.getBeBack());
            map.put("计划数量", task.getPlanQty());
            map.put("移位数量", task.getMoveQty());
            map.put("上架号", task.getPutCode());
            map.put("库存ID", task.getInvId());
            map.put("仓库ID", task.getDept());
            map.put("创建人", task.getCreateBy());
            map.put("修改人", task.getUpdateBy());
            map.put("创建时间", task.getCreateTime());
            map.put("修改时间", task.getUpdateTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public Task toEntity(TaskDto taskDto) {
        return taskMapper.toEntity(taskDto);
    }

    @Override
    public Task storeTask() {
        return null;
    }

    @Override
    public List<Task> getPickNotAllTask(Long id) {
        return taskRepository.getPickNotAllTask(id);
    }

    @Override
    public List<Task> getPickAllTask(Long id) {
        return taskRepository.getPickAllTask(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void pickConfirm(long taskId, double pickedQuantity) throws Exception {
        if (taskId > 0) {
            TaskDto taskDto = findById(taskId);
            Task task = taskMapper.toEntity(taskDto);//Dto转实体
            if (task.getPlanQty() > task.getMoveQty()) {
                PickDetail pickDetail = task.getPickDetail();
                task.setMoveQty(pickedQuantity);
                taskRepository.save(task);
                Inventory inv = inventoryRepository.findById(task.getInvId()).get();
                if (inv != null) {
                    ItemKey itemKey = inv.getItemKey();
                    Item item = itemKey.getItem();
                    Dept dept = item.getDept();
                    double srcQty=inv.getQuantity();
                    inv.setQuantity(inv.getQuantity() - pickedQuantity);
                    inv.setQueuedQty(inv.getQueuedQty() - pickedQuantity);
                    inventoryRepository.save(inv);

                    //添加库存日志
                    inventoryLogService.storeInventoryLog(BizStatus.PICK_DOWN,BizStatus.REDUCE,task.getPickDetail().getPo(),task.getItemKey(),task.getSrcPoint(),task.getDstPoint(),task.getSrcStock(),task.getDstStock(),srcQty,pickedQuantity, BizStatus.PICK,task.getId(),inv.getId(),"");

                    //刷新出库明细上的拣货数量
                    pickDetail.setPickedQty(pickDetail.getPickedQty() + pickedQuantity);
                    if (pickDetail.getOrderQty().equals(pickDetail.getPickedQty())) {
                        pickDetail.setStatus(BizStatus.PICK_ALL);
                    } else if (pickDetail.getAllocatedQty() > 0 && pickDetail.getOrderQty() - pickDetail.getPickedQty() > 0) {
                        pickDetail.setStatus(BizStatus.PICKUP);
                    }
                    pickDetailRepository.save(pickDetail);

                } else {
                    throw new RuntimeException("未找到库存相应记录！");
                }
            }

        } else {
            throw new RuntimeException("参数错误或为空");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized void pickBarBack(long taskId, double pickedQuantity) throws Exception {
        if (taskId > 0) {
            TaskDto taskDto = findById(taskId);
            Task task = taskMapper.toEntity(taskDto);//Dto转实体
            PickDetail pickDetail = task.getPickDetail();
            Inventory inv = inventoryRepository.findById(task.getInvId()).get();
            if (inv != null) {
                //退回库存
                double srcQty=inv.getQueuedQty();
                inv.setQueuedQty(inv.getQueuedQty()+pickedQuantity);
                inv.setQuantity(inv.getQuantity()+pickedQuantity);
                inventoryRepository.save(inv);

                //添加库存日志
                inventoryLogService.storeInventoryLog(BizStatus.PICK_CANCEL,BizStatus.ADD,task.getPickDetail().getPo(),task.getItemKey(),task.getDstPoint(),task.getSrcPoint(),task.getSrcStock(),task.getDstStock(),srcQty,pickedQuantity, BizStatus.PICK,task.getId(),inv.getId(),"");


                //退回Task
                task.setMoveQty(task.getMoveQty() - pickedQuantity);
                taskRepository.save(task);

                //退回出库明细
                pickDetail.setPickedQty(pickDetail.getPickedQty() - pickedQuantity);
                if (pickDetail.getPickedQty() == 0) {
                    pickDetail.setStatus(BizStatus.ALLOCATE);
                }
                pickDetailRepository.save(pickDetail);
            } else {
                throw new RuntimeException("未找到库存相应记录！");
            }

        } else {
            throw new RuntimeException("参数错误或为空");
        }
    }

    @Transactional(readOnly = true)
    public  List<RPTaskList> queryTaskApp(IPTask t){
        String sql="SELECT t.pick_detail_id pickDetailId, it.code itemCode,it.`name` itemName,t.plan_qty qty,ik.prop_c1 pch,t.src_point_code srcPointCode,t.src_stock_code stockCode,t.dst_point_code dstPointCode\n" +
                " from data_task t\n" +
                "left join data_pick_detail d on t.pick_detail_id=d.id\n" +
                "left join data_item_key ik on ik.id=t.item_key_id\n" +
                "left join base_item it on it.id=ik.item_id\n" +
                "where d.`status`='ALLOCATE' \n" +
                "ORDER BY it.code";
        List ts= entityMapper.createNativeQuery(sql)
                .unwrap(SQLQuery.class)
                .setResultTransformer(
                        AliasToEntityMapResultTransformer.INSTANCE
                )
                .list();
        log.error(JSON.toJSONString(ts));
        List<RPTaskList> l = JSON.parseArray(JSON.toJSONString(ts),RPTaskList.class);
        return  l;
    }
}