package cn.iocoder.yudao.module.mes.controller.admin.feedingrecord;

import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutRespVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO;
import cn.iocoder.yudao.module.mes.controller.admin.feedingrecord.vo.*;
import cn.iocoder.yudao.module.mes.controller.admin.itemrequisition.vo.ItemRequisitionDetailRespVO;
import cn.iocoder.yudao.module.mes.controller.admin.plan.vo.PlanStatusEnum;
import cn.iocoder.yudao.module.mes.dal.dataobject.feedingplan.FeedingRecordPlanDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.feedingrecord.FeedingRecordDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.feedingrecord.FeedingRecordDetailDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.itemrequisition.ItemRequisitionDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.organization.OrganizationDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.plan.PlanDO;
import cn.iocoder.yudao.module.mes.dal.mysql.feedingrecord.FeedingRecordDetailMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.feedingrecord.FeedingRecordMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.itemrequisition.ItemRequisitionMapper;
import cn.iocoder.yudao.module.mes.service.feedingrecord.FeedingRecordService;
import cn.iocoder.yudao.module.mes.service.itemrequisition.ItemRequisitionService;
import cn.iocoder.yudao.module.mes.service.organization.OrganizationService;
import cn.iocoder.yudao.module.mes.service.plan.PlanService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.FEEDING_RECORD_NOT_EXISTS;

@Tag(name = "管理后台 - 投料记录")
@RestController
@RequestMapping("/mes/feeding-record")
@Validated
public class FeedingRecordController {

    @Resource
    private FeedingRecordService feedingRecordService;

    @Resource
    private OrganizationService organizationService;

    @Resource
    private FeedingRecordDetailMapper feedingRecordDetailMapper;

    @PostMapping("/create")
    @Operation(summary = "创建投料记录")
    @PreAuthorize("@ss.hasPermission('mes:feeding-record:create')")
    public CommonResult<Long> createFeedingRecord(@Valid @RequestBody FeedingRecordSaveReqVO createReqVO) {
        Long userId = getLoginUserId();
        createReqVO.setUserId(userId);
        if(createReqVO.getFeedingTime()==null)
            createReqVO.setFeedingTime(LocalDateTime.now());
        return success(feedingRecordService.createFeedingRecord(createReqVO));
    }

    @PutMapping("/update")
    @Operation(summary = "更新投料记录")
    @PreAuthorize("@ss.hasPermission('mes:feeding-record:update')")
    public CommonResult<Boolean> updateFeedingRecord(@Valid @RequestBody FeedingRecordSaveReqVO updateReqVO) {
        Long userId = getLoginUserId();
        updateReqVO.setUserId(userId);
        if(updateReqVO.getFeedingTime()==null)
            updateReqVO.setFeedingTime(LocalDateTime.now());
        feedingRecordService.updateFeedingRecord(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除投料记录")
    @Parameter(name = "id", description = "编号", required = true)
    @PreAuthorize("@ss.hasPermission('mes:feeding-record:delete')")
    public CommonResult<Boolean> deleteFeedingRecord(@RequestParam("id") Long id) {
        feedingRecordService.deleteFeedingRecord(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得投料记录")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    @PreAuthorize("@ss.hasPermission('mes:feeding-record:query')")
    public CommonResult<FeedingRecordRespVO> getFeedingRecord(@RequestParam("id") Long id) {
        FeedingRecordDO feedingRecord = feedingRecordService.getFeedingRecord(id);
        return success(BeanUtils.toBean(feedingRecord, FeedingRecordRespVO.class));
    }

    @GetMapping("/page")
    @Operation(summary = "获得投料记录分页")
    @PreAuthorize("@ss.hasPermission('mes:feeding-record:query')")
    public CommonResult<PageResult<FeedingRecordRespVO>> getFeedingRecordPage(@Valid FeedingRecordPageReqVO pageReqVO) {
        PageResult<FeedingRecordRespVO> pageResult = feedingRecordService.getFeedingRecordPage(pageReqVO);
//        List<OrganizationDO> organizationList = organizationService.getOrganizationListByOutIds(convertSet(pageResult.getList(), FeedingRecordRespVO::getFeedingPipeline));
//        Map<Long, List<OrganizationDO>> organizationMap = convertMultiMap(organizationList, OrganizationDO::getId);
        Map<Long, OrganizationDO> organizationMap = organizationService.getOrganizationVOMap(
                convertSet(pageResult.getList(), FeedingRecordRespVO::getFeedingPipeline));
        return success(BeanUtils.toBean(pageResult, FeedingRecordRespVO.class, feedingRecord -> {
            MapUtils.findAndThen(organizationMap, feedingRecord.getFeedingPipeline(), feedingPipeline -> feedingRecord.setFeedingPipelineName(feedingPipeline.getName()));
        }));
    }

    @GetMapping("/export-excel")
    @Operation(summary = "导出投料记录 Excel")
    @PreAuthorize("@ss.hasPermission('mes:feeding-record:export')")
    @ApiAccessLog(operateType = EXPORT)
    public void exportFeedingRecordExcel(@Valid FeedingRecordPageReqVO pageReqVO,
                                         HttpServletResponse response) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        List<FeedingRecordRespVO> list = feedingRecordService.getFeedingRecordPage(pageReqVO).getList();
        // 导出 Excel
        ExcelUtils.write(response, "投料记录.xls", "数据", FeedingRecordRespVO.class,
                list);
    }
    @GetMapping("/getRecordList")
    @Operation(summary = "投料记录 ")
    @PreAuthorize("@ss.hasPermission('mes:feeding-record:query')")
    public CommonResult<List<FeedingRecordRespVO>> getRecordList(@Valid FeedingRecordPageReqVO pageReqVO) throws IOException {
        pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
        if(pageReqVO.getFeedingTime()==null || pageReqVO.getFeedingTime().length==0){
            LocalDateTime[] dateTimes={LocalDateTime.now().plusDays(-3),LocalDateTime.now()};
            pageReqVO.setFeedingTime(dateTimes);
        }
        List<FeedingRecordRespVO> list = feedingRecordService.getFeedingRecordPage(pageReqVO).getList();
        return success(list);
    }
    // ==================== 子表（投料记录明细） ====================

    @GetMapping("/feeding-record-detail/list-by-record-id")
    @Operation(summary = "获得投料记录明细列表")
    @Parameter(name = "recordId", description = "记录id")
    @PreAuthorize("@ss.hasPermission('mes:feeding-record:query')")
    public CommonResult<List<FeedingRecordDetailRespVO>> getFeedingRecordDetailListByRecordId(@RequestParam("recordId") Long recordId) {
        List<FeedingRecordDetailDO> detailDOList = feedingRecordService.getFeedingRecordDetailListByRecordId(recordId);
        return success(feedingRecordService.buildVOList(detailDOList));
    }

    @Resource
    private FeedingRecordMapper feedingRecordMapper;
    @Resource
    private ItemRequisitionService itemRequisitionService;
    @Resource
    private PlanService planService;
    @Resource
    private ItemRequisitionMapper itemRequisitionMapper;

    @PutMapping("/update-status")
    @Operation(summary = "提交状态")
    public CommonResult<Boolean> updateStatus(@RequestParam("id") Long id,
                                              @RequestParam("status") String status) {
        LoginUser user = SecurityFrameworkUtils.getLoginUser();
        if (user != null) {
            FeedingRecordDO recordDO = feedingRecordMapper.selectById(id);
            if (recordDO == null) throw exception(FEEDING_RECORD_NOT_EXISTS);
            //后续步骤只处理领料投料的投料单，湿废品和干废品投料暂不处理
            //计划及计划物料需求
            List<Integer> statusList = new ArrayList<>();
            statusList.add(PlanStatusEnum.量产.getValue());
            //获取正在开工的计划，按照计划完工时间从小到大排序，优先分配给最近计划完工的计划。
            List<PlanDO> planDOList = planService.getPlanByStatusAndPipeline(statusList, String.valueOf(recordDO.getFeedingPipeline()));/** todo 这里改了 以前固定2 5立方制浆线*/


            if (recordDO.getFeedingType().equals(FeedingTypeEnum.领料.getValue())) {
                List<FeedingRecordDetailDO> detailDOList = feedingRecordService.getFeedingRecordDetailListByRecordId(id);
                Map<Long, List<ItemRequisitionDetailRespVO>> planItemListMap = new HashMap<>();
                Map<String, ItemRequisitionDetailRespVO> planItemMap = new HashMap<>();

                for (int i = 0; i < planDOList.size(); i++) {
                    //获取计划的物料需求
                    List<ItemRequisitionDetailRespVO> list = itemRequisitionService.getItemRequisitionList(planDOList.get(i).getId());
                    planItemListMap.put(planDOList.get(i).getId(), list);

                    for (ItemRequisitionDetailRespVO respVO : list) {
                        String key = getMapKey(planDOList.get(i).getId(), respVO.getProductId());
                        planItemMap.put(key, respVO);
                    }
                }
                //当只有一个计划在开工时，投料直接分配给该计划
                if(planDOList.size()==1){
                    feedingRecordService.dealWithOnPlan( planDOList.get(0),  detailDOList, planItemMap,  user,recordDO);
                }
                else{
                    Map<String, FeedingRecordPlanDO> recordPlanDOMap = feedingRecordService.updateStatus(recordDO, detailDOList, status, user.getId(), planDOList,
                            planItemListMap, planItemMap);
                    //更新计划对应的领料单投料时间
                    Map<Long, Long> map = new HashMap<>();
                    for (String key : recordPlanDOMap.keySet()) {
                        FeedingRecordPlanDO item = recordPlanDOMap.get(key);
                        if (!map.containsKey(item.getPlanId())) {
                            ItemRequisitionDO itemRequisitionDO = itemRequisitionService.getItemRequisitionByPlanId(item.getPlanId());
                            if (itemRequisitionDO != null && itemRequisitionDO.getDeliveryDate() == null &&!map.containsKey(item.getPlanId())) {
                                itemRequisitionDO.setDeliveryDate(LocalDate.now());
                                itemRequisitionMapper.updateById(itemRequisitionDO);
                                map.put(item.getPlanId(), item.getPlanId());
                            }
                        }
                    }
                }
            } else {

            }
//            if (recordDO.getWeight().compareTo(recordDO.getFeedingWeight()) == 0) {
//                recordDO.setRecordStatus(FeedingStatusEnum.已完成.getValue());
//            } else {
//                recordDO.setRecordStatus(FeedingStatusEnum.投料中.getValue());
//
//                list.forEach(o -> o.setId(null).setRecordId(recordDO.getId())
//                        .setUserId(recordDO.getUserId())
//                        .setFeedingTime(recordDO.getFeedingTime())
//                );
//                feedingRecordDetailMapper.insertBatch(list);
//            }
            feedingRecordMapper.updateById(recordDO);
            return success(true);
        } else return CommonResult.error(500, "无法获取操作用户！请检查！");
    }


    private String getMapKey(Long planId, Long itemId) {
        return planId + "-" + itemId;
    }
}