package com.eactive.eai.rms.onl.manage.inflow.inflow;

import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import com.eactive.eai.data.entity.onl.inflow.InflowControl;
import com.eactive.eai.data.entity.onl.inflow.InflowControlId;
import com.eactive.eai.rms.common.base.BaseService;
import com.eactive.eai.rms.common.combo.ComboService;
import com.eactive.eai.rms.data.entity.onl.inflow.InflowControlService;
import com.eactive.eai.rms.data.entity.onl.inflow.InflowControlServiceDto;
import com.eactive.eai.rms.onl.common.service.EaiServerInfoService;

@Service
public class InflowControlManService extends BaseService {

	private static final Logger logger = LoggerFactory.getLogger(InflowControlManService.class);

	private static final String ADAPTER_TYPE_INFLOW = "01";
	private static final String INTERFACE_TYPE_INFLOW = "02";
	private static final String CLIENT_TYPE_INFLOW = "03";

	@Autowired
	@Qualifier("comboService")
	public ComboService comboService;

	@Autowired
	private InflowControlService service;

	@Autowired
	private InflowControlManMapper mapper;

	@Autowired
	private EaiServerInfoService eaiServerInfoService;

	private RestTemplate restTemplate = new RestTemplate();

	// 어댑터 유량제어
	public Page<InflowControlManUI> selectAdapterList(Pageable pageable, String searchName, String searchUseYn) {
		Page<InflowControlServiceDto> dtoList = service.findAllForAdapter(pageable, searchName, searchUseYn);
		return dtoList.map(mapper::toVo);
	}

	public InflowControlManUI selectAdapterDetail(String name) {
		InflowControlServiceDto dto = service.findByIdForAdapter(name);
		return mapper.toVo(dto);
	}

	public void mergeAdapter(InflowControlManUI ui) {
		ui.setType(ADAPTER_TYPE_INFLOW);
		InflowControlId id = toId(ui);
		Optional<InflowControl> inflowControlOptional = service.findById(id);

		InflowControl entity = null;
		if (inflowControlOptional.isPresent()) {
			entity = inflowControlOptional.get();
			mapper.updateToEntity(ui, entity);
		} else {
			entity = mapper.toEntity(ui);
		}
		if (entity.getThreshold() == null || StringUtils.isEmpty(entity.getThresholdtimeunit())) {
			entity.setThreshold(0);
		}
		service.save(entity);
	}

	public void deleteAdater(String name) {
		InflowControlId id = toId(ADAPTER_TYPE_INFLOW, name);
		service.deleteById(id);
	}
	
	// 인터페이스 유량제어
	public Page<InflowControlManUI> selectInterfaceList(Pageable pageable, String searchName, String searchUseYn) {
		Page<InflowControlServiceDto> dtoList = service.findAllForInterface(pageable, searchName, searchUseYn);
		return dtoList.map(mapper::toVo);
	}

	public InflowControlManUI selectInterfaceDetail(String name) {
		return mapper.toVo(service.findByIdForInterface(name));
	}

	public void mergeInterface(InflowControlManUI ui) {
		ui.setType(INTERFACE_TYPE_INFLOW);
		InflowControlId id = toId(ui);
		Optional<InflowControl> inflowControlOptional = service.findById(id);

		InflowControl entity = null;
		if (inflowControlOptional.isPresent()) {
			entity = inflowControlOptional.get();
			mapper.updateToEntity(ui, entity);
		} else {
			entity = mapper.toEntity(ui);
		}
		if (entity.getThreshold() == null || StringUtils.isEmpty(entity.getThresholdtimeunit())) {
			entity.setThreshold(0);
		}
		service.save(entity);
	}

	public void deleteInterface(String name) {
		InflowControlId id = toId(INTERFACE_TYPE_INFLOW, name);
		service.deleteById(id);
	}
	
	
	// 클라이언트 유량제어
	public Page<InflowControlManUI> selectClientList(Pageable pageable, String searchName, String searchUseYn) {
		Page<InflowControlServiceDto> dtoList = service.findAllForClient(pageable, searchName, searchUseYn);
		return dtoList.map(mapper::toVo);
	}

	public InflowControlManUI selectClientDetail(String name) {
		return mapper.toVo(service.findByIdForClient(name));
	}

	public void mergeClient(InflowControlManUI ui) {
		ui.setType(CLIENT_TYPE_INFLOW);
		InflowControlId id = toId(ui);
		Optional<InflowControl> inflowControlOptional = service.findById(id);

		InflowControl entity = null;
		if (inflowControlOptional.isPresent()) {
			entity = inflowControlOptional.get();
			mapper.updateToEntity(ui, entity);
		} else {
			entity = mapper.toEntity(ui);
		}
		if (entity.getThreshold() == null || StringUtils.isEmpty(entity.getThresholdtimeunit())) {
			entity.setThreshold(0);
		}
		service.save(entity);
	}

	public void deleteClient(String name) {
		InflowControlId id = toId(CLIENT_TYPE_INFLOW, name);
		service.findById(id).ifPresent(service::delete);
	}

	@SuppressWarnings("unchecked")
	public List<Map<String, Object>> getClientBucketStatus(String clientId) {
		return getBucketStatus("client", clientId, "클라이언트가 로드되지 않음", "클라이언트 버킷 상태 조회 실패");
	}

	@SuppressWarnings("unchecked")
	public List<Map<String, Object>> getAdapterBucketStatus(String adapterId) {
		return getBucketStatus("adapter", adapterId, "어댑터가 로드되지 않음", "어댑터 버킷 상태 조회 실패");
	}

	@SuppressWarnings("unchecked")
	public List<Map<String, Object>> getInterfaceBucketStatus(String interfaceId) {
		return getBucketStatus("interface", interfaceId, "인터페이스가 로드되지 않음", "인터페이스 버킷 상태 조회 실패");
	}

	@SuppressWarnings("unchecked")
	private List<Map<String, Object>> getBucketStatus(String target, String targetId, String noDataMessage, String logPrefix) {
		List<Map<String, Object>> result = new ArrayList<>();
		List<Map<String, String>> serverList = eaiServerInfoService.getEaiServerIpList();

		for (Map<String, String> server : serverList) {
			String serverName = server.get("EAISVRINSTNM");
			String serverIp = server.get("EAISVRIP");
			String serverPort = server.get("EAISVRLSNPORT");

			Map<String, Object> serverStatus = new HashMap<>();
			serverStatus.put("serverName", serverName);
			serverStatus.put("serverIp", serverIp);
			serverStatus.put("serverPort", serverPort);

			try {
				URI uri = UriComponentsBuilder.fromHttpUrl(String.format("http://%s:%s/manage/inflow", serverIp, serverPort))
						.pathSegment(target, targetId, "bucket-status")
						.build()
						.encode()
						.toUri();
				ResponseEntity<Map> response = restTemplate.getForEntity(uri, Map.class);

				if (response.getBody() != null && Boolean.TRUE.equals(response.getBody().get("success"))) {
					serverStatus.put("status", "online");
					serverStatus.put("data", response.getBody().get("data"));
				} else {
					serverStatus.put("status", "no_data");
					serverStatus.put("message", noDataMessage);
				}
			} catch (Exception e) {
				logger.warn("{} - server: {}, error: {}", logPrefix, serverName, e.getMessage());
				serverStatus.put("status", "offline");
				serverStatus.put("message", "서버 연결 실패");
			}

			result.add(serverStatus);
		}

		return result;
	}
		
	
	private InflowControlId toId(InflowControlManUI ui) {
		return toId(ui.getType(), ui.getName());
	}
	
	private InflowControlId toId(String type, String name) {
		InflowControlId id = new InflowControlId();
		id.setType(type);
		id.setName(name);
		return id;
	}
	
}
