package com.iformall.service.invest.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iformall.common.ErrorCode;
import com.iformall.domain.po.*;
import com.iformall.domain.po.invest.*;
import com.iformall.domain.vo.invest.InvestPageQuery;
import com.iformall.domain.vo.invest.InvestPageResult;
import com.iformall.domain.vo.invest.InvestUserContext;
import com.iformall.enums.EnumFollowType;
import com.iformall.enums.EnumInvestMessageType;
import com.iformall.enums.EnumInvestType;
import com.iformall.enums.EnumShopStatus;
import com.iformall.exception.MallinkException;
import com.iformall.service.MallUserInfoService;
import com.iformall.service.WxBrandService;
import com.iformall.service.WxBusinessService;
import com.iformall.service.WxShopService;
import com.iformall.service.invest.InvestBaseService;
import com.iformall.service.invest.InvestCustomerService;
import com.iformall.service.invest.InvestHelper;
import com.iformall.service.invest.InvestMessageService;
import com.iformall.utils.JsonUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;

public class InvestBaseServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> implements InvestBaseService<T> {

	@Autowired
	private InvestMessageService messageService;

	@Override
	public InvestPageResult<T> queryPage(InvestPageQuery<T> params) {
		return this.queryPage(params, null);
	}

	@Override
	public InvestPageResult<T> queryPage(InvestPageQuery<T> params, LambdaQueryWrapper<T> queryWrapper) {
		InvestHelper.notNull(params);
		//1、分页信息
		Page<T> queryPage = buildQueryPage(params);
		//2、查询数据
		T queryParams = params.getQueryData();
		if (Objects.isNull(queryWrapper)) {
			queryWrapper = new LambdaQueryWrapper<>(queryParams);
		}
		IPage<T> resultPage = this.page(queryPage, queryWrapper);

		InvestPageResult<T> investPage = new InvestPageResult<>();
		if (CollectionUtils.isEmpty(resultPage.getRecords())) {
			return investPage;
		}
		BeanUtils.copyProperties(resultPage, investPage);
		return investPage;
	}

	@Override
	public T getByIdNotNull(Serializable id) {
		InvestHelper.checkResult(id,"id=null");
		T t = super.getById(id);
		InvestHelper.checkResult(t,"id=null");
		return t;
	}

	boolean saveAction(T entity, Consumer<T> consumer) {
		checkUserAndTenant(entity,consumer);
		return super.save(entity);
	}

	boolean updateActon(T entity, Wrapper<T> updateWrapper, Consumer<T> consumer) {
		checkUserAndTenant(entity,consumer);
		return super.update(entity, updateWrapper);
	}

	boolean saveOrUpdateAction(T entity, Consumer<T> consumer) {
		checkUserAndTenant(entity,consumer);
		return super.saveOrUpdate(entity);
	}

	boolean updateByIdAction(T entity, Consumer<T> consumer) {
		checkUserAndTenant(entity,consumer);
		return super.updateById(entity);
	}

	void checkUserAndTenant(T input,Consumer<T> consumer) {
		InvestHelper.notNull(input, "参数");
		InvestHelper.notNull(InvestUserContext.getUser(), ErrorCode.USER_IS_EMPTY);
		((InvestBaseEntity) input).setTenantId(InvestUserContext.getUser().getTenantId());
		if(consumer!=null) {
			consumer.accept(input);
		}
	}

	@Override
	public boolean saveBatchMessage(List<Long> ownerArray, EnumInvestMessageType message, EnumFollowType type, Long tid) {
		if (CollectionUtils.isEmpty(ownerArray)) {
			return false;
		}
		LambdaQueryWrapper<InvestMessageEntity> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(InvestMessageEntity::getType, type);
		queryWrapper.eq(InvestMessageEntity::getTid, tid);
		queryWrapper.in(InvestMessageEntity::getOwner, ownerArray);
		List<InvestMessageEntity> before = messageService.list();
		Map<Long,InvestMessageEntity> map = InvestHelper.getMap(before,InvestMessageEntity::getOwner) ;
		List<InvestMessageEntity> messageEntityList = new ArrayList<>();
		for (Long aLong : ownerArray) {
			if(Objects.nonNull(map.get(aLong))) {
				continue;
			}
			InvestMessageEntity messageEntity = new InvestMessageEntity();
			messageEntity.setOwner(aLong);
			messageEntity.setTid(tid);
			messageEntity.setType(type);
			messageEntity.setTenantId(InvestUserContext.getUser().getTenantId());
			messageEntity.setMessage(EnumInvestMessageType.message(message));
			messageEntityList.add(messageEntity);
		}
		return messageService.saveBatch(messageEntityList);
	}

	/**
	 * 校验商铺
	 *
	 * @param shopService
	 * @param inputEntity
	 */
	void checkShop(WxShopService shopService, T inputEntity) {
		Long targetId = null;
		EnumInvestType investType = null;
		if (inputEntity instanceof InvestDemandEntity) {
			InvestDemandEntity entity = (InvestDemandEntity) inputEntity;
			targetId = entity.getTargetId();
			investType = entity.getTargetType();
		} else if (inputEntity instanceof InvestTaskEntity) {
			InvestTaskEntity entity = (InvestTaskEntity) inputEntity;
			targetId = entity.getTargetId();
			investType = entity.getTargetType();
		}

		if (EnumInvestType.RENT.equals(investType)) {
			WxShop shop = shopService.getById(targetId);
			checkShopNotNull(shop);
		}
	}


	/**
	 * 校验参数是否为空
	 *
	 * @param shop
	 */
	private void checkShopNotNull(WxShop shop) {
		InvestHelper.notNull(shop, ErrorCode.SHOP_IS_NOT_FOUND);
		InvestHelper.isTrue(Objects.equals(shop.getStatus(), EnumShopStatus.NOT_RENT.getCode()), ErrorCode.SHOP_IS_RENT, null);
	}

	/**
	 * 校验用户是否存在
	 *
	 * @param userInfoService
	 * @param userIdJson
	 */
	void checkUserExit(MallUserInfoService userInfoService, String userIdJson) {
		if (Objects.nonNull(userIdJson)) {
			List<Long> ids = JSONArray.parseArray(userIdJson, Long.class);
			if (CollectionUtils.isNotEmpty(ids)) {
				List<Long> usersFromDb = userInfoService.getByIds(ids).stream().map(MallUserInfo::getId).collect(Collectors.toList());
				List<Long> notExsitIds = ids.stream().filter(uid -> !usersFromDb.contains(uid)).collect(Collectors.toList());
				InvestHelper.isTrue(CollectionUtils.isEmpty(notExsitIds), ErrorCode.USER_IS_EMPTY, notExsitIds);
			}
		}
	}

	void checkUserExit(MallUserInfoService userInfoService, Long id) {
		if (Objects.nonNull(id)) {
			MallUserInfo userInfo = userInfoService.getById(id);
			InvestHelper.isTrue(Objects.nonNull(userInfo), ErrorCode.USER_IS_EMPTY, id);
		}
	}

	void checkCustomerExit(InvestCustomerService customerService, Long id) {
		InvestCustomerEntity customerEntity = customerService.getById(id);
		InvestHelper.isTrue(Objects.nonNull(customerEntity), ErrorCode.INVEST_CUSTOMER_NOT_FOUND, id);
	}

	void checkBusiness(WxBusinessService businessService, Integer businessId) {
		WxBusiness business = businessService.getById(businessId) ;
		InvestHelper.notNull(business, ErrorCode.BUSINESS_NOT_FOUND);
	}

	void checkBrand(WxBrandService brandService, Long brandId) {
		WxBrand brand = brandService.getById(brandId);
		InvestHelper.notNull(brand, ErrorCode.BRAND_NOT_FOUND);
	}

	protected Page<T> buildQueryPage(InvestPageQuery<T> pageQuery) {
		return InvestHelper.buildQueryPage(pageQuery) ;
	}


	void notSupport() {
		throw new MallinkException(ErrorCode.SYS_METHOD_NOT_SUPPORT);
	}

	String stringToJson(String json) {
		Object object = JsonUtil.readValue(json, Object.class);
		return JsonUtil.obj2Json(object);
	}

}
