package com.fuint.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fuint.common.Constants;
import com.fuint.common.dto.MaterialSearchDto;
import com.fuint.common.util.TimeUtils;
import com.fuint.common.vo.MaterialVo;
import com.fuint.framework.annoation.OperationServiceLog;
import com.fuint.framework.exception.BusinessCheckException;
import com.fuint.framework.pagination.PaginationRequest;
import com.fuint.framework.pagination.PaginationResponse;
import com.fuint.framework.web.PageResult;
import com.fuint.repository.mapper.MtMaterialTypeMapper;
import com.fuint.repository.mapper.MtStoreMapper;
import com.fuint.repository.model.MtMaterial;
import com.fuint.common.service.MaterialService;
import com.fuint.common.enums.StatusEnum;
import com.fuint.repository.mapper.MtMaterialMapper;
import com.fuint.repository.model.MtMaterialType;
import com.fuint.repository.model.MtStore;
import com.github.pagehelper.PageHelper;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.pagehelper.Page;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 材料表服务接口
 * <p>
 * Created by PZG
 * CopyRight https://www.fuint.cn
 */
@Service
@AllArgsConstructor
public class MaterialServiceImpl extends ServiceImpl<MtMaterialMapper, MtMaterial> implements MaterialService {

	private static final Logger logger = LoggerFactory.getLogger(MaterialServiceImpl.class);

	private MtMaterialMapper mtMaterialMapper;

	private MtStoreMapper storeMapper;

    private MtMaterialTypeMapper mtMaterialTypeMapper;


	/**
	 * 分页查询数据列表
	 *
	 * @param paginationRequest
	 * @return
	 */
	@Override
	public PaginationResponse<MtMaterial> queryMaterialListByPagination(PaginationRequest paginationRequest) {
		Page<MtMaterial> pageHelper = PageHelper.startPage(paginationRequest.getCurrentPage(), paginationRequest.getPageSize());
		LambdaQueryWrapper<MtMaterial> lambdaQueryWrapper = Wrappers.lambdaQuery();
		lambdaQueryWrapper.ne(MtMaterial::getDeleteFlag, 0);

		lambdaQueryWrapper.orderByAsc(MtMaterial::getId);
		List<MtMaterial> dataList = mtMaterialMapper.selectList(lambdaQueryWrapper);

		PageRequest pageRequest = PageRequest.of(paginationRequest.getCurrentPage(), paginationRequest.getPageSize());
		PageImpl pageImpl = new PageImpl(dataList, pageRequest, pageHelper.getTotal());
		PaginationResponse<MtMaterial> paginationResponse = new PaginationResponse(pageImpl, MtMaterial.class);
		paginationResponse.setTotalPages(pageHelper.getPages());
		paginationResponse.setTotalElements(pageHelper.getTotal());
		paginationResponse.setContent(dataList);

		return paginationResponse;
	}

	/**
	 * 添加材料表
	 *
	 * @param mtMaterial 材料表信息
	 * @return
	 */
	@Override
	@OperationServiceLog(description = "新增材料表")
	public MtMaterial addMaterial(MtMaterial mtMaterial) throws BusinessCheckException {
		MtStore mtStore = storeMapper.selectById(mtMaterial.getStoreId());
		if (Objects.isNull(mtStore)){
			throw new BusinessCheckException("店铺不存在");
		}
		mtMaterial.setDeleteFlag(0);
		mtMaterial.setUpdateTime(new Date());
		mtMaterial.setCreateTime(new Date());
		int id = mtMaterialMapper.insert(mtMaterial);
		if (id > 0) {
			return mtMaterial;
		} else {
			throw new BusinessCheckException("新增材料表数据失败");
		}
	}

	/**
	 * 根据ID获材料表取息
	 *
	 * @param id 材料表ID
	 * @return
	 */
	@Override
	public MtMaterial queryMaterialById(Long id) {
		return mtMaterialMapper.selectById(id);
	}

	/**
	 * 根据ID删除材料表
	 *
	 * @param id       材料表ID
	 * @param operator 操作人
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	@OperationServiceLog(description = "删除材料表")
	public void deleteMaterial(Long id, String operator) {
		MtMaterial mtMaterial = queryMaterialById(id);
		if (null == mtMaterial) {
			return;
		}
		mtMaterial.setUpdateUserId(operator);
		mtMaterial.setDeleteFlag(1);
		mtMaterial.setUpdateTime(new Date());
		mtMaterialMapper.updateById(mtMaterial);
	}

	/**
	 * 修改材料表数据
	 *
	 * @param mtMaterial
	 * @return
	 * @throws BusinessCheckException
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	@OperationServiceLog(description = "更新材料表")
	public MtMaterial updateMaterial(MtMaterial mtMaterial) throws BusinessCheckException {
		mtMaterialMapper.updateById(mtMaterial);
		return mtMaterial;
	}

	/**
	 * 根据条件搜索材料表
	 *
	 * @param params 查询参数
	 * @return
	 * @throws BusinessCheckException
	 */
	@Override
	public List<MtMaterial> queryMaterialListByParams(Map<String, Object> params) {
		String status = params.get("status") == null ? StatusEnum.ENABLED.getKey() : params.get("status").toString();
		String storeId = params.get("storeId") == null ? "" : params.get("storeId").toString();
		String merchantId = params.get("materialTypeId") == null ? "" : params.get("materialTypeId").toString();

		LambdaQueryWrapper<MtMaterial> lambdaQueryWrapper = Wrappers.lambdaQuery();
		if (StringUtils.isNotBlank(status)) {
			lambdaQueryWrapper.eq(MtMaterial::getDeleteFlag, status);
		}
		if (StringUtils.isNotBlank(merchantId)) {
			lambdaQueryWrapper.eq(MtMaterial::getMaterialTypeId, merchantId);
		}
		if (StringUtils.isNotBlank(storeId)) {
			lambdaQueryWrapper.and(wq -> wq
					.eq(MtMaterial::getStoreId, 0)
					.or()
					.eq(MtMaterial::getStoreId, storeId));
		}

		lambdaQueryWrapper.orderByAsc(MtMaterial::getId);
		List<MtMaterial> dataList = mtMaterialMapper.selectList(lambdaQueryWrapper);
		return dataList;
	}

	@SneakyThrows
    @Override
	public PageResult<MaterialVo> selectMaterialList(MaterialSearchDto materialSearchDto) {
		int pageNo = materialSearchDto.getPageNo() == null ? Constants.PAGE_NUMBER : materialSearchDto.getPageNo();
		int pageSize = materialSearchDto.getPageSize() == null ? Constants.PAGE_SIZE : materialSearchDto.getPageSize();
		//构件查询条件
		LambdaQueryWrapper<MtMaterial> queryWrapper = new LambdaQueryWrapper<>();
		if (StringUtils.isNotBlank(materialSearchDto.getName())){
			queryWrapper.eq(MtMaterial::getName, materialSearchDto.getName());
		}
		if (Objects.nonNull(materialSearchDto.getStatus())){
			queryWrapper.eq(MtMaterial::getStatus, materialSearchDto.getStatus());
		}
		if (StringUtils.isNotBlank(materialSearchDto.getStoreId()) && Long.parseLong(materialSearchDto.getStoreId())>0){
			queryWrapper.eq(MtMaterial::getStoreId, Long.valueOf(materialSearchDto.getStoreId()));
		}
		if (StringUtils.isNotBlank(materialSearchDto.getCreateTime())){
			queryWrapper.between(MtMaterial::getCreateTime,
					TimeUtils.getStartAndEndOfDay(materialSearchDto.getCreateTime())[0],
					TimeUtils.getStartAndEndOfDay(materialSearchDto.getCreateTime())[1]);
		}
		//获取总条数
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> mtMaterialMapper.selectCount(queryWrapper));
       //构建分页
        PageHelper.startPage(Math.toIntExact(pageNo), Math.toIntExact(pageSize));
		//查询数据
        List<MtMaterial> mtMaterials = mtMaterialMapper.selectList(queryWrapper);
		List<MaterialVo> materialVos = mtMaterials.stream().map(mtMaterial -> {
			MaterialVo materialVo = new MaterialVo();
			BeanUtils.copyProperties(mtMaterial, materialVo);
			MtStore mtStore = storeMapper.selectById(mtMaterial.getStoreId());
            MtMaterialType mtMaterialType = mtMaterialTypeMapper.selectById(mtMaterial.getMaterialTypeId());
            if (Objects.nonNull(mtStore)){
	            materialVo.setStoreName(mtStore.getName());
            }
			if (Objects.nonNull(mtMaterialType)){
				materialVo.setMaterialType(mtMaterialType.getName());

			}
			return materialVo;
		}).collect(Collectors.toList());
		return PageResult.<MaterialVo>builder().data(materialVos).total(future.get()).build();
	}
}
