package org.springblade.transport.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
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.cache.UserCache;
import org.springblade.transport.excel.EquipmentLedgerExcel;
import org.springblade.transport.mapper.EquipmentLedgerMapper;
import org.springblade.transport.pojo.entity.EquipmentLedger;
import org.springblade.transport.pojo.vo.EquipmentLedgerVO;
import org.springblade.transport.service.IEquipmentLedgerService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 设备台账服务实现
 *
 * @author Chill
 */
@Service
public class EquipmentLedgerServiceImpl extends BaseServiceImpl<EquipmentLedgerMapper, EquipmentLedger> implements IEquipmentLedgerService {

	private static final String VEHICLE = "车辆";
	private static final String SHIP = "船舶";
	private static final int VEHICLE_NO_MAX_LENGTH = 30;
	private static final int EQUIPMENT_CODE_MAX_LENGTH = 12;
	private static final int EQUIPMENT_NAME_MAX_LENGTH = 100;
	private static final int EQUIPMENT_BRAND_MAX_LENGTH = 50;
	private static final int EQUIPMENT_TYPE_MAX_LENGTH = 50;
	private static final int SPECIFICATION_MODEL_MAX_LENGTH = 100;
	private static final int ORIGINAL_EQUIPMENT_NO_MAX_LENGTH = 100;
	private static final int REMARK_MAX_LENGTH = 200;
	private static final int ATTACHMENTS_MAX_LENGTH = 1000;

	@Override
	public IPage<EquipmentLedgerVO> selectEquipmentLedgerPage(IPage<EquipmentLedgerVO> page, EquipmentLedgerVO equipmentLedger) {
		List<EquipmentLedgerVO> records = baseMapper.selectEquipmentLedgerPage(page, equipmentLedger);
		records.forEach(record -> record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser())));
		return page.setRecords(records);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public boolean submit(EquipmentLedger equipmentLedger) {
		prepare(equipmentLedger);
		if (equipmentLedger.getId() == null && Func.isEmpty(equipmentLedger.getEquipmentCode())) {
			equipmentLedger.setEquipmentCode(nextEquipmentCode());
		}
		validate(equipmentLedger);
		validateEquipmentCodeImmutable(equipmentLedger);
		return saveOrUpdate(equipmentLedger);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public List<EquipmentLedgerExcel> importEquipmentLedger(List<EquipmentLedgerExcel> data) {
		if (Func.isEmpty(data)) {
			throw new ServiceException("导入数据不能为空");
		}
		List<EquipmentLedgerExcel> errorList = new ArrayList<>();
		for (int index = 0; index < data.size(); index++) {
			EquipmentLedgerExcel excel = data.get(index);
			try {
				EquipmentLedger equipmentLedger = Objects.requireNonNull(BeanUtil.copyProperties(excel, EquipmentLedger.class));
				submit(equipmentLedger);
			} catch (Exception exception) {
				excel.setErrorMessage("第" + (index + 2) + "行：" + exception.getMessage());
				errorList.add(excel);
			}
		}
		return errorList;
	}

	@Override
	public List<EquipmentLedgerExcel> exportEquipmentLedger(Wrapper<EquipmentLedger> queryWrapper) {
		return list(queryWrapper).stream()
			.map(item -> Objects.requireNonNull(BeanUtil.copyProperties(item, EquipmentLedgerExcel.class)))
			.toList();
	}

	@Override
	public String nextEquipmentCode() {
		String prefix = "EQ" + LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE);
		for (int sequence = 1; sequence <= 99; sequence++) {
			String code = prefix + String.format("%02d", sequence);
			if (!exists(new LambdaQueryWrapper<EquipmentLedger>().eq(EquipmentLedger::getEquipmentCode, code))) {
				return code;
			}
		}
		throw new ServiceException("当天设备编号已达到上限");
	}

	private void prepare(EquipmentLedger equipmentLedger) {
		equipmentLedger.setVehicleType(trimToEmpty(equipmentLedger.getVehicleType()));
		equipmentLedger.setVehicleNo(trimToEmpty(equipmentLedger.getVehicleNo()));
		if (VEHICLE.equals(equipmentLedger.getVehicleType())) {
			equipmentLedger.setVehicleNo(equipmentLedger.getVehicleNo().toUpperCase());
		}
		equipmentLedger.setEquipmentCode(trimToNull(equipmentLedger.getEquipmentCode()));
		equipmentLedger.setEquipmentName(trimToNull(equipmentLedger.getEquipmentName()));
		equipmentLedger.setEquipmentBrand(trimToNull(equipmentLedger.getEquipmentBrand()));
		equipmentLedger.setEquipmentType(trimToNull(equipmentLedger.getEquipmentType()));
		equipmentLedger.setSpecificationModel(trimToNull(equipmentLedger.getSpecificationModel()));
		equipmentLedger.setOriginalEquipmentNo(trimToNull(equipmentLedger.getOriginalEquipmentNo()));
		equipmentLedger.setAttachments(trimToNull(equipmentLedger.getAttachments()));
		equipmentLedger.setRemark(trimToNull(equipmentLedger.getRemark()));
		if (equipmentLedger.getOnlineStatus() == null) {
			equipmentLedger.setOnlineStatus(0);
		}
	}

	private void validate(EquipmentLedger equipmentLedger) {
		if (!VEHICLE.equals(equipmentLedger.getVehicleType()) && !SHIP.equals(equipmentLedger.getVehicleType())) {
			throw new ServiceException("车船类型不正确");
		}
		if (Func.isEmpty(equipmentLedger.getVehicleNo())) {
			throw new ServiceException("车牌号/船号不能为空");
		}
		if (Func.isEmpty(equipmentLedger.getEquipmentCode())) {
			throw new ServiceException("设备编号不能为空");
		}
		if (Func.isEmpty(equipmentLedger.getEquipmentName())) {
			throw new ServiceException("设备名称不能为空");
		}
		if (equipmentLedger.getOnlineStatus() != 0 && equipmentLedger.getOnlineStatus() != 1) {
			throw new ServiceException("是否在线不正确");
		}
		validateLength(equipmentLedger.getVehicleNo(), VEHICLE_NO_MAX_LENGTH, "车牌号/船号不能超过30字");
		validateLength(equipmentLedger.getEquipmentCode(), EQUIPMENT_CODE_MAX_LENGTH, "设备编号格式不正确");
		validateLength(equipmentLedger.getEquipmentName(), EQUIPMENT_NAME_MAX_LENGTH, "设备名称不能超过100字");
		validateLength(equipmentLedger.getEquipmentBrand(), EQUIPMENT_BRAND_MAX_LENGTH, "设备品牌不能超过50字");
		validateLength(equipmentLedger.getEquipmentType(), EQUIPMENT_TYPE_MAX_LENGTH, "设备类型不能超过50字");
		validateLength(equipmentLedger.getSpecificationModel(), SPECIFICATION_MODEL_MAX_LENGTH, "规格型号不能超过100字");
		validateLength(equipmentLedger.getOriginalEquipmentNo(), ORIGINAL_EQUIPMENT_NO_MAX_LENGTH, "原厂设备号不能超过100字");
		validateLength(equipmentLedger.getRemark(), REMARK_MAX_LENGTH, "备注不能超过200字");
		validateLength(equipmentLedger.getAttachments(), ATTACHMENTS_MAX_LENGTH, "附件不能超过1000字");
	}

	private void validateEquipmentCodeImmutable(EquipmentLedger equipmentLedger) {
		EquipmentLedger existing = getOne(new LambdaQueryWrapper<EquipmentLedger>()
			.eq(EquipmentLedger::getEquipmentCode, equipmentLedger.getEquipmentCode())
			.ne(equipmentLedger.getId() != null, EquipmentLedger::getId, equipmentLedger.getId()));
		if (existing != null) {
			throw new ServiceException("设备编号已存在");
		}
		if (equipmentLedger.getId() != null) {
			EquipmentLedger current = getById(equipmentLedger.getId());
			if (current == null) {
				throw new ServiceException("设备台账不存在");
			}
			if (!Objects.equals(current.getEquipmentCode(), equipmentLedger.getEquipmentCode())) {
				throw new ServiceException("设备编号不允许修改");
			}
		}
	}

	private void validateLength(String value, int maxLength, String message) {
		if (Func.isNotEmpty(value) && value.length() > maxLength) {
			throw new ServiceException(message);
		}
	}

	private String trimToEmpty(String value) {
		return value == null ? "" : value.trim();
	}

	private String trimToNull(String value) {
		String trimValue = trimToEmpty(value);
		return trimValue.isEmpty() ? null : trimValue;
	}
}
