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

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.neusoft.smart.pos.dto.device.request.DeviceQueryRequest;
import com.neusoft.smart.pos.dto.device.request.DeviceRequest;
import com.neusoft.smart.pos.dto.device.request.DeviceStatusRequest;
import com.neusoft.smart.pos.dto.device.request.DeviceStoreRequest;
import com.neusoft.smart.pos.dto.device.response.DeviceResponse;
import com.neusoft.smart.pos.dto.org.request.PutOrgRequest;
import com.neusoft.smart.pos.dto.org.request.PutShopRequest;
import com.neusoft.smart.pos.dto.ota.response.UpgradeHistoryExtResponse;
import com.neusoft.smart.pos.framework.bean.PaginationExtendBean;
import com.neusoft.smart.pos.framework.dto.ResponseData;
import com.neusoft.smart.pos.gateway.service.feignService.RemoteDeviceService;
import com.neusoft.smart.pos.gateway.service.feignService.RemoteOTAService;
import com.neusoft.smart.pos.gateway.service.feignService.RemoteOrgService;
import com.neusoft.smart.pos.gateway.service.feignService.RemoteShopService;
import com.neusoft.smart.pos.redis.bean.DeviceVersionList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toMap;

@Service
public class DeviceService {
	
	@Autowired
	private RemoteDeviceService remoteDeviceService;
	
	@Autowired
	private RemoteOTAService remoteOTAService;
	
	@Autowired
	private RemoteOrgService remoteOrgService;
	
	@Autowired
	private RemoteShopService remoteShopService;
	
	@Autowired
	private RedisTemplate redisTemplate;
	
	/**
	 * @param deviceQueryRequest
	 * @return
	 */
	public PaginationExtendBean<?> queryDeviceStatus(DeviceQueryRequest deviceQueryRequest) {
		PaginationExtendBean<DeviceResponse> devicePage = remoteDeviceService.fetchList(deviceQueryRequest).getResult();
		List<DeviceResponse> devices = devicePage.getRows();
		List<Integer> deviceIds = devices.stream().map(DeviceResponse::getId).collect(Collectors.toList());
		List<UpgradeHistoryExtResponse> upgradeHistoryExtResponses = remoteOTAService.getLastUpdateTime(deviceIds).getResult();
		JSONArray jsonArray = (JSONArray) JSONArray.toJSON(devices);
		if (null != upgradeHistoryExtResponses) {
			Map<Integer, Date> map =
					upgradeHistoryExtResponses.stream().collect(toMap(UpgradeHistoryExtResponse::getDeviceId,
							UpgradeHistoryExtResponse::getLastUpdateTime));
			
			jsonArray.forEach(device -> {
				JSONObject jsonObject = (JSONObject) device;
				Date lastUpdateTime = map.getOrDefault(jsonObject.getInteger("id"), null);
				jsonObject.put("lastUpdateTime", lastUpdateTime);
			});
		}
		
		PaginationExtendBean paginationExtendBean = new PaginationExtendBean<>();
		paginationExtendBean.setTotal(devicePage.getTotal());
		paginationExtendBean.setRows(jsonArray);
		return paginationExtendBean;
	}
	
	
	public ResponseData<DeviceResponse> create(DeviceRequest deviceRequest) {
		ResponseData<DeviceResponse> responseData = remoteDeviceService.create(deviceRequest);
		this.updateOrgPOSCount(null);
		if (null != deviceRequest.getStoreId()) {
			this.updateStorePosCount(deviceRequest.getStoreId());
		}
		return responseData;
	}
	
	public ResponseData<?> update(DeviceRequest deviceRequest) {
		BoundHashOperations<String, String, DeviceVersionList> deviceHashWithSn = redisTemplate.boundHashOps("deviceVersionsMapWithSn");
		DeviceVersionList deviceVersionList = deviceHashWithSn.get(deviceRequest.getSerialNo());
		ResponseData<?> responseData = remoteDeviceService.update(deviceRequest);
		this.updateStorePosCount(deviceRequest.getStoreId());
        if (null != deviceVersionList && null != deviceVersionList.getDeviceInfo().getStoreId() &&
                !deviceVersionList.getDeviceInfo().getStoreId().equals(deviceRequest.getStoreId())) {
            this.updateStorePosCount(deviceVersionList.getDeviceInfo().getStoreId());
        }
		return responseData;
	}
	
	public ResponseData<List<DeviceResponse>> createByBatch(List<DeviceRequest> deviceRequestList) {
		ResponseData<List<DeviceResponse>> responseData = remoteDeviceService.createByBatch(deviceRequestList);
		this.updateOrgPOSCount(null);
		Integer storeId = 0;
		if (!deviceRequestList.isEmpty() && (storeId = deviceRequestList.get(0).getStoreId()) != null) {
			this.updateStorePosCount(storeId);
		}
		return responseData;
	}
	
	public ResponseData<DeviceResponse> updateStore(DeviceStoreRequest deviceStoreRequest) {
		ResponseData<DeviceResponse> responseData = remoteDeviceService.updateStore(deviceStoreRequest);
		this.updateStorePosCount(deviceStoreRequest.getStoreId());
		this.updateOrgPOSCount(null);
		return responseData;
	}
	
	public ResponseData<?> updateStatus(DeviceStatusRequest deviceStatusRequest) {
		ResponseData<Pair<List<Integer>, List<Integer>>> responseData = remoteDeviceService.updateStatus(deviceStatusRequest);
		if (!"200".equals(responseData.getCode())) {
			return responseData;
		}
		List<Integer> orgIds = responseData.getResult().getFirst();
		List<Integer> storeIds = responseData.getResult().getSecond();
		orgIds.forEach(this::updateOrgPOSCount);
		storeIds.forEach(this::updateStorePosCount);
		return new ResponseData<>();
	}
	
	private void updateStorePosCount(Integer storeId) {
		DeviceQueryRequest deviceQueryRequest = new DeviceQueryRequest();
		deviceQueryRequest.setStoreIds(Collections.singletonList(storeId));
		deviceQueryRequest.setLimit(1);
		PaginationExtendBean<DeviceResponse> devicePage = remoteDeviceService.fetchList(deviceQueryRequest).getResult();
		PutShopRequest putShopRequest = new PutShopRequest();
		putShopRequest.setId(storeId);
		putShopRequest.setPosnum(devicePage.getTotal());
		remoteShopService.shopUpdate(putShopRequest);
	}
	
	private void updateOrgPOSCount(Integer orgId) {
		DeviceQueryRequest deviceQueryRequest = new DeviceQueryRequest();
		deviceQueryRequest.setLimit(1);
		if (null != orgId) {
			deviceQueryRequest.setOrganizationId(orgId);
		}
		deviceQueryRequest.setIsStoreUserQueryWithoutStoreId(true);
		PaginationExtendBean<DeviceResponse> devicePage = remoteDeviceService.fetchList(deviceQueryRequest).getResult();
		if (devicePage.getTotal() != 0) {
			PutOrgRequest putOrgRequest = new PutOrgRequest();
			putOrgRequest.setId(devicePage.getRows().get(0).getOrganizationId());
			putOrgRequest.setPosnum(devicePage.getTotal());
			remoteOrgService.orgUpdate(putOrgRequest);
		}
	}
	
	public JSONObject queryConfig(String sn) {
		return remoteDeviceService.queryConfig(sn);
	}
}
