package net.lab1024.sa.admin.module.business.wms.base.location.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.constant.UsageStatusEnum;
import net.lab1024.sa.admin.module.business.wms.base.area.domain.entity.AreaEntity;
import net.lab1024.sa.admin.module.business.wms.base.area.manager.AreaManager;
import net.lab1024.sa.admin.module.business.wms.base.area.service.AreaQueryService;
import net.lab1024.sa.admin.module.business.wms.base.location.dao.LocationDao;
import net.lab1024.sa.admin.module.business.wms.base.location.domain.entity.LocationEntity;
import net.lab1024.sa.admin.module.business.wms.base.location.domain.form.LocationQueryForm;
import net.lab1024.sa.admin.module.business.wms.base.location.domain.form.LocationSelect;
import net.lab1024.sa.admin.module.business.wms.base.location.domain.vo.LocationsExcelVO;
import net.lab1024.sa.admin.module.business.wms.base.location.domain.vo.LocationVO;
import net.lab1024.sa.admin.module.business.wms.base.location.manager.LocationManager;
import net.lab1024.sa.admin.module.business.wms.base.location.service.LocationQueryService;
import net.lab1024.sa.admin.module.business.wms.excel.ExportTaskService;
import net.lab1024.sa.base.common.domain.PageResult;
import net.lab1024.sa.base.common.util.SmartEnumUtil;
import net.lab1024.sa.base.common.util.SmartExcelUtil;
import net.lab1024.sa.base.common.util.SmartPageUtil;
import net.lab1024.sa.base.module.support.dict.constant.DictConst;
import net.lab1024.sa.base.module.support.dict.service.DictService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Slf4j
public class LocationQueryServiceImpl implements LocationQueryService {

    @Resource
    private LocationDao locationDao;

    @Resource
    private AreaManager areaManager;

    @Resource
    private LocationManager locationManager;

    @Resource
    private AreaQueryService areaQueryService;

    @Resource
    private DictService dictService;

    @Resource
    private ExportTaskService exportTaskService;

    /**
     * 分页查询
     *
     * @param queryForm 查询参数
     * @return PageResult<LocationVO>
     */
    public PageResult<LocationVO> queryPage(LocationQueryForm queryForm) {
        Page<?> page = SmartPageUtil.convert2PageQuery(queryForm);
        List<LocationVO> list = locationDao.queryPage(page, queryForm);

        // 查询库区名称
        List<Long> areaIdList = list.stream().filter(Objects::nonNull).map(LocationVO::getAreaId).toList();
        Map<Long, AreaEntity> areaMap = areaQueryService.queryByAreaIds(areaIdList);
        list.forEach(locationVO -> {
            AreaEntity area = areaMap.get(locationVO.getAreaId());
            if (area != null) {
                locationVO.setAreaName(area.getAreaName());
            }
        });
        return SmartPageUtil.convert2PageResult(page, list);
    }

    /**
     * 实体转VO
     *
     * @param entity 实体
     * @return LocationVO
     */
    public LocationVO entityToVO(LocationEntity entity) {
        AreaEntity area = areaManager.queryArea(entity.getAreaId());
        return LocationVO.builder()
                .locationId(entity.getLocationId())
                .locationCode(entity.getLocationCode())
                .status(entity.getStatus())
                .areaId(entity.getAreaId())
                .areaName(area == null ? null : area.getAreaName())
                .disabledFlag(entity.getDisabledFlag())
                .locationRow(entity.getLocationRow())
                .locationLine(entity.getLocationLine())
                .locationCow(entity.getLocationCow())
                .locationType(entity.getLocationType())
                .remark(entity.getRemark())
                .createTime(entity.getCreateTime())
                .build();
    }


    /**
     * 库位下拉查询
     *
     * @param locationSelect 查询参数
     * @return List<LocationVO>
     */
    public List<LocationVO> queryLocation(LocationSelect locationSelect) {
        LambdaQueryWrapper<LocationEntity> queryWrapper = new LambdaQueryWrapper<>();
        //是否启用
        if (locationSelect.getDisabledFlag() != null) {
            queryWrapper.eq(LocationEntity::getDisabledFlag, locationSelect.getDisabledFlag());
        }
        //库区
        if (CollectionUtils.isNotEmpty(locationSelect.getAreaNames())) {
            List<AreaEntity> areaList = areaQueryService.queryByAreaNames(locationSelect.getAreaNames());
            if (CollectionUtils.isNotEmpty(areaList)) {
                List<Long> areaIdList = areaList.stream().map(AreaEntity::getAreaId).toList();
                queryWrapper.in(LocationEntity::getAreaId, areaIdList);
            }
        }

        //库位类型
        if (StringUtils.isNotBlank(locationSelect.getLocationType())) {
            queryWrapper.eq(LocationEntity::getLocationType, locationSelect.getLocationType());
        }

        //库位状态
        if (StringUtils.isNotBlank(locationSelect.getStatus())) {
            queryWrapper.eq(LocationEntity::getStatus, locationSelect.getStatus());
        }

        List<LocationEntity> list = locationManager.list(queryWrapper);

        return list.stream().map(this::entityToVO).collect(Collectors.toList());
    }

    /**
     * 根据库位ID集合查询库位信息
     *
     * @param locationIdList 库位ID集合
     * @return Map<Long, LocationEntity>
     */
    public Map<Long, LocationEntity> queryByLocationIdsToMap(List<Long> locationIdList) {
        if (CollectionUtils.isEmpty(locationIdList)) {
            return Collections.emptyMap();
        }
        locationIdList = locationIdList.stream().filter(Objects::nonNull).distinct().toList();
        Map<Long, LocationEntity> locationMap = Maps.newHashMap();
        for (Long locationId : locationIdList) {
            LocationEntity location = locationManager.queryLocation(locationId);
            if (location != null) {
                locationMap.put(locationId, location);
            }
        }
        return locationMap;
    }

    /**
     * 验证库区是否存在库位
     *
     * @param areaId 库区
     */
    public Boolean checkLocationExist(Long areaId) {
        if (areaId == null) {
            return true;
        }
        LambdaQueryWrapper<LocationEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LocationEntity::getAreaId, areaId);
        List<LocationEntity> list = locationManager.list(queryWrapper);
        return list.isEmpty();
    }

    /**
     * 根据库位编码查询库位信息
     *
     * @param locationCode 库位编码
     * @return LocationEntity
     */
    public LocationEntity queryByLocationCode(String locationCode) {
        if (StringUtils.isBlank(locationCode)) {
            return null;
        }
        LambdaQueryWrapper<LocationEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LocationEntity::getLocationCode, locationCode);
        return locationManager.getOne(queryWrapper);
    }

    /**
     * 根据库位编码集合查询库位信息
     *
     * @param locationCodes 库位编码集合
     * @return List<LocationEntity>
     */
    public List<LocationEntity> queryByLocationCodes(List<String> locationCodes) {
        if (CollectionUtils.isEmpty(locationCodes)) {
            return Collections.emptyList();
        }
        locationCodes = locationCodes.stream().filter(Objects::nonNull).distinct().toList();
        LambdaQueryWrapper<LocationEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(LocationEntity::getLocationCode, locationCodes);
        return locationManager.list(queryWrapper);
    }

    /**
     * 根据库位编码集合查询库位信息
     *
     * @param locationCodes 库位集合
     * @return Map<String, LocationEntity>
     */
    public Map<String, LocationEntity> queryByLocationCodesToMap(List<String> locationCodes) {
        if (CollectionUtils.isEmpty(locationCodes)) {
            return Collections.emptyMap();
        }
        //查询库位
        List<LocationEntity> locationList = queryByLocationCodes(locationCodes);
        //封装map
        Map<String, LocationEntity> locationMap = Maps.newHashMap();
        for (LocationEntity location : locationList) {
            locationMap.put(location.getLocationCode(), location);
        }
        return locationMap;
    }

    /**
     * 库位导出
     *
     * @return List<LocationsExcelVO>
     */
    public List<LocationsExcelVO> queryLocationsExcelVO() {
        List<LocationEntity> locationsList = locationManager.list();
        //库区
        List<Long> areaIds = locationsList.stream().map(LocationEntity::getAreaId).distinct().toList();
        Map<Long, AreaEntity> areaMap = areaQueryService.queryByAreaIds(areaIds);
        return locationsList.stream()
                .map(location ->
                        LocationsExcelVO.builder()
                                .areaName(areaMap.get(location.getAreaId()).getAreaName())
                                .locationCode(location.getLocationCode())
                                .locationType(dictService.getDictDataLabel(DictConst.LOC_TYPE.getValue(), location.getLocationType()))
                                .status(SmartEnumUtil.getEnumDescByValue(location.getStatus(), UsageStatusEnum.class))
                                .disabledFlag(location.getDisabledFlag() ? "启用" : "禁用")
                                .build()
                )
                .collect(Collectors.toList());

    }

    @Override
    public long locationCount(LocationQueryForm queryForm) {
        LambdaQueryWrapper<LocationEntity> queryWrapper = new LambdaQueryWrapper<>();
        if (queryForm.getAreaId() != null) {
            queryWrapper.eq(LocationEntity::getAreaId, queryForm.getAreaId());
        }
        if (queryForm.getLocationId() != null) {
            queryWrapper.eq(LocationEntity::getLocationId, queryForm.getLocationId());
        }
        if (StringUtils.isNotBlank(queryForm.getStatus())) {
            queryWrapper.eq(LocationEntity::getStatus, queryForm.getStatus());
        }
        if (queryForm.getDisabledFlag() != null) {
            queryWrapper.eq(LocationEntity::getDisabledFlag, queryForm.getDisabledFlag());
        }
        return locationManager.count(queryWrapper);
    }

    @Override
    public void exportLocation(String taskId, LocationQueryForm queryForm, HttpServletResponse response) {
        try {
            SmartExcelUtil.batchExportExcel(
                    response,
                    "库位信息.xlsx",
                    "库位信息",
                    LocationsExcelVO.class,
                    taskId,
                    locationCount(queryForm),
                    (lastId, pageSize) -> locationDao.listByCursor(lastId, pageSize, queryForm),
                    location -> LocationsExcelVO.builder()
                            .areaName(areaManager.queryArea(location.getAreaId()).getAreaName())
                            .locationCode(location.getLocationCode())
                            .locationType(dictService.getDictDataLabel(DictConst.LOC_TYPE.getValue(), location.getLocationType()))
                            .status(SmartEnumUtil.getEnumDescByValue(location.getStatus(), UsageStatusEnum.class))
                            .disabledFlag(location.getDisabledFlag() ? "启用" : "禁用")
                            .build(),
                    LocationVO::getLocationId,
                    2000,
                    (processed, progress) -> exportTaskService.updateProgress(taskId, progress)
            );
        } catch (Exception e) {
            exportTaskService.updateProgress(taskId, -1);
        } finally {
            exportTaskService.updateProgress(taskId, 100);
        }
    }

}
