package com.bb.service;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientRequestException;
import org.springframework.web.reactive.function.client.WebClientResponseException;

import com.bb.model.Game;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class ThenutServiceImpl implements ThenutService {
	
	@Autowired
	WebClient webClient;

	@Override
	public JSONObject getAgent(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		LOG_PREFIX = LOG_PREFIX + "getAgent::";
		JSONObject responseObj = null;
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
		headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
		String apiKey = "Bearer "+apiInfo.get("apiKey").toString();
		headers.set("Authorization", apiKey);
		
		String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/agent";
		log.info(LOG_PREFIX+ "apiUrl::"+apiUrl);
		
		try {
			ResponseEntity<String> resEntity = webClient.get()
														.uri(apiUrl)
														.headers(h -> h.addAll(headers))
														.retrieve()
														.toEntity(String.class)
														.block();
			if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) {
				responseObj = new JSONObject(resEntity.getBody());
				log.info(LOG_PREFIX+ "Response : " + responseObj.toString());
			}
		} catch (WebClientResponseException wce) {
			log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage());
			log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value());
			log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::"+e.getMessage());
			e.printStackTrace();
        }
		
		return responseObj;
	}

	@Override
	public JSONObject getUser(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		LOG_PREFIX = LOG_PREFIX + "getUser::";
		JSONObject responseObj = null;
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
		headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
		String apiKey = "Bearer "+apiInfo.get("apiKey").toString();
		headers.set("Authorization", apiKey);
		
		String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/user?";
		String param = "username="+apiInfo.get("apiUsername");
		apiUrl = apiUrl + param;
		log.info(LOG_PREFIX+ "apiUrl::"+apiUrl);
		
		try {
			ResponseEntity<String> resEntity = webClient.get()
														.uri(apiUrl)
														.headers(h -> h.addAll(headers))
														.retrieve()
														.toEntity(String.class)
														.block();
			if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) {
				responseObj = new JSONObject(resEntity.getBody());
				log.info(LOG_PREFIX+ "Response : " + responseObj.toString());
			}
		} catch (WebClientResponseException wce) {
			log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage());
			log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value());
			log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::"+e.getMessage());
			e.printStackTrace();
        }
		
		return responseObj;
	}

	@Override
	public JSONObject createUser(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		LOG_PREFIX = LOG_PREFIX + "createUser::";
		JSONObject responseObj = null;
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
		headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
		String apiKey = "Bearer "+apiInfo.get("apiKey").toString();
		headers.set("Authorization", apiKey);
		
		String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/user";
		
		try {
			JSONObject params = new JSONObject();
			params.put("username", apiInfo.get("apiUsername"));
			params.put("nickname", apiInfo.get("apiNickname"));
			log.info(LOG_PREFIX+ "apiUrl::"+apiUrl);
			log.info(LOG_PREFIX+ "params::"+params.toString());
			
			ResponseEntity<String> resEntity = webClient.post()
														.uri(apiUrl)
														.headers(h -> h.addAll(headers))
														.bodyValue(params.toString())
														.retrieve()
														.toEntity(String.class)
														.block();
			if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) {
				responseObj = new JSONObject(resEntity.getBody());
				log.info(LOG_PREFIX+ "Response : " + responseObj.toString());
			}
		} catch (WebClientResponseException wce) {
			log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage());
			log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value());
			log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::"+e.getMessage());
			e.printStackTrace();
        }
		
		return responseObj;
	}

	@Override
	public String createUserToken(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		LOG_PREFIX = LOG_PREFIX + "createUserToken::";
		String token = null;
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
		headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
		String apiKey = "Bearer "+apiInfo.get("apiKey").toString();
		headers.set("Authorization", apiKey);
		
		String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/user/token";
		
		try {
			JSONObject params = new JSONObject();
			params.put("vendorCode", apiInfo.get("apiVendor"));
			params.put("username", apiInfo.get("apiUsername"));
			log.info(LOG_PREFIX+ "apiUrl::"+apiUrl);
			log.info(LOG_PREFIX+ "params::"+params.toString());
			
			ResponseEntity<String> resEntity = webClient.patch()
														.uri(apiUrl)
														.headers(h -> h.addAll(headers))
														.bodyValue(params.toString())
														.retrieve()
														.toEntity(String.class)
														.block();
			if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) {
				JSONObject responseObj = new JSONObject(resEntity.getBody());
				log.info(LOG_PREFIX+ "Response : " + responseObj.toString());
				token = responseObj.getString("token");
			}
		} catch (WebClientResponseException wce) {
			log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage());
			log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value());
			log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::"+e.getMessage());
			e.printStackTrace();
        }
		
		return token;
	}

	@Override
	public List<Game> getGameList(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		LOG_PREFIX = LOG_PREFIX + "getGameList::";
		List<Game> gameList = null;
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
		headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
		String apiKey = "Bearer "+apiInfo.get("apiKey").toString();
		headers.set("Authorization", apiKey);
		
		String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/game?";
		String param = "vendorCode="+apiInfo.get("apiVendor");
		apiUrl = apiUrl + param;
		log.info(LOG_PREFIX+ "apiUrl::"+apiUrl);
		
		try {
			ResponseEntity<String> resEntity = webClient.get()
														.uri(apiUrl)
														.headers(h -> h.addAll(headers))
														.retrieve()
														.toEntity(String.class)
														.block();
			if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) {
				JSONArray jsonArr  = new JSONArray(resEntity.getBody());
				int length = jsonArr.length();
				gameList = new ArrayList<>();
				
				for(int i=0; i<length; i++) {
					Game game = new Game();
					JSONObject objGame = jsonArr.getJSONObject(i);
					game.setGameIdx(i);
					game.setGameKey(objGame.getString("gameCode"));
					game.setGameName(objGame.getString("gameTitleKr"));
					game.setGameNameEn(objGame.getString("gameTitle"));
					game.setGameImg(objGame.getString("thumbnail"));
					gameList.add(game);
				}
			}
		} catch (WebClientResponseException wce) {
			log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage());
			log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value());
			log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::"+e.getMessage());
			e.printStackTrace();
        }
		
		return gameList;
	}

	@Override
	public String getGameUrl(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		LOG_PREFIX = LOG_PREFIX + "getGameUrl::";
		String gameUrl = null;
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
		headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
		String apiKey = "Bearer "+apiInfo.get("apiKey").toString();
		headers.set("Authorization", apiKey);
		
		String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/game/url?";
		String param = "gameCode="+apiInfo.get("apiGameCode")+"&vendorCode="+apiInfo.get("apiVendor")
		+"&token="+apiInfo.get("apiUserToken");
		apiUrl = apiUrl + param;
		log.info(LOG_PREFIX+ "apiUrl::"+apiUrl);
		
		try {
			ResponseEntity<String> resEntity = webClient.get()
														.uri(apiUrl)
														.headers(h -> h.addAll(headers))
														.retrieve()
														.toEntity(String.class)
														.block();
			if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) {
				JSONObject responseObj = new JSONObject(resEntity.getBody());
				log.info(LOG_PREFIX+ "Response : " + responseObj.toString());
				gameUrl = responseObj.getString("url");
			}
		} catch (WebClientResponseException wce) {
			log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage());
			log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value());
			log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::"+e.getMessage());
			e.printStackTrace();
        }
		
		return gameUrl;
	}

	@Override
	public JSONObject getBetDetail(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		LOG_PREFIX = LOG_PREFIX + "getBetDetail::";
		JSONObject detailObj = null;
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
		headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
		String apiKey = "Bearer "+apiInfo.get("apiKey").toString();
		headers.set("Authorization", apiKey);
		
		String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/bet/"+apiInfo.get("betId")+"/result";
		log.info(LOG_PREFIX+ "apiUrl::"+apiUrl);
		
		try {
			ResponseEntity<String> resEntity = webClient.get()
														.uri(apiUrl)
														.headers(h -> h.addAll(headers))
														.retrieve()
														.toEntity(String.class)
														.block();
			if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) {
				JSONObject responseObj = new JSONObject(resEntity.getBody());
				String value = responseObj.getString("value");
				JSONObject valueObj = new JSONObject(value);
				detailObj = valueObj.optJSONObject("detail").optJSONObject("data");
				log.info(LOG_PREFIX+ "Detail Obj : " + detailObj.toString());
			}
		} catch (WebClientResponseException wce) {
			log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage());
			log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value());
			log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::"+e.getMessage());
			e.printStackTrace();
        }
		
		return detailObj;
	}

	@Override
	public String getBetDetailUrl(String LOG_PREFIX, HashMap<String, String> apiInfo) {
		LOG_PREFIX = LOG_PREFIX + "getBetDetailUrl::";
		String detailUrl = null;
		
		HttpHeaders headers = new HttpHeaders();
		headers.setContentType(MediaType.APPLICATION_JSON);
		headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
		headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
		String apiKey = "Bearer "+apiInfo.get("apiKey").toString();
		headers.set("Authorization", apiKey);
		
		String apiUrl = apiInfo.get("apiBaseUrl").toString() + "/bet/"+apiInfo.get("betId")+"/result/url";
		log.info(LOG_PREFIX+ "apiUrl::"+apiUrl);
		
		try {
			ResponseEntity<String> resEntity = webClient.get()
														.uri(apiUrl)
														.headers(h -> h.addAll(headers))
														.retrieve()
														.toEntity(String.class)
														.block();
			if(resEntity != null && resEntity.getStatusCode() == HttpStatus.OK) {
				JSONObject responseObj = new JSONObject(resEntity.getBody());
				detailUrl = responseObj.getString("value");
				log.info(LOG_PREFIX+ "Detail Url : " + detailUrl);
			}
		} catch (WebClientResponseException wce) {
			log.error(LOG_PREFIX+ "WebClientResponseException::"+wce.getMessage());
			log.error(LOG_PREFIX+ "status code::"+wce.getStatusCode().value());
			log.error(LOG_PREFIX+ "response body::"+wce.getResponseBodyAsString());
		} catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "ConnectTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
            	log.error(LOG_PREFIX+ "SocketTimeoutException::"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "InterruptedException::"+rae.getMessage());
            }
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::"+e.getMessage());
			e.printStackTrace();
        }
		
		return detailUrl;
	}

}
