package com.bb.service;

import com.bb.jwt.JwtManager;
import com.bb.model.Game;
import com.bb.model.PlayParam;
import com.bb.model.Site;
import com.bb.util.StringUtils;


import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;
import org.springframework.web.reactive.function.client.WebClientRequestException;



import java.math.BigDecimal;
import java.util.*;



@Slf4j
@EnableScheduling
@RequiredArgsConstructor
@Service
public class PragmaticServiceImpl implements PragmaticService {

	
	@Autowired
	WebClient webClient;


	@Override
	public String getLaunchUrl(String LOG_PREFIX, String token, HashMap venderInfo, PlayParam param, String hexMemberId) throws Exception {
		 String gameUrl = venderInfo.get("vendorApiUrl").toString()+"/IntegrationService/v3/http/CasinoGameAPI/game/url/";

	        //body
	        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
	        String language = param.getLanguage();
	        if(language == null || language.isEmpty()) {
	            language = "en";
	        } else {
	            language = language.toLowerCase();
	            if(language.equals("kr")) {
	                language = "en";
	            }
	        }

	      //  String currency = venderInfo.get("currency").toString();
	        parameters.add("currency", "VND");
	        parameters.add("language", language);
	        parameters.add("secureLogin", venderInfo.get("vendorApiId").toString());
	        parameters.add("externalPlayerId", hexMemberId);
	        parameters.add("symbol", param.getGameKey());
	        parameters.add("token", hexMemberId);

	        // hash
	        String hashString = "currency="+"VND"
	                + "&externalPlayerId="+hexMemberId
	                + "&language="+language
	                + "&secureLogin="+ venderInfo.get("vendorApiId").toString()
	                + "&symbol="+param.getGameKey()
	                + "&token="+hexMemberId;

	        log.info(LOG_PREFIX+ "Pragmatic hash string:{}", hashString);
	        parameters.add("hash", StringUtils.md5AndHex(hashString+ venderInfo.get("vendorApiKey").toString()));
	        log.info(LOG_PREFIX+ "org_pragmatic_gameUrl parameters:{}", parameters.toString());
	        //header
	        HttpHeaders header = new HttpHeaders();
	        header.add("Content-Type", "application/x-www-form-urlencoded");

	        try {
	            String responseBody = webClient.post()
	                    .uri(gameUrl)
	                    .headers(h -> h.addAll(header))
	                    .bodyValue(parameters)
	                    .retrieve()
	                    .bodyToMono(String.class)
	                    .block();
	            
	            JSONObject resdata = new JSONObject(responseBody);
	            log.info(LOG_PREFIX+ "org_pragmatic_gameUrl res:{}", resdata.toString());
	            
	            return resdata.get("gameURL").toString();
	        } catch(WebClientResponseException e) {
	        	log.error(LOG_PREFIX+ "getLaunchUrl HttpClientErrorException : " + e.getMessage());
	        	log.error(LOG_PREFIX+ "getLaunchUrl status code : " + e.getStatusCode().value());
	        	log.error(LOG_PREFIX+ "getLaunchUrl response body : " + e.getResponseBodyAsString());
	        	throw e;
	        } catch(WebClientRequestException rae) {
	        	if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
	        		log.error(LOG_PREFIX+ "getLaunchUrl ConnectTimeoutException::"+rae.getMessage());
	        	}
	        	if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
	        		log.error(LOG_PREFIX+ "getLaunchUrl SocketTimeoutException::"+rae.getMessage());
	        	}
	        	if(rae.getCause() instanceof InterruptedException) {
	        		log.error(LOG_PREFIX+ "getLaunchUrl InterruptedException::"+rae.getMessage());
	        	}
	        	throw rae;
	        }
	}


	@Override
	public List<Game> getGameList(String LOG_PREFIX, HashMap venderInfo) throws Exception{
		String apiUrl = venderInfo.get("vendorApiUrl").toString()+"/IntegrationService/v3/http/CasinoGameAPI/getCasinoGames";
		MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
		parameters.add("secureLogin", venderInfo.get("vendorApiId").toString());
		List<Game> gameList = null;
		
		log.info(LOG_PREFIX+ "apiUrl:"+apiUrl);
		String hashString = "secureLogin="+ venderInfo.get("vendorApiId").toString();
		log.info(hashString);
		String hash = StringUtils.md5AndHex(hashString+ venderInfo.get("vendorApiKey").toString());
		parameters.add("hash", hash);
		log.info(LOG_PREFIX+ "hash:"+hash);
	        //header
        HttpHeaders header = new HttpHeaders();
        header.add("Content-Type", "application/x-www-form-urlencoded");

        try {
            String responseBody = webClient.post()
                    .uri(apiUrl)
                    .headers(h -> h.addAll(header))
                    .bodyValue(parameters)
                    .retrieve()
                    .bodyToMono(String.class)
                    .block();
            
            log.info(LOG_PREFIX+ "res"+ responseBody);
            JSONObject resdata = new JSONObject(responseBody);
            log.info(LOG_PREFIX+ resdata.toString());
            JSONArray games = resdata.getJSONArray("gameList");
            int length = games.length();
            gameList = new ArrayList<>();
            
            for(int i=0; i<length; i++) {
                Game game = new Game();
                JSONObject objGame = games.getJSONObject(i);
                
                if(venderInfo.get("vendorCode").toString().contains("org_pragmatic_slot")) {    
                     
                     if(objGame.getString("gameID").startsWith("vs") || objGame.getString("gameID").startsWith("cs")) {
                                //log.info(objGame.toString());
                        game.setGameIdx(i+1);
                        game.setGameKey(objGame.getString("gameID"));
                        game.setGameName(objGame.getString("gameName"));
                        game.setGameNameEn(objGame.getString("gameName"));            
                        game.setGameImg("https://common-static.ppgames.net/gs2c/common/lobby/v1/apps/slots-lobby-assets/"+objGame.getString("gameID")+"/"+objGame.getString("gameID")+"_200x200_B.png");
                        game.setGameType("slot");
                        gameList.add(game);
                    }
                //}
                }else if(venderInfo.get("vendorCode").toString().contains("org_pragmatic_casino")) {    
                    //if("slot".equals(type.toLowerCase())) {
                    //log.info(objGame.toString());
                    if(!(objGame.getString("gameID").startsWith("vs") || objGame.getString("gameID").startsWith("cs"))) {
                        game.setGameIdx(i+1);
                        game.setGameKey(objGame.getString("gameID"));
                        game.setGameName(objGame.getString("gameName"));
                        game.setGameNameEn(objGame.getString("gameName"));            
                        game.setGameImg("https://common-static.ppgames.net/gs2c/common/lobby/v1/apps/slots-lobby-assets/"+objGame.getString("gameID")+"/"+objGame.getString("gameID")+"_200x200_B.png");
                        game.setGameType("casino");
                        gameList.add(game);
                     }
                }
            }
            
            return gameList;
        } catch(WebClientResponseException e) {
        	log.error(LOG_PREFIX+ "getGameList HttpClientErrorException : " + e.getMessage());
        	log.error(LOG_PREFIX+ "getGameList status code : " + e.getStatusCode().value());
        	log.error(LOG_PREFIX+ "getGameList response body : " + e.getResponseBodyAsString());
        	throw e;
        } catch(WebClientRequestException rae) {
        	if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
        		log.error(LOG_PREFIX+ "getGameList ConnectTimeoutException::"+rae.getMessage());
        	}
        	if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
        		log.error(LOG_PREFIX+ "getGameList SocketTimeoutException::"+rae.getMessage());
        	}
        	if(rae.getCause() instanceof InterruptedException) {
        		log.error(LOG_PREFIX+ "getGameList InterruptedException::"+rae.getMessage());
        	}
        	throw rae;
        }
	}


	@Override
	public String getDetails(String LOG_PREFIX, HashMap betInfo) {
		try {
            String historyUrl = betInfo.get("vendorApiUrl").toString() + "/IntegrationService/v3/http/HistoryAPI/OpenHistoryExtended/";
            String siteIdxStr = betInfo.get("siteHex").toString();
            String playerId = siteIdxStr.toUpperCase() + betInfo.get("memberId").toString();
            String refId = betInfo.get("refId").toString();
            String roundId = refId.replaceAll(betInfo.get("siteId").toString(), "");
            //body
	        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
	       
	
	        parameters.add("secureLogin", betInfo.get("vendorApiId").toString());
	        parameters.add("playerId", playerId);
	        parameters.add("gameId", betInfo.get("gameIdx").toString());
	        parameters.add("roundId", roundId);

	        // hash
	        String hashString = "secureLogin="+ betInfo.get("vendorApiId").toString()
	                + "&playerId="+playerId
	                + "&gameId="+betInfo.get("gameIdx").toString()
	                + "&roundId="+ roundId;

	        log.info("Pragmatic hash string:{}", hashString);
	        parameters.add("hash", StringUtils.md5AndHex(hashString+ betInfo.get("vendorApiKey").toString()));
	        //header
	        
	        HttpHeaders header = new HttpHeaders();
	        header.add("Content-Type", "application/x-www-form-urlencoded");

	        try {
	            String responseBody = webClient.post()
	                    .uri(historyUrl)
	                    .headers(h -> h.addAll(header))
	                    .bodyValue(parameters)
	                    .retrieve()
	                    .bodyToMono(String.class)
	                    .block();
	            
	            JSONObject resdata = new JSONObject(responseBody);
	            
                if(resdata != null) {
                    return resdata.getString("url");
                } else {
                    return "";
                }
	        } catch(WebClientResponseException e) {
	        	log.error(LOG_PREFIX+ "getDetails HttpClientErrorException : " + e.getMessage());
	        	log.error(LOG_PREFIX+ "getDetails status code : " + e.getStatusCode().value());
	        	log.error(LOG_PREFIX+ "getDetails response body : " + e.getResponseBodyAsString());
	        	return "";
	        } catch(WebClientRequestException rae) {
	        	if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
	        		log.error(LOG_PREFIX+ "getDetails ConnectTimeoutException::"+rae.getMessage());
	        	}
	        	if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
	        		log.error(LOG_PREFIX+ "getDetails SocketTimeoutException::"+rae.getMessage());
	        	}
	        	if(rae.getCause() instanceof InterruptedException) {
	        		log.error(LOG_PREFIX+ "getDetails InterruptedException::"+rae.getMessage());
	        	}
	        	return "";
	        }
        } catch(Exception e) {
            log.error("OpenHistoryExtended Exception: ", e);
            return "";
        }
	} 
	
	
}
