/**
 * BladeX Commercial License Agreement
 * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
 * <p>
 * Use of this software is governed by the Commercial License Agreement
 * obtained after purchasing a license from BladeX.
 * <p>
 * 1. This software is for development use only under a valid license
 * from BladeX.
 * <p>
 * 2. Redistribution of this software's source code to any third party
 * without a commercial license is strictly prohibited.
 * <p>
 * 3. Licensees may copyright their own code but cannot use segments
 * from this software for such purposes. Copyright of this software
 * remains with BladeX.
 * <p>
 * Using this software signifies agreement to this License, and the software
 * must not be used for illegal purposes.
 * <p>
 * Author: Chill Zhuang (bladejava@qq.com)
 */
package org.springblade.transport.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.system.pojo.entity.Dept;
import org.springblade.transport.excel.CommonCargoExcel;
import org.springblade.transport.excel.CommonCargoExportExcel;
import org.springblade.transport.excel.CommonCargoImportFailureExcel;
import org.springblade.transport.mapper.CommonCargoMapper;
import org.springblade.transport.pojo.entity.CommonCargo;
import org.springblade.transport.pojo.vo.BusinessRemoveResultVO;
import org.springblade.transport.pojo.vo.CommonCargoVO;
import org.springblade.transport.service.ICommonCargoService;
import org.springblade.transport.support.TransportBusinessSupport;
import org.springblade.transport.wrapper.CommonCargoWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 常用货物 服务实现类
 *
 * @author Chill
 */
@Service
public class CommonCargoServiceImpl extends BaseServiceImpl<CommonCargoMapper, CommonCargo> implements ICommonCargoService {

	@Override
	public IPage<CommonCargoVO> selectCommonCargoPage(IPage<CommonCargo> page, CommonCargoVO commonCargo) {
		IPage<CommonCargo> entityPage = page(page, buildQuery(commonCargo));
		return CommonCargoWrapper.build().pageVO(entityPage);
	}

	@Override
	public CommonCargoVO detail(Long id) {
		return CommonCargoWrapper.build().entityVO(loadEditable(id, false));
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean submit(CommonCargo commonCargo) {
		boolean created = Func.isEmpty(commonCargo.getId());
		if (!created) {
			CommonCargo oldRecord = loadEditable(commonCargo.getId(), true);
			commonCargo.setCargoCode(oldRecord.getCargoCode());
			commonCargo.setDeptId(oldRecord.getDeptId());
			commonCargo.setDeptName(oldRecord.getDeptName());
		}
		prepare(commonCargo);
		validate(commonCargo);
		return saveOrUpdate(commonCargo);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public BusinessRemoveResultVO removeCommonCargo(String ids) {
		List<Long> idList = Func.toLongList(ids);
		if (Func.isEmpty(idList)) {
			throw new ServiceException("请选择需要删除的数据");
		}
		BusinessRemoveResultVO result = new BusinessRemoveResultVO();
		List<Long> deleteIdList = new ArrayList<>();
		for (CommonCargo commonCargo : listByIds(idList)) {
			TransportBusinessSupport.assertCurrentDept(commonCargo.getDeptId(), "常用货物");
			if (shouldSkipDelete(commonCargo)) {
				result.setSkippedCount(result.getSkippedCount() + 1);
				result.getSkippedCodes().add(commonCargo.getCargoCode());
				continue;
			}
			deleteIdList.add(commonCargo.getId());
		}
		if (Func.isNotEmpty(deleteIdList)) {
			deleteLogic(deleteIdList);
		}
		result.setSuccessCount(deleteIdList.size());
		return result;
	}

	@Override
	public List<CommonCargoExportExcel> exportCommonCargo(CommonCargoVO commonCargo, String ids) {
		LambdaQueryWrapper<CommonCargo> queryWrapper = buildQuery(commonCargo);
		if (Func.isNotEmpty(ids)) {
			queryWrapper.in(CommonCargo::getId, Func.toLongList(ids));
		}
		return list(queryWrapper).stream().map(record -> {
			CommonCargoExportExcel excel = new CommonCargoExportExcel();
			BeanUtil.copyProperties(record, excel);
			excel.setPackageBrand(String.join(" / ", List.of(
				Func.isEmpty(record.getPackageType()) ? "" : record.getPackageType(),
				Func.isEmpty(record.getBrand()) ? "" : record.getBrand()
			).stream().filter(value -> !value.isEmpty()).toList()));
			return excel;
		}).toList();
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public List<CommonCargoImportFailureExcel> importCommonCargo(List<CommonCargoExcel> data) {
		if (Func.isEmpty(data)) {
			throw new ServiceException("导入数据不能为空");
		}
		List<CommonCargoImportFailureExcel> failureList = new ArrayList<>();
		for (int index = 0; index < data.size(); index++) {
			CommonCargoExcel excel = data.get(index);
			try {
				CommonCargo commonCargo = new CommonCargo();
				commonCargo.setFirstCargoTypeName(TransportBusinessSupport.trimToNull(excel.getFirstCargoTypeName()));
				commonCargo.setSecondCargoTypeCode(TransportBusinessSupport.trimToNull(excel.getSecondCargoTypeCode()));
				String suffix = TransportBusinessSupport.trimToEmpty(excel.getCargoCodeSuffix());
				if (!suffix.matches("^\\d{2}$")) {
					throw new ServiceException("请输入2位数字");
				}
				if (Func.isEmpty(commonCargo.getSecondCargoTypeCode()) || commonCargo.getSecondCargoTypeCode().length() < 4) {
					throw new ServiceException("二级货物类型编码不存在");
				}
				commonCargo.setCargoCode(commonCargo.getSecondCargoTypeCode().substring(0, 4) + suffix);
				commonCargo.setCargoName(TransportBusinessSupport.trimToNull(excel.getCargoName()));
				commonCargo.setBrand(TransportBusinessSupport.trimToNull(excel.getBrand()));
				commonCargo.setPackageType(TransportBusinessSupport.trimToNull(excel.getPackageType()));
				commonCargo.setCargoValue(excel.getCargoValue());
				commonCargo.setSpecification(TransportBusinessSupport.trimToNull(excel.getSpecification()));
				commonCargo.setPriceUnit(TransportBusinessSupport.trimToNull(excel.getPriceUnit()));
				commonCargo.setModel(TransportBusinessSupport.trimToNull(excel.getModel()));
				commonCargo.setDescriptionOne(TransportBusinessSupport.trimToNull(excel.getDescriptionOne()));
				commonCargo.setSizeText(TransportBusinessSupport.trimToNull(excel.getSizeText()));
				commonCargo.setDescriptionTwo(TransportBusinessSupport.trimToNull(excel.getDescriptionTwo()));
				commonCargo.setRemark(TransportBusinessSupport.trimToNull(excel.getRemark()));
				commonCargo.setDataSource("批量导入");
				submit(commonCargo);
			} catch (Exception exception) {
				CommonCargoImportFailureExcel failureExcel = new CommonCargoImportFailureExcel();
				BeanUtil.copyProperties(excel, failureExcel);
				failureExcel.setErrorMessage("第" + (index + 2) + "行：" + exception.getMessage());
				failureList.add(failureExcel);
			}
		}
		return failureList;
	}

	private void validateCommonCargo(CommonCargo commonCargo) {
		if (Func.isEmpty(commonCargo.getSecondCargoTypeCode()) || commonCargo.getSecondCargoTypeCode().length() < 4) {
			throw new ServiceException("二级货物类型编码不存在");
		}
		String firstCode = commonCargo.getSecondCargoTypeCode().substring(0, 2);
		String firstName = baseMapper.selectCargoTypeName(firstCode, 1);
		String secondName = baseMapper.selectCargoTypeName(commonCargo.getSecondCargoTypeCode(), 2);
		if (Func.isEmpty(firstName)) {
			throw new ServiceException("请选择一级货物类型");
		}
		if (Func.isEmpty(secondName)) {
			throw new ServiceException("请选择二级货物类型");
		}
		if (Func.isNotEmpty(commonCargo.getFirstCargoTypeName()) && !Objects.equals(firstName, commonCargo.getFirstCargoTypeName())) {
			throw new ServiceException("二级货物类型编码不属于填写的一级货物类型");
		}
		commonCargo.setFirstCargoTypeCode(firstCode);
		commonCargo.setFirstCargoTypeName(firstName);
		commonCargo.setSecondCargoTypeName(secondName);
	}

	private LambdaQueryWrapper<CommonCargo> buildQuery(CommonCargoVO commonCargo) {
		TransportBusinessSupport.validateAllDept(commonCargo.getAllDept(), "常用货物");
		LambdaQueryWrapper<CommonCargo> queryWrapper = Wrappers.<CommonCargo>lambdaQuery().eq(CommonCargo::getIsDeleted, 0);
		if (!Objects.equals(commonCargo.getAllDept(), 1)) {
			queryWrapper.eq(CommonCargo::getDeptId, TransportBusinessSupport.currentDeptId("常用货物"));
		} else if (Func.isNotEmpty(commonCargo.getDeptId())) {
			queryWrapper.eq(CommonCargo::getDeptId, commonCargo.getDeptId());
		}
		if (Func.isNotEmpty(commonCargo.getFirstCargoTypeId())) {
			queryWrapper.eq(CommonCargo::getFirstCargoTypeId, commonCargo.getFirstCargoTypeId());
		}
		if (Func.isNotEmpty(commonCargo.getFirstCargoTypeName())) {
			queryWrapper.like(CommonCargo::getFirstCargoTypeName, commonCargo.getFirstCargoTypeName());
		}
		if (Func.isNotEmpty(commonCargo.getFirstCargoTypeCode())) {
			queryWrapper.like(CommonCargo::getFirstCargoTypeCode, commonCargo.getFirstCargoTypeCode());
		}
		if (Func.isNotEmpty(commonCargo.getSecondCargoTypeId())) {
			queryWrapper.eq(CommonCargo::getSecondCargoTypeId, commonCargo.getSecondCargoTypeId());
		}
		if (Func.isNotEmpty(commonCargo.getSecondCargoTypeName())) {
			queryWrapper.like(CommonCargo::getSecondCargoTypeName, commonCargo.getSecondCargoTypeName());
		}
		if (Func.isNotEmpty(commonCargo.getSecondCargoTypeCode())) {
			queryWrapper.like(CommonCargo::getSecondCargoTypeCode, commonCargo.getSecondCargoTypeCode());
		}
		if (Func.isNotEmpty(commonCargo.getCargoName())) {
			queryWrapper.like(CommonCargo::getCargoName, commonCargo.getCargoName());
		}
		if (Func.isNotEmpty(commonCargo.getCargoCode())) {
			queryWrapper.eq(CommonCargo::getCargoCode, commonCargo.getCargoCode());
		}
		if (Func.isNotEmpty(commonCargo.getBrand())) {
			queryWrapper.like(CommonCargo::getBrand, commonCargo.getBrand());
		}
		if (Func.isNotEmpty(commonCargo.getPackageType())) {
			queryWrapper.like(CommonCargo::getPackageType, commonCargo.getPackageType());
		}
		if (Func.isNotEmpty(commonCargo.getSpecification())) {
			queryWrapper.like(CommonCargo::getSpecification, commonCargo.getSpecification());
		}
		if (Func.isNotEmpty(commonCargo.getPriceUnit())) {
			queryWrapper.like(CommonCargo::getPriceUnit, commonCargo.getPriceUnit());
		}
		if (Func.isNotEmpty(commonCargo.getModel())) {
			queryWrapper.like(CommonCargo::getModel, commonCargo.getModel());
		}
		if (Func.isNotEmpty(commonCargo.getDescriptionOne())) {
			queryWrapper.like(CommonCargo::getDescriptionOne, commonCargo.getDescriptionOne());
		}
		if (Func.isNotEmpty(commonCargo.getSizeText())) {
			queryWrapper.like(CommonCargo::getSizeText, commonCargo.getSizeText());
		}
		if (Func.isNotEmpty(commonCargo.getDescriptionTwo())) {
			queryWrapper.like(CommonCargo::getDescriptionTwo, commonCargo.getDescriptionTwo());
		}
		if (Func.isNotEmpty(commonCargo.getDataSource())) {
			queryWrapper.eq(CommonCargo::getDataSource, commonCargo.getDataSource());
		}
		if (Func.isNotEmpty(commonCargo.getRemark())) {
			queryWrapper.like(CommonCargo::getRemark, commonCargo.getRemark());
		}
		queryWrapper.orderByDesc(CommonCargo::getUpdateTime).orderByDesc(CommonCargo::getCreateTime);
		return queryWrapper;
	}

	private void prepare(CommonCargo commonCargo) {
		commonCargo.setFirstCargoTypeName(TransportBusinessSupport.trimToNull(commonCargo.getFirstCargoTypeName()));
		commonCargo.setFirstCargoTypeCode(TransportBusinessSupport.trimToNull(commonCargo.getFirstCargoTypeCode()));
		commonCargo.setSecondCargoTypeName(TransportBusinessSupport.trimToNull(commonCargo.getSecondCargoTypeName()));
		commonCargo.setSecondCargoTypeCode(TransportBusinessSupport.trimToNull(commonCargo.getSecondCargoTypeCode()));
		commonCargo.setCargoName(TransportBusinessSupport.trimToNull(commonCargo.getCargoName()));
		commonCargo.setCargoCode(TransportBusinessSupport.trimToNull(commonCargo.getCargoCode()));
		commonCargo.setBrand(TransportBusinessSupport.trimToNull(commonCargo.getBrand()));
		commonCargo.setPackageType(TransportBusinessSupport.trimToNull(commonCargo.getPackageType()));
		commonCargo.setSpecification(TransportBusinessSupport.trimToNull(commonCargo.getSpecification()));
		commonCargo.setPriceUnit(TransportBusinessSupport.trimToNull(commonCargo.getPriceUnit()));
		commonCargo.setModel(TransportBusinessSupport.trimToNull(commonCargo.getModel()));
		commonCargo.setDescriptionOne(TransportBusinessSupport.trimToNull(commonCargo.getDescriptionOne()));
		commonCargo.setSizeText(TransportBusinessSupport.trimToNull(commonCargo.getSizeText()));
		commonCargo.setDescriptionTwo(TransportBusinessSupport.trimToNull(commonCargo.getDescriptionTwo()));
		commonCargo.setDataSource(TransportBusinessSupport.trimToNull(commonCargo.getDataSource()));
		commonCargo.setDeptName(TransportBusinessSupport.trimToNull(commonCargo.getDeptName()));
		commonCargo.setRemark(TransportBusinessSupport.trimToNull(commonCargo.getRemark()));
		if (Func.isEmpty(commonCargo.getDeptId())) {
			Dept dept = TransportBusinessSupport.currentDept("常用货物");
			commonCargo.setDeptId(dept.getId());
			commonCargo.setDeptName(dept.getDeptName());
		}
		if (commonCargo.getStatus() == null) { commonCargo.setStatus(1); }
	}

	private void validate(CommonCargo commonCargo) {
		TransportBusinessSupport.validateRequired(commonCargo.getFirstCargoTypeName(), "请选择一级货物类型");
		TransportBusinessSupport.validateRequired(commonCargo.getSecondCargoTypeCode(), "请选择二级货物类型");
		TransportBusinessSupport.validateRequired(commonCargo.getCargoName(), "请输入货物名称");
		TransportBusinessSupport.validateRequired(commonCargo.getCargoCode(), "请输入货物编号");
		TransportBusinessSupport.validateLength(commonCargo.getFirstCargoTypeName(), 255, "一级货物类型不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getFirstCargoTypeCode(), 255, "一级货物类型编码不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getSecondCargoTypeName(), 255, "二级货物类型不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getSecondCargoTypeCode(), 255, "二级货物类型编码不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getCargoName(), 255, "货物名称不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getCargoCode(), 255, "货物编号不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getBrand(), 255, "品牌不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getPackageType(), 255, "包装不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getSpecification(), 255, "规格不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getPriceUnit(), 255, "计价单位不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getModel(), 255, "型号不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getDescriptionOne(), 255, "说明1不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getSizeText(), 255, "尺寸不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getDescriptionTwo(), 255, "说明2不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getDataSource(), 255, "数据来源不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getDeptName(), 255, "所属组织不能超过255字");
		TransportBusinessSupport.validateLength(commonCargo.getRemark(), 500, "备注不能超过500字");
		validateCommonCargo(commonCargo);
		TransportBusinessSupport.validateNonNegative(commonCargo.getCargoValue(), "货值");
		if (count(Wrappers.<CommonCargo>lambdaQuery().eq(CommonCargo::getCargoCode, commonCargo.getCargoCode()).ne(Func.isNotEmpty(commonCargo.getId()), CommonCargo::getId, commonCargo.getId()).eq(CommonCargo::getIsDeleted, 0)) > 0) { throw new ServiceException("该货物编号已存在"); }
	}

	private CommonCargo loadEditable(Long id, boolean checkDept) {
		if (Func.isEmpty(id)) {
			throw new ServiceException("主键不能为空");
		}
		CommonCargo commonCargo = getById(id);
		if (Func.isEmpty(commonCargo) || Objects.equals(commonCargo.getIsDeleted(), 1)) {
			throw new ServiceException("常用货物不存在");
		}
		if (checkDept) {
			TransportBusinessSupport.assertCurrentDept(commonCargo.getDeptId(), "常用货物");
		}
		return commonCargo;
	}

	private boolean shouldSkipDelete(CommonCargo commonCargo) {
		return false;
	}

}
