/*
 *  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.rest;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.youchain.annotation.AnonymousAccess;
import com.youchain.annotation.Log;
import com.youchain.basicdata.domain.*;
import com.youchain.basicdata.repository.StockRepository;
import com.youchain.basicdata.service.ItemService;
import com.youchain.basicdata.service.StockService;
import com.youchain.basicdata.service.PointService;
import com.youchain.basicdata.service.mapstruct.ItemMapper;
import com.youchain.basicdata.service.mapstruct.PointMapper;
import com.youchain.businessdata.ReturnJson.RRkMo;
import com.youchain.businessdata.inputJson.IRkConfirm;
import com.youchain.businessdata.inputJson.IRkInv;
import com.youchain.businessdata.inputJson.IRkStockCode;
import com.youchain.businessdata.inputJson.IScanPut;
import com.youchain.businessdata.domain.*;
import com.youchain.businessdata.service.*;
import com.youchain.businessdata.service.dto.AsnDetailDto;
import com.youchain.businessdata.service.dto.AsnDetailQueryCriteria;
import com.youchain.config.FileProperties;
import com.youchain.exception.handler.ApiError;
import com.youchain.exception.handler.ApiResult;
import com.youchain.modules.quartz.utils.TimeNumberUtils;
import com.youchain.modules.system.domain.Dept;
import com.youchain.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.*;

import java.beans.Transient;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import static org.springframework.http.HttpStatus.BAD_REQUEST;

/**
 * @author hjl
 * @website https://eladmin.vip
 * @date 2023-08-14
 **/
@RestController
@RequiredArgsConstructor
@Api(tags = "asn_detail管理")
@Slf4j
@RequestMapping("/api/asnDetail")
public class AsnDetailController {

    private final AsnDetailService asnDetailService;

    private final ItemService itemService;

    private final TaskService taskService;

    private final StockService stockService;
    private final StockRepository stockRepository;

    private final ItemKeyService itemKeyService;

    private final InventoryService invService;

    private final InventoryLogService invLogService;

    private final PointService pointService;

    private final FileProperties properties;

    @Log("导出数据")
    @ApiOperation("导出数据")
    @GetMapping(value = "/download")
    @PreAuthorize("@el.check('asnDetail:list')")
    public void exportAsnDetail(HttpServletResponse response, AsnDetailQueryCriteria criteria) throws IOException {
        asnDetailService.download(asnDetailService.queryAll(criteria), response);
    }

    @GetMapping
    @ApiOperation("查询asn_detail")
    public ResponseEntity<Object> queryAsnDetail(AsnDetailQueryCriteria criteria, Pageable pageable) {
        return new ResponseEntity<>(asnDetailService.queryAll(criteria, pageable), HttpStatus.OK);
    }

    @PostMapping
    @Log("新增asn_detail")
    @ApiOperation("新增asn_detail")
    @PreAuthorize("@el.check('asnDetail:add')")
    @Transient
    public ResponseEntity<Object> createAsnDetail(@Validated @RequestBody AsnDetail asnDetail) {
        asnDetail.setStatus(BizStatus.OPEN);
        asnDetail.setDept(UserUtils.getDept());
        asnDetail.setPo(TimeNumberUtils.getRKCode());
        asnDetailService.create(asnDetail);
        Stock stock = asnDetail.getStock();
        stock.setStatus(BaseStatus.USED);
        stockService.update(stock);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @Log("采集MO票")
    @ApiOperation("新增createMoInfo")
    @PostMapping(value = "/createMoInfo")
    @PreAuthorize("@el.check('asnDetail:createMoInfo')")
    @Transient
    public ResponseEntity<Object> storeMO(@Validated @RequestBody AsnDetail asnDetail) {
        return addDetailMo(asnDetail, asnDetail.getPo(), asnDetail.getStock().getCode());
    }


    @PutMapping
    @Log("修改asn_detail")
    @ApiOperation("修改asn_detail")
    @PreAuthorize("@el.check('asnDetail:edit')")
    public ResponseEntity<Object> updateAsnDetail(@Validated @RequestBody AsnDetail resources) {
        asnDetailService.update(resources);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    @PutMapping("/updateContainer")
    @Log("修改容器")
    @ApiOperation("修改容器")
    @PreAuthorize("@el.check('asnDetail:edit')")
    public ResponseEntity<Object> updateContainer(@Validated @RequestBody AsnDetail resources, @RequestParam("stockId") Long stockId) {
        Stock stockData = stockRepository.getById(stockId);
        Stock stock = resources.getStock();
        stockData.setStatus("FREE");
        stock.setStatus("USED");
        resources.setStock(stock);
        asnDetailService.update(resources);
        stockService.update(stockData);
        stockService.update(stock);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    @DeleteMapping
    @Log("删除asn_detail")
    @ApiOperation("删除asn_detail")
    @PreAuthorize("@el.check('asnDetail:del')")
    public ResponseEntity<Object> deleteAsnDetail(@RequestBody Long[] ids) {
        asnDetailService.deleteAll(ids);
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @Log("收货")
    @ApiOperation("收货数据")
    @PutMapping(value = "/checkAsn")
    @PreAuthorize("@el.check('asnDetail:checkAsn')")
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity<Object> checkAsn(@RequestBody Long[] ids) {
        for (Long id : ids) {
            AsnDetail d = asnDetailService.toEntity(asnDetailService.findById(id));
            String areaCode = null;
            String goodType = d.getItem().getGoodType();
            if (goodType != null && goodType.equals(BizStatus.ZC)) {
                areaCode = "ZCMCK";
            }
            List<Point> points = pointService.getPoint(BaseStatus.STORAGE, areaCode);
            Point dstPoint = null;
            if (points.size() > 0) {
                dstPoint = points.get(0);
            } else {
                ApiError apiError = ApiError.errorJosn(BAD_REQUEST.value(), "找不到空闲点位");
                return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));
            }

            ApiResult r1 = putawayInv(d, d.getPoint(), dstPoint);
            if (r1.getStatus() == 400) {
                ApiError apiError = ApiError.errorJosn(BAD_REQUEST.value(), r1.getMessage());
                return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));
            }

        }
        return new ResponseEntity<>(HttpStatus.OK);
    }

    public ApiResult putawayInv(@RequestBody AsnDetail d, Point srcPoint, Point dstPoint) {
        if (d.getOrderQty() - d.getReceivedQty() > 0) {
            ItemKey ik = itemKeyService.getItemKey(d.getItem(), d.getPropC1(), d.getPropC3());
            Task t = new Task();
            t.setAsnDetail(d);
            t.setSrcStock(d.getStock());
            t.setSrcStockCode(d.getStock().getCode());
            t.setDstStock(d.getStock());
            t.setDstStockCode(d.getStock().getCode());
            t.setTaskStatus(BizStatus.OPEN);
            t.setItem(d.getItem());
            t.setPlanQty(d.getOrderQty());
            t.setItemKey(ik);
            if (srcPoint != null) {
                t.setSrcPoint(srcPoint);
                t.setSrcPointCode(srcPoint.getCode());
            }
            t.setDstPoint(dstPoint);
            t.setDstPointCode(dstPoint.getCode());
            taskService.create(t);
            d.setReceivedQty(d.getOrderQty());
            d.setStatus(BizStatus.RECEIVED);
            asnDetailService.update(d);
            dstPoint.setStatus(BaseStatus.USED);
            pointService.update(dstPoint);
            double srcQty = 0d;
            Inventory inv = invService.getInventory(ik, dstPoint, d.getStock(), d.getDept(), BizStatus.RECEIVING_UP);
            t.setInvId(inv.getId());
            taskService.update(t);
            srcQty = inv.getQuantity();
            inv.addQty(inv, d.getOrderQty());
            invService.update(inv);
            invLogService.storeInventoryLog(BizStatus.RECEIVING_UP, BizStatus.ADD, null, ik, srcPoint, dstPoint, d.getStock(), d.getStock(), srcQty, d.getOrderQty(),
                    BizStatus.ASN, d.getId(), inv.getId(), d.getRemark());
        } else {
            return ApiResult.result(400, d.getItem().getCode() + "已收货", "obj");
        }

        return ApiResult.result(200, null, "obj");
    }

    @PostMapping(value = "/import_mo")
    @ApiOperation("导入MO")
    @javax.transaction.Transactional
    @PreAuthorize("@el.check('asnDetail:list')")
    public ResponseEntity<Object> importMo(@RequestParam("file") MultipartFile multipartFile) {
        FileUtil.checkSize(properties.getMaxSize(), multipartFile.getSize());
        String suffix = FileUtil.getExtensionName(multipartFile.getOriginalFilename());
        String type = FileUtil.getFileType(suffix);
        log.error("--" + properties.getPath().getPath() + type + File.separator);
        File file = FileUtil.upload(multipartFile, properties.getPath().getPath() + type + File.separator);
        //MO票、容器代码
        ExcelReader reader = ExcelUtil.getReader(file);
        Dept dept = UserUtils.getDept();
        int i = 0;
        int new_len = 0;
        try {
            List<Map<String, Object>> readAll = reader.readAll();
            for (i = 0; i < readAll.size(); i++) {
                log.error(i + "=====");
                String mo = readAll.get(i).get("MO票").toString().trim();
                String stockCode = readAll.get(i).get("容器代码").toString().trim();
                String[] str = mo.split("]");
                int j = 0;
                IScanPut s = new IScanPut();
                s.setScanCode(mo);
                ApiResult r1 = analysisMO(s);
                if (r1.getStatus() == 400) {
                    ApiError apiError = ApiError.errorJosn(BAD_REQUEST.value(), r1.getMessage());
                    return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));
                }
                RRkMo rmo = (RRkMo) r1.getData();
                ApiResult r2 = retrievalStockCode(new IRkStockCode(rmo.getItemId(), stockCode));
                if (r2.getStatus() == 400) {
                    ApiError apiError = ApiError.errorJosn(BAD_REQUEST.value(), r2.getMessage());
                    return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));
                }
                JSONObject obj = (JSONObject) r2.getData();
                Long stockId = (Long) obj.get("stockId");
                ApiResult r3 = createAsnDetail(new IRkConfirm(mo, rmo.getItemId(), rmo.getItemCode(), stockId, stockCode, rmo.getQty(), rmo.getPch(), rmo.getCjbh()));
                if (r3.getStatus() == 400) {
                    ApiError apiError = ApiError.errorJosn(BAD_REQUEST.value(), r3.getMessage());
                    return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));
                }
                new_len++;
            }
        } catch (Exception e) {
            ApiError apiError = ApiError.errorJosn(HttpStatus.BAD_REQUEST.value(), "导入异常---第" + (i + 1) + "行：" + e.toString());
            return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));
        }
        ApiError apiError = ApiError.errorJosn(HttpStatus.OK.value(), "导入成功：" + (i) + "行 新增（" + new_len + ")");
        return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));

    }

    @Log("保存MO票，生成入库采集数据")
    @ApiOperation("新增addDetailMo")
    @PostMapping(value = "/addDetailMo")
    @PreAuthorize("@el.check('asnDetail:addDetailMo')")
    @Transient
    @AnonymousAccess
    public ResponseEntity<Object> addDetailMo(AsnDetail asnDetail, String MO, String stockCode) {
        log.error("join.....addDetailMo:" + MO + "=====:" + stockCode);
        //MO票解析规则 LB]A0008157]230729]12122000026352]20]230729283171]]
        int j = 0;
        IScanPut s = new IScanPut();
        s.setScanCode(MO);
        ApiResult r1 = analysisMO(s);
        if (r1.getStatus() == 400) {
            ApiError apiError = ApiError.errorJosn(BAD_REQUEST.value(), r1.getMessage());
            return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));
        }
        RRkMo rmo = (RRkMo) r1.getData();
        ApiResult r2 = retrievalStockCode(new IRkStockCode(rmo.getItemId(), stockCode));
        if (r2.getStatus() == 400) {
            ApiError apiError = ApiError.errorJosn(BAD_REQUEST.value(), r2.getMessage());
            return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));
        }
        JSONObject obj = (JSONObject) r2.getData();
        Long stockId = (Long) obj.get("stockId");
        ApiResult r3 = createAsnDetail(new IRkConfirm(MO, rmo.getItemId(), rmo.getItemCode(), stockId, stockCode, rmo.getQty(), rmo.getPch(), rmo.getCjbh()));
        if (r3.getStatus() == 400) {
            ApiError apiError = ApiError.errorJosn(BAD_REQUEST.value(), r3.getMessage());
            return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));
        }
        return new ResponseEntity<>(HttpStatus.OK);
    }

    @PostMapping("/scanMO")
    @Log("扫描MO")
    @ApiOperation("扫描MO票接口")
    @PreAuthorize("@el.check('asnDetail:scanMO')")
    @AnonymousAccess
    public ResponseEntity<Object> scanMO(@RequestBody IScanPut s) {
        ApiResult r = analysisMO(s);
        return HttpUtils.handle(r);
    }

    public ApiResult analysisMO(IScanPut s) {
        //MO票解析规则 LB]A0008157]230729]12122000026352]20]230729283171]]
        String mo = s.getScanCode();
        String[] str = mo.split("]");
        RRkMo rm = new RRkMo();
        int j = 0;
        if (str.length <= 5) {
            rm.setMsg(mo + "格式不正确");
            String msg = mo + "格式不正确";
            return ApiResult.result(400, msg, rm);
        }
        String itemCode = str[3];
        Double qty = Double.parseDouble(str[4]);
        String pch = str[2];
        String cjbh = str[1];

        rm.setCjbh(cjbh);
        rm.setQty(qty);
        rm.setPch(pch);
        rm.setItemCode(itemCode);
        Item it = itemService.existItem(itemCode);
        if (it == null) {
            rm.setMsg(itemCode + "不存在");
            String msg = itemCode + "不存在";
            return ApiResult.result(400, msg, rm);
        }
        rm.setItemId(it.getId());
        rm.setItemName(it.getName());
        return ApiResult.result(200, null, rm);
    }


    @PostMapping("/scanStockCode")
    @Log("MO票采集，扫描容器号")
    @ApiOperation("MO票采集，扫描容器号")
    @PreAuthorize("@el.check('asnDetail:scanStockCode')")
    @AnonymousAccess
    public ResponseEntity<Object> scanStockCode(@RequestBody IRkStockCode s) {
        ApiResult r = retrievalStockCode(s);
        return HttpUtils.handle(r);
    }

    public ApiResult retrievalStockCode(IRkStockCode s) {
        JSONObject obj = new JSONObject();
        Long itemId = s.getItemId();
        String stockCode = s.getStockCode();
        Stock st = stockService.findByCode(stockCode, BaseStatus.FREE);
        if (st == null) {
            return ApiResult.result(400, stockCode + "不存在或已使用", obj);
        }

        Map<String, Object> map = new HashMap<>();
        map.put("stockId", st.getId());
        obj.putAll(map);
        return ApiResult.result(200, null, obj);
    }

    @PostMapping("/putawayStock")
    @Log("APP入库上架")
    @ApiOperation("APP入库上架-容器号")
    @PreAuthorize("@el.check('asnDetail:putawayStock')")
    @AnonymousAccess
    public ResponseEntity<Object> putawayStock(@RequestBody IRkInv rk) {
        String stockCode = rk.getStockCode();
        AsnDetail ad = asnDetailService.findByStock(stockCode);
        if (ad == null) {
            ApiError apiError = ApiError.errorJosn(HttpStatus.BAD_REQUEST.value(), stockCode + "找不到收货记录");
            return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));
        } else {
            rk.setAsnDetailId(ad.getId());
            return new ResponseEntity<>(rk, HttpStatus.OK);
        }
    }

    @PostMapping("/putawaySrcPoint")
    @Log("APP入库上架")
    @ApiOperation("APP入库上架-起点")
    @PreAuthorize("@el.check('asnDetail:putawaySrcPoint')")
    @AnonymousAccess
    public ResponseEntity<Object> putawaySrcPoint(@RequestBody IRkInv rk) {
        String srcPointCode = rk.getSrcPointCode();
        Point srcPoint = pointService.findByCode(srcPointCode, null, null, null, null,null);
        if (srcPoint == null) {
            ApiError apiError = ApiError.errorJosn(HttpStatus.BAD_REQUEST.value(), srcPointCode + "找不到起点");
            return new ResponseEntity(apiError, HttpStatus.valueOf(apiError.getStatus()));
        } else {
            rk.setSrcPointId(srcPoint.getId());
            return new ResponseEntity<>(rk, HttpStatus.OK);
        }
    }

    @PostMapping("/putawayConfirmApp")
    @Log("APP入库上架")
    @ApiOperation("APP入库上架")
    @PreAuthorize("@el.check('asnDetail:putawayConfirmApp')")
    @AnonymousAccess
    public ResponseEntity<Object> putawayConfirmApp(@RequestBody IRkInv rk) {
        ApiResult r = putawayConfirm(rk);
        return HttpUtils.handle(r);
    }


    public ApiResult putawayConfirm(IRkInv rk) {
        JSONObject obj = new JSONObject();
        //查找容器是否有未完成记录
//        String stockCode=rk.getStockCode();
//        AsnDetail ad=asnDetailService.findByStock(stockCode);
//        if(ad==null){
//            return ApiResult.result(400,stockCode+"找不到收货记录",obj);
//        }
//
//        String srcPointCode=rk.getSrcPointCode();
        String dstPointCode = rk.getDstPoinCode();
        AsnDetail ad = asnDetailService.toEntity(asnDetailService.findById(rk.getAsnDetailId()));
        Point srcPoint = pointService.findEntityById(rk.getSrcPointId());
//        Point srcPoint=pointService.findByCode(srcPointCode,null,null);
//        if (srcPoint == null) {
//            return ApiResult.result(400,srcPointCode+"找不到起点",obj);
//        }
        Point dstPoint = pointService.findByCode(dstPointCode, BaseStatus.FREE, BaseStatus.STORAGE, "", null,null);
        if (dstPoint == null) {
            return ApiResult.result(400, dstPoint + "找不到终点或状态不对", obj);
        }
        ApiResult r1 = putawayInv(ad, srcPoint, dstPoint);
        if (r1.getStatus() == 400) {
            return r1;
        }

        Map<String, Object> map = new HashMap<>();
        obj.putAll(map);
        return ApiResult.result(200, null, obj);
    }


    @PostMapping("/storeAsnDetail")
    @Log("MO票确认绑定")
    @ApiOperation("MO票确认绑定")
    @PreAuthorize("@el.check('asnDetail:storeAsnDetail')")
    @AnonymousAccess
    public ResponseEntity<Object> storeAsnDetail(@RequestBody IRkConfirm cf) {
        ApiResult r = createAsnDetail(cf);
        return HttpUtils.handle(r);
    }

    public ApiResult createAsnDetail(IRkConfirm cf) {
        AsnDetail asnDetail = new AsnDetail();
        int j = 0;
        String mo = cf.getMo();
        String itemCode = cf.getItemCode();
        Double qty = cf.getQty();
        String pc = cf.getPch();
        String cjbh = cf.getCjbh();
        Long itemId = cf.getItemId();
        Long stockId = cf.getStockId();
        Item it = itemService.findByItemId(itemId);
        Stock st = stockService.toEntity(stockService.findById(stockId));

        asnDetail.setPropC1(pc);
        asnDetail.setPropC2(cjbh);
        asnDetail.setOrderQty(qty);
        asnDetail.setDept(UserUtils.getDept());
        asnDetail.setItem(it);
        asnDetail.setStock(st);
        asnDetail.setStatus(BizStatus.OPEN);
        asnDetail.setPo(mo);
        asnDetail.setDept(UserUtils.getDept());
        asnDetailService.create(asnDetail);
        st.setStatus(BaseStatus.USED);
        stockService.update(st);
        return ApiResult.result(200, "绑定成功", "");
    }

    @PostMapping("/scanStock")
    @Log("输送线扫码接口")
    @ApiOperation("输送线扫码接口")
    @AnonymousAccess
    public synchronized ResponseEntity<Object> boxTask(@RequestBody String json) {
        JSONObject jsonObject = JSON.parseObject(json);
        String stockCode = jsonObject.getString("stockCode");
        String taskCode = jsonObject.getString("taskCode");
        String returnDate = jsonObject.getString("returnDate");

        //调用收货方法

        JSONObject obj = new JSONObject();
        Map<String, Object> map = new HashMap<>();
        map.put("taskCode", taskCode);
        obj.putAll(map);
        return new ResponseEntity<>(ApiResult.success("", obj), HttpStatus.OK);

    }
}
