package com.neusoft.smart.pos.device.service;

import com.neusoft.smart.pos.device.constants.DeviceErrorCode;
import com.neusoft.smart.pos.device.persistent.domain.ConfigStrategy;
import com.neusoft.smart.pos.device.persistent.domain.ConfigStrategyGroup;
import com.neusoft.smart.pos.device.persistent.domain.Device;
import com.neusoft.smart.pos.device.persistent.ext.domain.ConfigStrategyQuery;
import com.neusoft.smart.pos.device.persistent.ext.domain.DeviceQuery;
import com.neusoft.smart.pos.device.persistent.repository.ConfigStrategyRepository;
import com.neusoft.smart.pos.device.persistent.repository.DeviceRepository;
import com.neusoft.smart.pos.device.task.ConfigStrategyTask;
import com.neusoft.smart.pos.dto.device.request.ConfigStrategyGroupRequest;
import com.neusoft.smart.pos.dto.device.request.ConfigStrategyQueryRequest;
import com.neusoft.smart.pos.dto.device.response.*;
import com.neusoft.smart.pos.framework.exception.BusinessCommonException;
import com.neusoft.smart.pos.framework.task.TaskExecutor;
import com.neusoft.smart.pos.framework.utils.BeanUtil;
import com.neusoft.smart.pos.redis.bean.DeviceConfig;
import com.neusoft.smart.pos.utils.RequestHeaderUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ConfigStrategyService {
	
	@Autowired
	private ConfigStrategyRepository configStrategyRepository;
	
	@Autowired
	private DeviceRepository deviceRepository;
	
	@Autowired
	private TaskExecutor taskExecutor;
	
	@Resource(name = "deviceConfigMap")
	private BoundHashOperations<String, String, List<DeviceConfig>> deviceConfigMap;

	@Resource(name = "deviceConfigMapWithSn")
	private BoundHashOperations<String, String, List<DeviceConfig>> deviceConfigMapWithSn;

	/**
	 * @param configStrategyGroupRequest
	 */
	@Transactional
	public void create(ConfigStrategyGroupRequest configStrategyGroupRequest) {
		ConfigStrategyQuery configStrategyQuery = new ConfigStrategyQuery();
		configStrategyQuery.setStrategyName(configStrategyGroupRequest.getStrategyName());
		configStrategyQuery.setOrganizationId(RequestHeaderUtil.getOrgId());
		Integer count = configStrategyRepository.queryGroupCount(configStrategyQuery);
		if (count > 0) {
			throw new BusinessCommonException(DeviceErrorCode.CONFIG_STRATEGY_NAME_DUPLICATE);
		}
		ConfigStrategyGroup configStrategyGroup = new ConfigStrategyGroup();
		configStrategyGroup.setStrategyName(configStrategyGroupRequest.getStrategyName());
		configStrategyGroup.setCreatedBy(RequestHeaderUtil.getUserId());
		configStrategyGroup.setOrganizationId(RequestHeaderUtil.getOrgId());
		configStrategyRepository.createGroup(configStrategyGroup);
		Integer groupId = configStrategyGroup.getId();
		List<ConfigStrategy> configStrategyList = new ArrayList<>();
		configStrategyGroupRequest.getDeviceList().forEach(device ->
				configStrategyGroupRequest.getStrategyList().forEach(strategy -> {
					ConfigStrategy configStrategy = new ConfigStrategy();
					configStrategy.setDeviceId(device.getId());
					configStrategy.setStrategyId(groupId);
					configStrategy.setConfigFileCode(strategy.getConfigFileCode());
					configStrategy.setConfigFileName(strategy.getConfigFileName());
					configStrategy.setConfigUrl(strategy.getConfigUrl());
					configStrategy.setStatus(0);
					configStrategyList.add(configStrategy);
				})
		);
		configStrategyRepository.batchCreate(configStrategyList);
		ConfigStrategyTask configStrategyTask = new ConfigStrategyTask();
		configStrategyTask.setConfigStrategyGroupRequest(configStrategyGroupRequest);
		taskExecutor.getExecutorService().submit(configStrategyTask);
	}
	
	/**
	 * @param configStrategyQueryRequest
	 * @return
	 */
	public List<ConfigStrategyGroupResponse> getGroupList(ConfigStrategyQueryRequest configStrategyQueryRequest) {
		List<ConfigStrategyGroupResponse> result = new ArrayList<>();
		List<ConfigStrategyGroup> poList = configStrategyRepository.queryGroupList(BeanUtil.parse(configStrategyQueryRequest, ConfigStrategyQuery.class));
		poList.forEach(po -> {
			ConfigStrategyGroupResponse response = new ConfigStrategyGroupResponse();
			BeanUtils.copyProperties(po, response);
			result.add(response);
		});
		return result;
	}
	
	/**
	 * @param configStrategyQueryRequest
	 * @return
	 */
	public Integer queryGroupCount(ConfigStrategyQueryRequest configStrategyQueryRequest) {
		return configStrategyRepository.queryGroupCount(BeanUtil.parse(configStrategyQueryRequest, ConfigStrategyQuery.class));
	}
	
	/**
	 * @param strategyId
	 * @return
	 */
	public ConfigStrategyDetailResponse getDetail(Integer strategyId) {
		ConfigStrategyQuery configStrategyQuery = new ConfigStrategyQuery();
		configStrategyQuery.setStrategyId(strategyId);
		List<ConfigStrategy> configStrategies = configStrategyRepository.queryByStrategyId(strategyId);
		
		if (configStrategies.isEmpty()) {
			throw new BusinessCommonException(DeviceErrorCode.CONFIG_STRATEGY_NOT_FOUNT);
		}
		
		Map<String, ConfigStrategy> map = configStrategies.stream().collect(Collectors.toMap(ConfigStrategy::getConfigFileCode,
				ConfigStrategy -> ConfigStrategy, (oldValue, newValue) -> oldValue));
		
		List<Integer> deviceIds = configStrategies.stream().map(ConfigStrategy::getDeviceId).collect(Collectors.toList());
		DeviceQuery deviceQuery = new DeviceQuery();
		deviceQuery.setIds(deviceIds);
		deviceQuery.setIsPage(false);
		List<Device> devices = deviceRepository.getList(deviceQuery);
		List<DeviceResponse> deviceResponses = BeanUtil.parseList(devices, DeviceResponse.class);
		List<ConfigStrategyResponse> configStrategyResponses = BeanUtil.parseList(new ArrayList<>(map.values()), ConfigStrategyResponse.class);
		return new ConfigStrategyDetailResponse(configStrategyResponses, deviceResponses);
	}
	
	/**
	 * @param sn
	 * @return
	 */
	public DeviceConfigResponse queryConfig(String sn) {
		DeviceConfigResponse deviceMediaResponse = new DeviceConfigResponse();
		List<DeviceConfig> deviceConfigs = deviceConfigMapWithSn.get(sn);

		//SN没有找到，尝试使用MAC
		if(null == deviceConfigs) {
			deviceConfigs = deviceConfigMap.get(sn);
		}

		if (null != deviceConfigs) {
			deviceMediaResponse.setConfig(deviceConfigs);
			deviceMediaResponse.setSt(0);
			deviceMediaResponse.setMsg("success");
		} else {
			deviceMediaResponse.setSt(-999);
			deviceMediaResponse.setMsg("查无此设备");
		}
		return deviceMediaResponse;
	}
	
	
}
