package com.bb.front;

import java.util.HashMap;
import java.util.Random;

import jakarta.servlet.http.HttpServletRequest;

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.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
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.jwt.JwtManager;
import com.bb.model.ApiResponse;
import com.bb.model.AuthParam;
import com.bb.model.CheckVo;
import com.bb.model.CommonParam;
import com.bb.model.EvoResponse;
import com.bb.model.EvolutionVo;
import com.bb.model.Member;
import com.bb.model.PlayParam;
import com.bb.service.SiteService;

import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@RestController
@Slf4j
@RequestMapping("/api/callback/evot")
@RequiredArgsConstructor
@SecurityRequirement(name = "Authorization")
public class CallBackBetGambleController {

	@Autowired
	private final JwtManager jwtManager;

	@Autowired
	SiteService siteService;

	@Autowired
	WebClient webClient;



	@ResponseBody
	@RequestMapping(value="/test")
	public EvoResponse test(HttpServletRequest request, @RequestBody  EvolutionVo evo) throws Exception {
		EvoResponse evoResponse = new EvoResponse();
		  try {
			  log.debug(evo.toString());

			  JSONObject member = new JSONObject();
			  member.put("userId", "moka_gk01");

				log.info("# site.getSiteCbUrl() : " + "https://dev-api.allboxstage.com/triple/balance");
				log.info("# site.getSiteCbUrl() : " + member.toString());

				HttpHeaders header = new HttpHeaders();
				header.add("Content-Type", "application/json");
				header.add("Accept", "application/json");
				header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");

				ResponseEntity<String> responseEntity = null;
				try {
					responseEntity = webClient.post()
						.uri("https://dev-api.allboxstage.com/triple/balance")
						.headers(h -> h.addAll(header))
						.bodyValue(member.toString())
						.retrieve()
						.toEntity(String.class)
						.block();
				} catch(WebClientResponseException e) {
					log.error("test::HttpClientErrorException : " + e.getMessage());
					log.error("test::status code : " + e.getStatusCode().value());
					log.error("test::response body : " + e.getResponseBodyAsString());
					evoResponse.fail();
					return evoResponse;
				} catch (WebClientRequestException rae) {
		            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
		            	log.error("test::ConnectTimeoutException::" + rae.getMessage());
		            }
		            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
		            	log.error("test::SocketTimeoutException::" + rae.getMessage());
		            }
		            if(rae.getCause() instanceof InterruptedException) {
		            	log.error("test::InterruptedException::" + rae.getMessage());
		            }
		            log.error("test::WebClientRequestException : " + rae.getMessage());
		            evoResponse.fail();
		            return evoResponse;
				}

				if(responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
					log.info("status code : {}", responseEntity.getStatusCode());
					log.info("body: {}", responseEntity.getBody());

					JSONObject resData  = new JSONObject(responseEntity.getBody());

				   	if(resData.getInt("result_code") == 0) {
				  	  evoResponse.setUuid(evo.getUuid());
						  evoResponse.setBalance( resData.getDouble("balance"));
						  evoResponse.setBonus(0.0);
						  evoResponse.success();
				   	}else {
				   	 evoResponse.setBalance( resData.getDouble("balance"));
				   	 evoResponse.fail();
				   	}
				} else {
					log.error("test::Unexpected response status code");
					evoResponse.fail();
				}


	        } catch (Exception e) {
	        	log.info(e.toString());
	        	e.printStackTrace();
	        	evoResponse.fail();
	        }

	        return evoResponse;
	}


	@ResponseBody
	@RequestMapping(value="/")
	public ApiResponse main(HttpServletRequest request,  @RequestBody CheckVo check) throws Exception {
		  ApiResponse apiResponse = new ApiResponse();
		  try {



	        	apiResponse.success();

	        } catch (Exception e) {
	        	log.info(e.toString());
	        	e.printStackTrace();
	            apiResponse.fail();
	        }

	        return apiResponse;
	}

	@ResponseBody
	@RequestMapping(value={"/sid"})
	public EvoResponse sid(HttpServletRequest request, @RequestBody CheckVo check) throws Exception {
		EvoResponse evoResponse = new EvoResponse();
		  System.out.print("sid CHECK " + check.toString());
		  try {




				//사이트정보
			  HashMap sParam = new HashMap();
			  sParam.put("siteIdx",Integer.parseInt(check.getUserId().substring(0, 3), 16));
			  sParam.put("memberId", check.getUserId().substring(3, check.getUserId().length()));
			  String memberId =check.getUserId().substring(3, check.getUserId().length());

			  HashMap siteApiInfo = siteService.getSiteApiInfo(sParam);

			  AuthParam param = new AuthParam();
			  param.setBalance(0);
			  param.setUserId(memberId);
			  param.setNickName(check.getUserId());

			  CommonParam commonParam = new CommonParam();
			  commonParam.setSiteIdx(Integer.parseInt(siteApiInfo.get("siteIdx").toString()));
			  commonParam.setAuthParam(param);

			  System.out.print("CHECK " + check.toString());

			  Member member  = siteService.getMember(commonParam);

			  if(member == null) {
				  siteService.insertMember(commonParam);
				  member  = siteService.getMember(commonParam);
			  }

			 String sid = makeApiKey("");
			 member.setLastSid(sid);
			 siteService.updateSid(member);
			  evoResponse.setSid(sid);
			  evoResponse.setUuid(check.getUuid());
			  evoResponse.success();

	        } catch (Exception e) {
	        	log.info(e.toString());
	        	e.printStackTrace();
	        	evoResponse.fail();
	        }

	        return evoResponse;
	}

	@ResponseBody
	@RequestMapping(value={"/check"})
	public EvoResponse check(HttpServletRequest request, @RequestBody CheckVo check) throws Exception {
		EvoResponse evoResponse = new EvoResponse();
		  try {
			  System.out.print("check CHECK " + check.toString());

			  evoResponse.setSid(check.getSid());
			  evoResponse.setUuid(check.getUuid());


			//사이트정보
			  HashMap sParam = new HashMap();
			  sParam.put("siteIdx",Integer.parseInt(check.getUserId().substring(0, 3), 16));
			  sParam.put("memberId", check.getUserId().substring(3, check.getUserId().length()));
			  String memberId =check.getUserId().substring(3, check.getUserId().length());


			  HashMap siteApiInfo = siteService.getSiteApiInfo(sParam);

			  AuthParam param = new AuthParam();
			  param.setBalance(0);
			  param.setUserId(memberId);
			  param.setNickName(check.getUserId());

			  CommonParam commonParam = new CommonParam();
			  commonParam.setSiteIdx(Integer.parseInt(siteApiInfo.get("siteIdx").toString()));
			  commonParam.setAuthParam(param);

			  System.out.print("CHECK " + check.toString());

			  Member member  = siteService.getMember(commonParam);

			  // 회원 없을경우 가입시키기

			  if(member == null) {

				 System.out.print("CHECK INVALID_PARAMETER");

				  evoResponse.fail("INVALID_PARAMETER");
				  return evoResponse;
			  }

			  /*
			  if(!check.getSid().equals(member.getLastSid())) {
				  evoResponse.fail("INVALID_SID");
				  return evoResponse;
			  }
			  */

			  evoResponse.success();


	        } catch (Exception e) {
	        	log.info(e.toString());
	        	e.printStackTrace();
	        	evoResponse.fail();
	        }

	        return evoResponse;
	}


	@ResponseBody
	@RequestMapping(value="/balance")
	public EvoResponse balance(HttpServletRequest request, @RequestBody  EvolutionVo evo) throws Exception {
		EvoResponse evoResponse = new EvoResponse();
		  try {
			  log.debug(evo.toString());

			  //사이트정보
			  HashMap sParam = new HashMap();

			  sParam.put("siteIdx",Integer.parseInt(evo.getUserId().substring(0, 3), 16));
			  sParam.put("memberId", evo.getUserId().substring(3, evo.getUserId().length()));
			  String memberId =evo.getUserId().substring(3, evo.getUserId().length());
			  /*
			  AuthParam param = new AuthParam();
			  param.setBalance(0);
			  param.setUserId("moka_"+evo.getUserId());
			  param.setNickName(evo.getUserId());

			  CommonParam commonParam = new CommonParam();
			  commonParam.setSiteIdx(1);
			  commonParam.setAuthParam(param);

			  Member memberS  = siteService.getMember(commonParam);
			  if(!evo.getSid().equals(memberS.getLastSid())) {
				  evoResponse.fail("INVALID_SID");
				  return evoResponse;
			  }

			  */
			  HashMap siteApiInfo = siteService.getSiteApiInfo(sParam);

			  if(siteApiInfo==null) {

					 evoResponse.setBalance(null);
				   	 evoResponse.fail();
				   	 return evoResponse;
			  }

			  JSONObject member = new JSONObject();
			  member.put("userId", memberId);

				log.info("# site.getSiteCbUrl() : " + siteApiInfo.get("siteCbUrl")+"/balance");
				log.info("# site.getSiteCbUrl() : " + member.toString());

				HttpHeaders header = new HttpHeaders();
				header.add("Content-Type", "application/json");
				header.add("Accept", "application/json");
				header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");

				ResponseEntity<String> responseEntity = null;
				try {
					responseEntity = webClient.post()
						.uri(siteApiInfo.get("siteCbUrl")+"/balance")
						.headers(h -> h.addAll(header))
						.bodyValue(member.toString())
						.retrieve()
						.toEntity(String.class)
						.block();
				} catch(WebClientResponseException e) {
					log.error("balance::HttpClientErrorException : " + e.getMessage());
					log.error("balance::status code : " + e.getStatusCode().value());
					log.error("balance::response body : " + e.getResponseBodyAsString());
					evoResponse.setBalance(null);
					evoResponse.fail();
					return evoResponse;
				} catch (WebClientRequestException rae) {
		            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
		            	log.error("balance::ConnectTimeoutException::" + rae.getMessage());
		            }
		            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
		            	log.error("balance::SocketTimeoutException::" + rae.getMessage());
		            }
		            if(rae.getCause() instanceof InterruptedException) {
		            	log.error("balance::InterruptedException::" + rae.getMessage());
		            }
		            log.error("balance::WebClientRequestException : " + rae.getMessage());
		            evoResponse.setBalance(null);
		            evoResponse.fail();
		            return evoResponse;
				}

				if(responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
					log.info("status code : {}", responseEntity.getStatusCode());
					log.info("body: {}", responseEntity.getBody());

					JSONObject resData  = new JSONObject(responseEntity.getBody());

				   	if(resData.getInt("result_code") == 0) {
				  	  evoResponse.setUuid(evo.getUuid());
						  evoResponse.setBalance( resData.getDouble("balance"));
						  evoResponse.setBonus(0.0);
						  evoResponse.success();
				   	}else {
				   	 evoResponse.setBalance( resData.getDouble("balance"));
				   	 evoResponse.fail();
				   	}
				} else {
					log.error("balance::Unexpected response status code");
					evoResponse.setBalance(null);
					evoResponse.fail();
				}

	        } catch (Exception e) {
	        	log.info(e.toString());
	        	e.printStackTrace();
	        	evoResponse.fail();
	        }

	        return evoResponse;
	}


	@ResponseBody
	@RequestMapping(value="/debit")
	public EvoResponse debit (HttpServletRequest request, @RequestBody  EvolutionVo evo) throws Exception {
		EvoResponse evoResponse = new EvoResponse();

		  try {
			  log.debug(evo.toString());
			  //사이트정보
			  //사이트정보
			  HashMap sParam = new HashMap();

			  sParam.put("siteIdx",Integer.parseInt(evo.getUserId().substring(0, 3), 16));
			  sParam.put("memberId", evo.getUserId().substring(3, evo.getUserId().length()));
			  String memberId =evo.getUserId().substring(3, evo.getUserId().length());


			  /*
			  AuthParam param = new AuthParam();
			  param.setBalance(0);
			  param.setUserId("moka_"+evo.getUserId());
			  param.setNickName(evo.getUserId());

			  CommonParam commonParam = new CommonParam();
			  commonParam.setSiteIdx(1);
			  commonParam.setAuthParam(param);

			  Member memberS  = siteService.getMember(commonParam);
			  if(!evo.getSid().equals(memberS.getLastSid())) {
				  evoResponse.fail("INVALID_SID");
				  return evoResponse;
			  }
			 */

			  HashMap siteApiInfo = siteService.getSiteApiInfo(sParam);
			  String siteId = siteApiInfo.get("siteId").toString();

			  if(siteApiInfo==null) {

					 evoResponse.setBalance(null);
				   	 evoResponse.fail();
				   	 return evoResponse;
			  }

			  // 사이트에 크레딧이 없을경우 에러 보냄 베팅막음
			  long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString());
			  if(targetSiteCredit < evo.getTransaction().getAmount() ) {
				  System.out.println("no siteCredit");
				  evoResponse.setBalance(null);
				  evoResponse.fail("INSUFFICIENT_FUNDS2");
				  return evoResponse;
			  }


//최대베팅액 (userMaxBet 우선 적용)
  			  sParam.put("vendorIdx", 1);
  			  long maxBet = siteService.getSiteMaxBet(sParam);

  			  // userMaxBet 조회
  			  long userMaxBet = 0;
  			  Long userMaxBetObj = siteService.getUserMaxBet(sParam);
  			  if(userMaxBetObj != null) {
  				  userMaxBet = userMaxBetObj;
  			  }

  			  // 최종 maxBet 결정: userMaxBet이 0이면 siteMaxBet 사용, 0이 아니면 userMaxBet 사용
  			  long finalMaxBet = (userMaxBet > 0) ? userMaxBet : maxBet;
  			  System.out.println("MaxBet Info - siteMaxBet: " + maxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet);

  			  if(evo.getTransaction().getAmount() > finalMaxBet) {
  				  System.out.println("Over bet money - finalMaxBet: " + finalMaxBet);
  				  evoResponse.setBalance(null);
  				  evoResponse.fail("INSUFFICIENT_FUNDS3");
				   return evoResponse;
  			  }


			  int fatErrCnt = siteService.getFinalErr(evo.getTransaction().getRefId());

			  if(fatErrCnt > 0) {
				  JSONObject member = new JSONObject();
				  member.put("userId", memberId);

				  HttpHeaders headerb = new HttpHeaders();
				  headerb.add("Content-Type", "application/json");
				  headerb.add("Accept", "application/json");

				  ResponseEntity<String> responseEntityb = null;
				  try {
					  responseEntityb = webClient.post()
						.uri(siteApiInfo.get("siteCbUrl")+"/balance")
						.headers(h -> h.addAll(headerb))
						.bodyValue(member.toString())
						.retrieve()
						.toEntity(String.class)
						.block();
				  } catch(WebClientResponseException e) {
					log.error("debit(fatErrCnt)::HttpClientErrorException : " + e.getMessage());
					log.error("debit(fatErrCnt)::status code : " + e.getStatusCode().value());
					log.error("debit(fatErrCnt)::response body : " + e.getResponseBodyAsString());
					evoResponse.fail();
					return evoResponse;
				  } catch (WebClientRequestException rae) {
			            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
			            	log.error("debit(fatErrCnt)::ConnectTimeoutException::" + rae.getMessage());
			            }
			            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
			            	log.error("debit(fatErrCnt)::SocketTimeoutException::" + rae.getMessage());
			            }
			            if(rae.getCause() instanceof InterruptedException) {
			            	log.error("debit(fatErrCnt)::InterruptedException::" + rae.getMessage());
			            }
			            log.error("debit(fatErrCnt)::WebClientRequestException : " + rae.getMessage());
			            evoResponse.fail();
			            return evoResponse;
				  }

				  if(responseEntityb != null && responseEntityb.getStatusCode() == HttpStatus.OK) {
					log.info("status code : {}", responseEntityb.getStatusCode());
					log.info("body: {}", responseEntityb.getBody());

					JSONObject resDatab  = new JSONObject(responseEntityb.getBody());

					evoResponse.setBalance(resDatab.getDouble("balance"));
					evoResponse.fail("FINAL_ERROR_ACTION_FAILED");
					return evoResponse;
				  }
			  }

			  HashMap tranParam = new HashMap();
			  tranParam.put("tranId", siteId+evo.getTransaction().getId());
			  tranParam.put("refId",  siteId+evo.getTransaction().getRefId());
			  tranParam.put("siteIdx", siteApiInfo.get("siteIdx"));
			  tranParam.put("siteId", siteId);
			  tranParam.put("memberIdx", siteApiInfo.get("memberIdx"));
			  tranParam.put("memberId", memberId);
			  tranParam.put("vendorIdx", 1);
			  tranParam.put("vendorCode", "evolution");
			  tranParam.put("vendorTranKey", evo.getTransaction().getId());
			  tranParam.put("gameIdx", evo.getGame().getType());
			  tranParam.put("tranType", "debit");
			  tranParam.put("depositAmt", evo.getTransaction().getAmount());
			  tranParam.put("creditAmt", "0");
			  tranParam.put("isCancel", "N");
			  tranParam.put("isTie", "N");
			  tranParam.put("apiStatus", 0);
			  tranParam.put("completed", false);

			  try {
      			CommonParam commonParam = new CommonParam();
    			commonParam.setSiteIdx(Integer.parseInt(siteApiInfo.get("siteIdx").toString()));
    			PlayParam param = new PlayParam();
    			param.setVendorKey("C01");
    			commonParam.setPlayParam(param);
    			HashMap venderInfo = siteService.getVenderApiInfo(commonParam);
    			tranParam.put("vendorApiId", venderInfo.get("vendorApiId").toString());
      	    	 }catch(Exception e) {System.out.println("VI ERR:" + e.toString());}
			  siteService.commonBetinsert(tranParam);

				  HttpHeaders header = new HttpHeaders();
				  header.add("Content-Type", "application/json");
				  header.add("Accept", "application/json");
				  header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
				  JSONObject debit = new JSONObject();

			  	  	debit.put("betId", siteId+evo.getTransaction().getRefId());
					debit.put("tranId", siteId+evo.getTransaction().getId());
					debit.put("userId", memberId);
					debit.put("vendorIdx", 1);
					debit.put("vendorKey","C01");
					debit.put("vendor", "evolution");
					debit.put("gameIdx", 1);
					debit.put("gameKey",evo.getGame().getType());
					debit.put("tranType", "debit");
					debit.put("debit", evo.getTransaction().getAmount());
					debit.put("credit", 0);
					debit.put("isCancel", 0);
					debit.put("isBonus",0);

					 log.info("send code : {}", debit.toString());

				  ResponseEntity<String> responseEntity = null;
				  try {
					  responseEntity = webClient.post()
						.uri(siteApiInfo.get("siteCbUrl")+"/changebalance")
						.headers(h -> h.addAll(header))
						.bodyValue(debit.toString())
						.retrieve()
						.toEntity(String.class)
						.block();
				  } catch(WebClientResponseException e) {
					log.error("debit::HttpClientErrorException : " + e.getMessage());
					log.error("debit::status code : " + e.getStatusCode().value());
					log.error("debit::response body : " + e.getResponseBodyAsString());
					evoResponse.fail();
					return evoResponse;
				  } catch (WebClientRequestException rae) {
			            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
			            	log.error("debit::ConnectTimeoutException::" + rae.getMessage());
			            }
			            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
			            	log.error("debit::SocketTimeoutException::" + rae.getMessage());
			            }
			            if(rae.getCause() instanceof InterruptedException) {
			            	log.error("debit::InterruptedException::" + rae.getMessage());
			            }
			            log.error("debit::WebClientRequestException : " + rae.getMessage());
			            evoResponse.fail();
			            return evoResponse;
				  }

				  if(responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
					log.info("status code : {}", responseEntity.getStatusCode());
					log.info("bodyD: {}", responseEntity.getBody());

					JSONObject resData  = new JSONObject(responseEntity.getBody());
					log.info("result_Dcode: {}", resData.getInt("result_code"));

				   	if(resData.getLong("result_code") == 0) {
				   		tranParam.put("balance", resData.getDouble("balance"));
				   		int res =  siteService.updateCbApi(tranParam);
				   		log.info("result_Dcode: {}2");
				  	  evoResponse.setUuid(evo.getUuid());
						  evoResponse.setBalance( resData.getDouble("balance"));
						  evoResponse.setBonus(0.0);

						  evoResponse.success();
				   	}else 	if(resData.getLong("result_code") == 80) {
				   		evoResponse.setBalance( resData.getDouble("balance"));
				   		evoResponse.fail("INSUFFICIENT_FUNDS");

				   	}else 	if(resData.getLong("result_code") == 98) {
				   	 log.info("result_Dcode 98: {}1");
				   		evoResponse.fail("BET_ALREADY_EXIST");
				   		evoResponse.setBalance( resData.getDouble("balance"));
				   	}else {
				   		evoResponse.fail();
				   	}
				  } else {
					log.error("debit::Unexpected response status code");
					evoResponse.fail();
				  }

	        } catch (Exception e) {
	        	log.info(e.toString());
	        	e.printStackTrace();
	        	evoResponse.fail();
	        }

	        return evoResponse;
	}


	@ResponseBody
	@RequestMapping(value={"/credit","/cancel"})
	public EvoResponse credit (HttpServletRequest request, @RequestBody  EvolutionVo evo) throws Exception {
		EvoResponse evoResponse = new EvoResponse();

		  try {
			  log.debug(evo.toString());
			  //사이트정보
			  HashMap sParam = new HashMap();

			  sParam.put("siteIdx",Integer.parseInt(evo.getUserId().substring(0, 3), 16));
			  sParam.put("memberId", evo.getUserId().substring(3, evo.getUserId().length()));
			  String memberId =evo.getUserId().substring(3, evo.getUserId().length());

			  HashMap siteApiInfo = siteService.getSiteApiInfo(sParam);
			  String siteId = siteApiInfo.get("siteId").toString();

			  HashMap tranParam = new HashMap();
			  tranParam.put("tranId",siteId+evo.getTransaction().getId());
			  tranParam.put("refId",  siteId+evo.getTransaction().getRefId());
			  tranParam.put("siteIdx", siteApiInfo.get("siteIdx"));
			  tranParam.put("siteId", siteId);
			  tranParam.put("memberIdx", siteApiInfo.get("memberIdx"));
			  tranParam.put("memberId", memberId);
			  tranParam.put("vendorIdx", 1);
			  tranParam.put("vendorCode", "evolution");
			  tranParam.put("vendorTranKey", evo.getTransaction().getId());
			  tranParam.put("gameIdx", evo.getGame().getType());
			  tranParam.put("tranType", "credit");
			  tranParam.put("depositAmt", 0);
			  tranParam.put("creditAmt", evo.getTransaction().getAmount());

			  tranParam.put("completed", true);

			  tranParam.put("isCancel", "N");

			  if(request.getRequestURI().indexOf("cancel") > 0 ) {
				  tranParam.put("isCancel", "Y");
			  }
			  tranParam.put("isTie", "N");
			  tranParam.put("apiStatus", 0);


			  try {
        			CommonParam commonParam = new CommonParam();
      			commonParam.setSiteIdx(Integer.parseInt(siteApiInfo.get("siteIdx").toString()));
      			PlayParam param = new PlayParam();
      			param.setVendorKey("C01");
      			commonParam.setPlayParam(param);
      			HashMap venderInfo = siteService.getVenderApiInfo(commonParam);
      			tranParam.put("vendorApiId", venderInfo.get("vendorApiId").toString());
        	    	 }catch(Exception e) {System.out.println("VI ERR:" + e.toString());}
			  siteService.commonBetinsert(tranParam);

			  HttpHeaders header = new HttpHeaders();
			  header.add("Content-Type", "application/json");
			  header.add("Accept", "application/json");
			  header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
			  JSONObject debit = new JSONObject();

			  	  	debit.put("betId", siteId+evo.getTransaction().getRefId());
					debit.put("tranId", siteId+evo.getTransaction().getId());
					debit.put("userId",  memberId);
					debit.put("vendorIdx", 1);
					debit.put("vendorKey","C01");
					debit.put("vendor", "evolution");
					debit.put("gameIdx", 1);
					debit.put("gameKey",evo.getGame().getType());
					debit.put("tranType", "credit");
					debit.put("debit", 0);
					debit.put("credit",  evo.getTransaction().getAmount());
					debit.put("isCancel",0);
					debit.put("isBonus",0);

					  if(request.getRequestURI().indexOf("cancel") > 0 ) {
						  debit.put("isCancel",1);
					  }

					  log.info("send code : {}", debit.toString());

				  ResponseEntity<String> responseEntity = null;
				  try {
					  responseEntity = webClient.post()
						.uri(siteApiInfo.get("siteCbUrl")+"/changebalance")
						.headers(h -> h.addAll(header))
						.bodyValue(debit.toString())
						.retrieve()
						.toEntity(String.class)
						.block();
				  } catch(WebClientResponseException e) {
					log.error("credit::HttpClientErrorException : " + e.getMessage());
					log.error("credit::status code : " + e.getStatusCode().value());
					log.error("credit::response body : " + e.getResponseBodyAsString());
					evoResponse.fail();
					return evoResponse;
				  } catch (WebClientRequestException rae) {
			            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
			            	log.error("credit::ConnectTimeoutException::" + rae.getMessage());
			            }
			            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
			            	log.error("credit::SocketTimeoutException::" + rae.getMessage());
			            }
			            if(rae.getCause() instanceof InterruptedException) {
			            	log.error("credit::InterruptedException::" + rae.getMessage());
			            }
			            log.error("credit::WebClientRequestException : " + rae.getMessage());
			            evoResponse.fail();
			            return evoResponse;
				  }

				  if(responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
					log.info("status code : {}", responseEntity.getStatusCode());
					log.info("bodyC: {}", responseEntity.getBody());

					JSONObject resData  = new JSONObject(responseEntity.getBody());
					log.info("result_DCcode: {}", resData.getInt("result_code"));
				   	if(resData.getLong("result_code") == 0) {
				   	 log.info("siteService.updateCbApi(tranParam)");
				   	tranParam.put("balance", resData.getDouble("balance"));
				   		int res = siteService.updateCbApi(tranParam);

				  	  evoResponse.setUuid(evo.getUuid());
						  evoResponse.setBalance( resData.getDouble("balance"));
						  evoResponse.setBonus(0.0);
						  evoResponse.success();
				   	}else if(resData.getLong("result_code") == 99) {

				   	  if(request.getRequestURI().indexOf("cancel") > 0 ) {

				   		HashMap eParam = new HashMap();
				   		eParam.put("betId", evo.getTransaction().getRefId());
				   		eParam.put("errorType", "FATAL_ERROR");

				   		siteService.insertError(eParam);
				   	  }

				   		evoResponse.fail("BET_DOES_NOT_EXIST");
				   		evoResponse.setBalance( resData.getDouble("balance"));

				   	}else if(resData.getLong("result_code") == 98) {
				   		evoResponse.fail("BET_ALREADY_SETTLED");
				   		evoResponse.setBalance( resData.getDouble("balance"));
				   	}else {
				   	 evoResponse.fail();
				   	}
				  } else {
					log.error("credit::Unexpected response status code");
					evoResponse.fail();
				  }

	        } catch (Exception e) {
	        	log.info(e.toString());
	        	e.printStackTrace();
	        	evoResponse.fail();
	        }

	        return evoResponse;
	}



	@ResponseBody
	@RequestMapping(value={"/promo_payout"})
	public EvoResponse promo_payout (HttpServletRequest request, @RequestBody  EvolutionVo evo) throws Exception {
		EvoResponse evoResponse = new EvoResponse();

		  try {
			  log.debug(evo.toString());
			  //사이트정보
			  HashMap sParam = new HashMap();
			  String[] usrinfo = evo.getUserId().split("_");

			  sParam.put("siteIdx",Integer.parseInt(evo.getUserId().substring(0, 3), 16));
			  sParam.put("memberId", evo.getUserId().substring(3, evo.getUserId().length()));
			  String memberId =evo.getUserId().substring(3, evo.getUserId().length());

			  HashMap siteApiInfo = siteService.getSiteApiInfo(sParam);
			  String siteId = siteApiInfo.get("siteId").toString();

			  HashMap tranParam = new HashMap();
			  tranParam.put("tranId",siteId+evo.getPromoTransaction().getId());
			  tranParam.put("refId",  siteId+evo.getPromoTransaction().getId());
			  tranParam.put("siteIdx", siteApiInfo.get("siteIdx"));
			  tranParam.put("siteId", siteId);
			  tranParam.put("memberIdx", siteApiInfo.get("memberIdx"));
			  tranParam.put("memberId", memberId);
			  tranParam.put("vendorIdx", 1);
			  tranParam.put("vendorCode", "evolution");
			  tranParam.put("vendorTranKey", evo.getPromoTransaction().getId());
			  tranParam.put("gameIdx", evo.getPromoTransaction().getType());
			  tranParam.put("tranType", "promo");
			  tranParam.put("depositAmt", 0);
			  tranParam.put("creditAmt", evo.getPromoTransaction().getAmount());

			  tranParam.put("isCancel", "N");

			  if(request.getRequestURI().indexOf("cancel") > 0 ) {
				  tranParam.put("isCancel", "Y");
			  }
			  tranParam.put("isTie", "N");
			  tranParam.put("apiStatus", 0);

			  tranParam.put("completed", true);
			  try {
        			CommonParam commonParam = new CommonParam();
      			commonParam.setSiteIdx(Integer.parseInt(siteApiInfo.get("siteIdx").toString()));
      			PlayParam param = new PlayParam();
      			param.setVendorKey("C01");
      			commonParam.setPlayParam(param);
      			HashMap venderInfo = siteService.getVenderApiInfo(commonParam);
      			tranParam.put("vendorApiId", venderInfo.get("vendorApiId").toString());
        	    	 }catch(Exception e) {System.out.println("VI ERR:" + e.toString());}
			  siteService.commonBetinsert(tranParam);

			  HttpHeaders header = new HttpHeaders();
			  header.add("Content-Type", "application/json");
			  header.add("Accept", "application/json");
			  header.add("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)" + " AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36");
			  JSONObject debit = new JSONObject();

			  	  	debit.put("betId", siteId+evo.getPromoTransaction().getId());
					debit.put("tranId", siteId+evo.getPromoTransaction().getId());
					debit.put("userId",  memberId);
					debit.put("vendorIdx", 1);
					debit.put("vendorKey","C01");
					debit.put("vendor","evolution");
					debit.put("gameIdx", 1);
					debit.put("gameKey",evo.getPromoTransaction().getType());
					debit.put("tranType", "credit");
					debit.put("debit", 0);
					debit.put("credit",  evo.getPromoTransaction().getAmount());
					debit.put("isCancel",0);
					debit.put("isBonus",1);

				  log.info("send code : {}", debit.toString());

				  ResponseEntity<String> responseEntity = null;
				  try {
					  responseEntity = webClient.post()
						.uri(siteApiInfo.get("siteCbUrl")+"/changebalance")
						.headers(h -> h.addAll(header))
						.bodyValue(debit.toString())
						.retrieve()
						.toEntity(String.class)
						.block();
				  } catch(WebClientResponseException e) {
					log.error("promo_payout::HttpClientErrorException : " + e.getMessage());
					log.error("promo_payout::status code : " + e.getStatusCode().value());
					log.error("promo_payout::response body : " + e.getResponseBodyAsString());
					evoResponse.fail();
					return evoResponse;
				  } catch (WebClientRequestException rae) {
			            if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
			            	log.error("promo_payout::ConnectTimeoutException::" + rae.getMessage());
			            }
			            if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
			            	log.error("promo_payout::SocketTimeoutException::" + rae.getMessage());
			            }
			            if(rae.getCause() instanceof InterruptedException) {
			            	log.error("promo_payout::InterruptedException::" + rae.getMessage());
			            }
			            log.error("promo_payout::WebClientRequestException : " + rae.getMessage());
			            evoResponse.fail();
			            return evoResponse;
				  }

				  if(responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
					log.info("status code : {}", responseEntity.getStatusCode());
					log.info("bodyC: {}", responseEntity.getBody());

					JSONObject resData  = new JSONObject(responseEntity.getBody());
					log.info("result_DCcode: {}", resData.getInt("result_code"));
				   	if(resData.getLong("result_code") == 0) {
				   	 log.info("siteService.updateCbApi(tranParam)");
				   	tranParam.put("balance", resData.getDouble("balance"));
				   		int res = siteService.updateCbApi(tranParam);

				  	  evoResponse.setUuid(evo.getUuid());
						  evoResponse.setBalance( resData.getDouble("balance"));
						  evoResponse.setBonus(0.0);
						  evoResponse.success();
				   	}else if(resData.getLong("result_code") == 99) {
				   		evoResponse.fail("BET_DOES_NOT_EXIST");
				   		evoResponse.setBalance( resData.getDouble("balance"));

				   	}else if(resData.getLong("result_code") == 98) {
				   		evoResponse.fail("BET_ALREADY_SETTLED");
				   		evoResponse.setBalance( resData.getDouble("balance"));

				   	}else if(resData.getLong("result_code") == 70) {
				   		evoResponse.fail("BET_ALREADY_SETTLED");
				   		evoResponse.setBalance( resData.getDouble("balance"));

				   	}else {
				   	 evoResponse.fail();
				   	}
				  } else {
					log.error("promo_payout::Unexpected response status code");
					evoResponse.fail();
				  }

	        } catch (Exception e) {
	        	log.info(e.toString());
	        	e.printStackTrace();
	        	evoResponse.fail();
	        }

	        return evoResponse;
	}



	 private String makeApiKey(String param) {

		   int n = 20; // n자리 쿠폰
		   char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
		  		'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
		  		'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ,'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z' };


		  	Random rd = new Random();
		  	StringBuilder sb = new StringBuilder();
		  	for (int i = 0; i < n; i++) {
		  		char ch = chs[rd.nextInt(chs.length)];
		  		sb.append(ch);
		  	}
		  	return param + sb.toString();


	  }

}

