package org.wcs.serve.service.impl;

import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.wcs.constant.ConstantData;
import org.wcs.constant.enums.database.StackerLocationStatusEnum;
import org.wcs.factory.AppServeResponseFactory;
import org.wcs.mapper.intf.AppStackerLocationService;
import org.wcs.model.bo.tuple.Tuple2;
import org.wcs.model.dto.serve.stackerLocation.AddManyStackerLocationsReq;
import org.wcs.model.dto.serve.stackerLocation.AddStackerLocationReq;
import org.wcs.model.dto.serve.stackerLocation.QueryStackerLocationReq;
import org.wcs.model.dto.serve.stackerLocation.UpdateStackerLocationReq;
import org.wcs.model.po.app.AppStackerLocation;
import org.wcs.model.vo.serve.AppServeDataResponse;
import org.wcs.model.vo.serve.AppServeResponse;
import org.wcs.model.vo.serve.common.PageDataResponse;
import org.wcs.model.vo.serve.stackerLocation.ExportAppStackerLocationVo;
import org.wcs.model.vo.serve.stackerLocation.QueryStackerLocationVo;
import org.wcs.plugin.excel.ExcelPoi;
import org.wcs.serve.service.intf.IStackerLocationService;
import org.wcs.utils.AppBeanUtils;
import org.wcs.utils.AppDataBaseTransUtils;
import org.wcs.utils.AppStringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class StackerLocationService implements IStackerLocationService {


    private final AppStackerLocationService appStackerLocationService;
    private final AppDataBaseTransUtils appDataBaseTransUtils;
    private final ExcelPoi excelPoi;

    /**
     * 分页查询库位信息
     * @param request 查询参数
     * @param pageSize 分页大小
     * @param pageIndex 页面序号
     * @return 查询结果
     */
    @Override
    public AppServeDataResponse<PageDataResponse<QueryStackerLocationVo>> queryStackerLocation(QueryStackerLocationReq request, Integer pageSize, Integer pageIndex) {
        if(pageSize == null || pageSize <= 0 || pageIndex == null || pageIndex <= 0) {
            return AppServeResponseFactory.fail("分页参数错误", null);
        }
        Tuple2<Long, List<AppStackerLocation>> pageResult = appStackerLocationService.queryStackerLocation(request, pageSize, pageIndex);
        if(pageResult == null) {
            return AppServeResponseFactory.internalServerError("数据服务异常", null);
        }
        List<QueryStackerLocationVo> queryStackerLocationVos = AppBeanUtils.copyListProperties(pageResult.item2, QueryStackerLocationVo::new);
        PageDataResponse<QueryStackerLocationVo> pageDataResponse = new PageDataResponse<>();
        pageDataResponse.setPageIndex(pageIndex);
        pageDataResponse.setPageSize(pageSize);
        pageDataResponse.setTotalCount(pageResult.item1);
        pageDataResponse.setData(queryStackerLocationVos);
        return AppServeResponseFactory.success("查询成功", pageDataResponse);
    }

    /**
     * 新增库位信息
     * @param request 新增参数
     * @return 新增结果
     */
    @Override
    public AppServeResponse addStackerLocation(AddStackerLocationReq request) {
        List<AppStackerLocation> appStackerLocations = appStackerLocationService.queryStackerLocationById(request.getLocationId());
        if(appStackerLocations == null) {
            return AppServeResponseFactory.internalServerError("数据服务异常", null);
        }
        if(!appStackerLocations.isEmpty()) {
            return AppServeResponseFactory.fail("库位已存在", null);
        }
        AppStackerLocation appStackerLocation = new AppStackerLocation();
        AppBeanUtils.copyProperties(request, appStackerLocation);
        appStackerLocation.setLocationStatus(StackerLocationStatusEnum.EMPTY.getCode());
        int insertCount = appStackerLocationService.insert(appStackerLocation);
        if(insertCount == 0) {
            return AppServeResponseFactory.internalServerError("数据服务异常", null);
        }
        return AppServeResponseFactory.success(String.format("添加成功，添加了 %d 条记录", insertCount));
    }

    /**
     * 新增多个库位信息
     * @param request 新增参数
     * @return 新增结果
     */
    @Override
    public AppServeResponse addStackerLocations(AddManyStackerLocationsReq request) {
        /* 先拿出忽略的列形成 list */
        List<Integer> lineSkips = new ArrayList<>();
        if(AppStringUtils.isNotEmpty(request.getLLineSkip())) {
            String[] splitLines = request.getLLineSkip().split(";");
            for (String splitLine : splitLines) {
                if(AppStringUtils.isNotEmpty(splitLine) && !AppStringUtils.isNumber(splitLine)) {
                    return AppServeResponseFactory.fail("列偏移格式错误");
                }
                lineSkips.add(Integer.parseInt(splitLine));
            }
        }
        /* 拿出忽略的层形成 list */
        List<Integer> layerSkips = new ArrayList<>();
        if(AppStringUtils.isNotEmpty(request.getLLayerSkip())) {
            String[] splitLayers = request.getLLayerSkip().split(";");
            for (String splitLayer : splitLayers) {
                if(AppStringUtils.isNotEmpty(splitLayer) && !AppStringUtils.isNumber(splitLayer)) {
                    return AppServeResponseFactory.fail("层偏移格式错误");
                }
                layerSkips.add(Integer.parseInt(splitLayer));
            }
        }
        List<AppStackerLocation> appStackerLocations = new ArrayList<>();
        for(int line = 1 + request.getLLineOffset(); line <= request.getLLineTotal() + request.getLLineOffset(); line++) {
            if(lineSkips.contains(line - request.getLLineOffset())) {
                continue;
            }
            for(int layer = 1; layer <= request.getLLayerTotal(); layer++) {
                if(layerSkips.contains(layer)) {
                    continue;
                }
                for(int depth = 1; depth <= request.getLDepthTotal(); depth++) {
                    AppStackerLocation appStackerLocation = new AppStackerLocation();
                    String locationString = request.getStartString() +
                            request.getLRow() +
                            "-" +
                            String.format("%03d", line - request.getLLineOffset()) +
                            "-" +
                            String.format("%02d", layer) +
                            "-" +
                            String.format("%1d", depth) +
                            request.getEndString();

                    appStackerLocation.setLocationId(locationString);
                    appStackerLocation.setLocationStatus(StackerLocationStatusEnum.EMPTY.getCode());
                    appStackerLocation.setBusinessLocation(locationString);
                    appStackerLocation.setLocationType(request.getLocationType());
                    appStackerLocation.setLaneId(request.getLaneId());
                    appStackerLocation.setMachineId(request.getMachineId());
                    appStackerLocation.setLRow(request.getLRow());
                    appStackerLocation.setLLine(line);
                    appStackerLocation.setLLayer(layer);
                    appStackerLocation.setLDepth(depth);
                    appStackerLocation.setLocationTag(request.getLocationTag());
                    appStackerLocation.setRemark(request.getRemark());
                    appStackerLocations.add(appStackerLocation);
                }
            }
        }
        if(appStackerLocations.isEmpty()) {
            return AppServeResponseFactory.fail("没有生成任何货位，请检查数据");
        }
        boolean tran = appDataBaseTransUtils.useTran(() -> {
            appStackerLocationService.deleteWithMachineIdAndLaneIdNoCatchException(request.getMachineId(), request.getLaneId(),request.getLRow());
            appStackerLocationService.insertNoCatchException(appStackerLocations);
        });
        if(tran) {
            return AppServeResponseFactory.success("生成成功");
        }
        return AppServeResponseFactory.fail("生成失败，事务执行失败");
    }

    /**
     * 下载堆垛机货位信息
     * @param response 响应
     * @param request 请求参数
     */
    @Override
    public void downloadStackerLocation(HttpServletResponse response, QueryStackerLocationReq request) {
        List<AppStackerLocation> stackerLocations = appStackerLocationService.queryStackerLocation(request);
        if(stackerLocations == null) {
            log.error("堆垛机货位信息下载失败，查询存在异常");
            return;
        }
        List<ExportAppStackerLocationVo> exportAppStackerLocationVos = new ArrayList<>();
        for (AppStackerLocation stackerLocation : stackerLocations) {
            ExportAppStackerLocationVo exportAppStackerLocationVo = new ExportAppStackerLocationVo();
            BeanUtils.copyProperties(stackerLocation, exportAppStackerLocationVo);
            exportAppStackerLocationVo.setLocationStatus(StackerLocationStatusEnum.getMessageByCode(stackerLocation.getLocationStatus()).getMessage());
            exportAppStackerLocationVos.add(exportAppStackerLocationVo);
        }
        try{
            excelPoi.doWriteExcel("堆垛机货位", response, exportAppStackerLocationVos, ExportAppStackerLocationVo.class);
        } catch (Exception e) {
            log.error("导出堆垛机位置失败", e);
        }
    }

    /**
     * 更新堆垛机货位信息
     * @param request 请求参数
     * @return 响应
     */
    @Override
    public AppServeResponse updateStackerLocation(UpdateStackerLocationReq request) {
        request.setVehicleNo(AppStringUtils.isEmptyOr(request.getVehicleNo(), ""));
        request.setLocationTag(AppStringUtils.isEmptyOr(request.getLocationTag(), ""));
        request.setRemark(AppStringUtils.isEmptyOr(request.getRemark(), ""));
        List<AppStackerLocation> appStackerLocations = appStackerLocationService.queryStackerLocationById(request.getLocationId());
        if(appStackerLocations == null) {
            return AppServeResponseFactory.internalServerError("数据服务异常", null);
        }
        if(appStackerLocations.isEmpty()) {
            return AppServeResponseFactory.fail("库位不存在，请刷新后再试", null);
        }
        AppStackerLocation appStackerLocation = new AppStackerLocation();
        BeanUtils.copyProperties(request, appStackerLocation);
        boolean update = appStackerLocationService.updateById(appStackerLocation);
        if(update) {
            return AppServeResponseFactory.success("更新成功");
        }
        return AppServeResponseFactory.fail("更新失败");
    }

    /**
     * 根据巷道号查询堆垛机货位信息
     * @param stackerId 设备号
     * @param laneId 巷道号
     * @return 响应
     */
    @Override
    public AppServeDataResponse<List<QueryStackerLocationVo>> queryStackerLocationListByStackerIdAndLaneId(Integer stackerId, Integer laneId) {
        if(laneId == null || laneId <= 0) {
            return AppServeResponseFactory.fail("参数错误", null);
        }
        List<AppStackerLocation> appStackerLocations = appStackerLocationService.queryStackerLocationByStackerIdAndLaneId(stackerId, laneId);
        if(appStackerLocations == null) {
            return AppServeResponseFactory.internalServerError("数据服务异常", null);
        }
        List<QueryStackerLocationVo> queryStackerLocationVos = AppBeanUtils.copyListProperties(appStackerLocations, QueryStackerLocationVo::new);
        return AppServeResponseFactory.success("查询成功", queryStackerLocationVos);
    }

    /**
     * 查询堆垛机货位巷道列表
     * @return 响应
     */
    @Override
    public AppServeDataResponse<List<Integer>> queryStackerLocationLaneList(Integer stackerId) {
        List<AppStackerLocation> stackerLocations = appStackerLocationService.queryStackerLocationAll();
        if(stackerLocations == null) {
            return AppServeResponseFactory.internalServerError("数据服务异常", null);
        }
        List<Integer> laneIds = stackerLocations.stream().filter(appStackerLocation -> appStackerLocation.getMachineId().equals(stackerId)).map(AppStackerLocation::getLaneId).distinct().toList();
        return AppServeResponseFactory.success("查询成功", laneIds);
    }

    /**
     * 查询堆垛机货位堆垛机列表
     * @return 响应
     */
    @Override
    public AppServeDataResponse<List<Integer>> queryStackerLocationStackerIdList() {
        List<AppStackerLocation> stackerLocations = appStackerLocationService.queryStackerLocationAll();
        if(stackerLocations == null) {
            return AppServeResponseFactory.internalServerError("数据服务异常", null);
        }
        List<Integer> machineIds = stackerLocations.stream().map(AppStackerLocation::getMachineId).distinct().toList();
        return AppServeResponseFactory.success("查询成功", machineIds);
    }
}
