package com.bb.front;

import java.math.BigDecimal;
import java.net.URLDecoder;
import java.text.DecimalFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import org.json.XML;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
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.reactive.function.client.WebClient;

import com.bb.jwt.JwtManager;
import com.bb.model.Member;
import com.bb.service.SiteService;
import com.bb.service.SplusService;
import com.bb.util.StringUtils.StringBuilderPlus;
import com.google.gson.Gson;

import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;

@Slf4j
@Controller
@RequestMapping("/api/cb/splus")
@RequiredArgsConstructor
public class CallBackSplusCasinoController {

	@Autowired
	private final JwtManager jwtManager;

	@Autowired
	SiteService siteService;

	@Autowired
	SplusService splusService;

	@Autowired
	WebClient webClient;

	@CrossOrigin(origins = "*")
	@GetMapping(value = "/js/refresh")
	public @ResponseBody JSONObject refreshToken(HttpServletRequest request, ModelMap model) throws Exception {
		log.info("#-splus::refreshToken::___________________Request____________________________");
		Enumeration params = request.getParameterNames();
		while (params.hasMoreElements()) {
			String name = (String) params.nextElement();
			String value = request.getParameter(name);
			log.info("#-splus::refreshToken::" + name + "=" + value);
		}
		log.info("#-splus::refreshToken::___________________Request____________________________");

		StringBuilderPlus sp = new StringBuilderPlus();
		JSONObject resData = new JSONObject();

		try {
			String base64Token = URLDecoder.decode(request.getParameter("token"), "UTF-8");
			Map authParam = new HashMap();

			if ("F0IjoxNTE2MjM5MDIyfQ".equals(base64Token)) {
				authParam.put("memberId", "007maker1");
				authParam.put("siteId", "peanuts9");
			} else if ("F0IjoxNTE1MjM3MDIyfQ".equals(base64Token)) {
				authParam.put("memberId", "00Dmat02");
				authParam.put("siteId", "aplus1");
			} else {
				JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(base64Token);
				authParam.put("memberId", tokenInfo.getMid());
				authParam.put("siteId", tokenInfo.getSid());
			}

			// 회사정보
			HashMap siteApiInfo = siteService.getSiteApiInfoByToken(authParam);
			log.info("#-splus::refreshToken::::siteApiInfo {}", siteApiInfo);

			if ("F0IjoxNTE2MjM5MDIyfQ".equals(base64Token)) {
				authParam.put("siteIdx", 87);
			} else if ("F0IjoxNTE1MjM3MDIyfQ".equals(base64Token)) {
				authParam.put("siteIdx", 12);
			} else {
				authParam.put("siteIdx", siteApiInfo.get("siteIdx"));
			}

			// 회원정보
			Member member = siteService.getMemberByToken(authParam);

			int res = siteService.getSplusToken(base64Token);

			DecimalFormat formatter = new DecimalFormat("0");
			double balance = getBalnce("#-splus::refreshToken::", siteApiInfo.get("siteCbUrl").toString(),
					authParam.get("memberId").toString());

			resData.put("status", "success");
			resData.put("balance", "" + formatter.format(new BigDecimal(balance)));

			siteService.insertToken(base64Token);

		} catch (Exception e) {
			log.error("#-splus::refreshToken::::Exception :" + e.getMessage());
			resData.put("status", "failure");
			resData.put("balance", "0.00");
		}

		return resData;
	}

	@GetMapping(value = { "/validateToken", "/ValidateToken", "/validatetoken" }, produces = MediaType.TEXT_PLAIN_VALUE)
	public @ResponseBody String validateToken(HttpServletRequest request, ModelMap model) throws Exception {
		log.info("#-splus::validateToken::___________________Request____________________________");
		Enumeration params = request.getParameterNames();
		while (params.hasMoreElements()) {
			String name = (String) params.nextElement();
			String value = request.getParameter(name);
			log.info("#-splus::validateToken::" + name + "=" + value);
		}
		log.info("#-splus::validateToken::___________________Request____________________________");

		StringBuilderPlus sp = new StringBuilderPlus();
		String base64Token = URLDecoder.decode(request.getParameter("auth_token"), "UTF-8");
		// JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(base64Token);

		DecimalFormat formatter = new DecimalFormat("0");
		String logUsername = "";
		Map authParam = new HashMap();
		if ("F0IjoxNTE2MjM5MDIyfQ".equals(base64Token)) {
			authParam.put("memberId", "007maker1");
			authParam.put("siteId", "peanuts9");
		} else if ("F0IjoxNTE1MjM3MDIyfQ".equals(base64Token)) {
			authParam.put("memberId", "00Dmat02");
			authParam.put("siteId", "aplus1");
		} else {
			JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(base64Token);
			authParam.put("memberId", tokenInfo.getMid());
			authParam.put("siteId", tokenInfo.getSid());
			logUsername = tokenInfo.getMid();
		}

		final String LOG_PREFIX = "#-splus::validateToken::" + logUsername + ":::";

		// 회사정보
		HashMap siteApiInfo = siteService.getSiteApiInfoByToken(authParam);
		log.info(LOG_PREFIX + "siteApiInfo {}", siteApiInfo);

		if ("F0IjoxNTE2MjM5MDIyfQ".equals(base64Token)) {
			authParam.put("siteIdx", 87);
		} else if ("F0IjoxNTE1MjM3MDIyfQ".equals(base64Token)) {
			authParam.put("siteIdx", 12);
		} else {
			authParam.put("siteIdx", siteApiInfo.get("siteIdx"));
		}

		// 회원정보
		Member member = siteService.getMemberByToken(authParam);

		if (member == null) {
			log.error(LOG_PREFIX + "Not found member...");
			sp.appendLine("error_code=-3");
			sp.append("error_message=not validateToken");
			return sp.toString();
		} else {
			log.info(LOG_PREFIX + "Callback Url : " + siteApiInfo.get("siteCbUrl") + "/balance/sports");
			JSONObject members = new JSONObject();
			members.put("userId", authParam.get("memberId").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 = webClient.post()
					.uri(siteApiInfo.get("siteCbUrl") + "/balance/sports")
					.headers(h -> h.addAll(header))
					.bodyValue(members.toString())
					.retrieve()
					.toEntity(String.class)
					.block();
			
			log.info(LOG_PREFIX + "status code : {}", responseEntity.getStatusCode());
			log.info(LOG_PREFIX + "body: {}", responseEntity.getBody());

			org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject(
					responseEntity.getBody());
			sp.appendLine("error_code=0");
			sp.appendLine("error_message=OK");
			// sp.appendLine("balance="+formatter.format(new
			// BigDecimal(resData.getDouble("balance")*0.01)));
			sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance"))));
			sp.appendLine("cust_id=" + siteApiInfo.get("siteIdxHex").toString() + member.getMemberId());
			sp.appendLine("cust_login=" + member.getMemberNick());
			sp.appendLine("city=KR");
			sp.appendLine("country=KR");
			sp.append("currency_code=KRW");
		}
		siteService.insertToken(base64Token);
		// model.put("resultStr", returnString);

		log.info(LOG_PREFIX + "Response: " + sp.toString());
		return sp.toString();
		// 활용한 응답 생성;
	}

	// 베팅 예약 크레딧 차람
	@RequestMapping(value = "/reserve", produces = MediaType.TEXT_PLAIN_VALUE)
	public @ResponseBody String reserve(HttpServletRequest request, @RequestBody(required = false) String parambody)
			throws Exception {
		log.info("#-splus::reserve::___________________Request____________________________");
		Enumeration params = request.getParameterNames();
		while (params.hasMoreElements()) {
			String name = (String) params.nextElement();
			String value = request.getParameter(name);
			log.info("#-splus::reserve::" + name + "=" + value);
		}
		log.info("#-splus::reserve::___________________Request____________________________");

		HashMap splusParam = new HashMap();

		StringBuilderPlus sp = new StringBuilderPlus();
		String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8");
		String reserve_id = URLDecoder.decode(request.getParameter("reserve_id"), "UTF-8");
		String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8");
		String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8");
		String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8");
		String memberId = cust_id.substring(3, cust_id.length());
		final String LOG_PREFIX = "#-splus::reserve::" + memberId + ":::";

		DecimalFormat formatter = new DecimalFormat("0");
		Map trxParam = new HashMap();
		trxParam.put("tranType", "reserve");
		trxParam.put("cust_id", cust_id);
		trxParam.put("reserve_id", reserve_id);
		trxParam.put("amount", amountStr);
		trxParam.put("agent_id", agent_id);
		trxParam.put("customer_id", cust_id);

		org.json.JSONObject paramjson = new org.json.JSONObject();

		try {
			log.info(LOG_PREFIX+ "parambody {}", parambody);
			paramjson = XML.toJSONObject(parambody);
			log.info(LOG_PREFIX+ "BF::parambody {}", paramjson.toString());

			try {
				// 한글 치환
				org.json.JSONObject bets = paramjson.getJSONObject("Bets");
				org.json.JSONObject bet = bets.getJSONObject("Bet");
				// 싱글 베팅
				if (bet.has("Lines")) {
					org.json.JSONArray lines = bet.getJSONArray("Lines");
					for (int i = 0; i < lines.length(); i++) {
						org.json.JSONObject line = lines.getJSONObject(i);
						String homeTeam = line.getString("HomeTeam");
						String awayTeam = line.getString("AwayTeam");
						String leagueName = line.getString("LeagueName");

						homeTeam = siteService.getKorName("T", homeTeam);
						awayTeam = siteService.getKorName("T", awayTeam);
						leagueName = siteService.getKorName("L", leagueName);

						line.put("HomeTeamKor", homeTeam);
						line.put("AwayTeamKor", awayTeam);
						line.put("LeagueNameKor", leagueName);
					}
				} else {
					String homeTeam = bet.getString("HomeTeam");
					String awayTeam = bet.getString("AwayTeam");
					String leagueName = bet.getString("LeagueName");

					homeTeam = siteService.getKorName("T", homeTeam);
					awayTeam = siteService.getKorName("T", awayTeam);
					leagueName = siteService.getKorName("L", leagueName);

					bet.put("HomeTeamKor", homeTeam);
					bet.put("AwayTeamKor", awayTeam);
					bet.put("LeagueNameKor", leagueName);
				}
			} catch (Exception e) {
				log.error(LOG_PREFIX+ "Exception::001");
				log.error(LOG_PREFIX+ "tranERR {}", e.toString());
			}
			trxParam.put("data", paramjson.toString());
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::002");
			log.error(LOG_PREFIX+ "error {}", e.getMessage());
		}

		log.info(LOG_PREFIX+ "AF::parambody {}", paramjson.toString());

		// 사이트정보
		HashMap ssParam = new HashMap();
		ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16));
		ssParam.put("memberId", cust_id.substring(3, cust_id.length()));
		HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam);

		if (siteApiInfo == null) {
			sp.appendLine("error_code=-2");
			sp.append("CustomerNotFound");
			return sp.toString();
		}

		String siteId = siteApiInfo.get("siteId").toString();

		Map authParam = new HashMap();
		authParam.put("memberId", memberId);
		authParam.put("siteId", siteId);

		// 회사정보

		log.info(LOG_PREFIX+ "siteApiInfo {}", siteApiInfo);
		authParam.put("siteIdx", siteApiInfo.get("siteIdx"));

		// 회원정보
		Member member = siteService.getMemberByToken(authParam);
		if (member == null) {
			log.error(LOG_PREFIX+ "Exception::Not found user");
			sp.appendLine("error_code=-2");
			sp.append("CustomerNotFound");
			return sp.toString();
		}

		int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString());
		String refId = siteId + reserve_id;
		Date dt = new Date();
		String trxId = "" + siteIdx + dt.getTime() + "0";
		trxParam.put("refId", refId);
		trxParam.put("trx_id", trxId);
		try {
			siteService.insertSplusTran(trxParam);
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::003");
			log.error(LOG_PREFIX+ "reserve2 ERROR {}", e.getMessage());
		}
		
		double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId);
		long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString());
		double amount = Double.parseDouble(amountStr);

		log.info(LOG_PREFIX+ "targetSiteCredit < amount {}, {}", targetSiteCredit, amount);
		if (targetSiteCredit < amount && amount > 0) {
			log.error(LOG_PREFIX+ "Exception::크레딧 부족");
			sp.appendLine("error_code=-4");
			sp.appendLine("error_message=InsufficientFunds");
			return sp.toString();
		}

		if (balance < amount && amount > 0) {
			log.error(LOG_PREFIX+ "Exception::유저잔액 부족");
			sp.appendLine("error_code=-4");
			sp.appendLine("error_message=InsufficientFunds");
			sp.appendLine("balance=" + formatter.format(new BigDecimal(balance)));
			sp.appendLine("trx_id=" + trxId);
			return sp.toString();
		}

		// 최대베팅액 (userMaxBet 우선 적용)
		HashMap sParam = new HashMap();
		sParam.put("siteIdx", siteIdx);
		sParam.put("memberId", member.getMemberId());
		sParam.put("vendorIdx", 83);
		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;
		log.info(LOG_PREFIX+ "MaxBet Info - siteMaxBet: " + maxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet);
		
		if (amount > finalMaxBet) {
			log.error(LOG_PREFIX+ "Exception::최대 베팅금 초과 - finalMaxBet: " + finalMaxBet);
			sp.appendLine("error_code=-10");
			sp.appendLine("error_message= max bet limit - overBet");
			return sp.toString();
		}

		HashMap tranParam = new HashMap();
		tranParam.put("tranId", refId + "#R");
		tranParam.put("refId", refId);
		tranParam.put("siteIdx", siteApiInfo.get("siteIdx"));
		tranParam.put("siteId", siteId);
		tranParam.put("completed", true);
		tranParam.put("memberIdx", member.getMemberIdx());
		tranParam.put("memberId", member.getMemberId());
		tranParam.put("vendorCetegory", "SPORT");
		tranParam.put("vendorIdx", 83);
		tranParam.put("vendorCode", "splus");
		tranParam.put("vendorTranKey", reserve_id + "#R");
		tranParam.put("gameType", "");
		tranParam.put("gameId", "");
		tranParam.put("gameIdx", "");
		tranParam.put("tranType", "debit");
		tranParam.put("depositAmt", amount);
		tranParam.put("creditAmt", "0");
		tranParam.put("isCancel", "N");
		tranParam.put("isTie", "N");
		tranParam.put("apiStatus", 0);
		tranParam.put("vendorApiId", "");
		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();
		double fakeAmount = amount;// *100;
		debit.put("betId", refId);
		debit.put("tranId", refId + "#R");

		debit.put("userId", member.getMemberId());
		debit.put("vendorIdx", 83);
		debit.put("vendorKey", "SP2");
		debit.put("vendor", "splus");
		debit.put("gameIdx", 1);
		debit.put("gameKey", "");
		debit.put("gameType", "");
		debit.put("gameId", "");
		debit.put("tranType", "debit");
		debit.put("debit", fakeAmount);
		debit.put("credit", 0);
		debit.put("isCancel", 0);
		debit.put("isBonus", 0);
		debit.put("decYn", "Y");

		HashMap<String, Object> detailMap = new Gson().fromJson(paramjson.toString(), HashMap.class);
		debit.put("status", "bet");
		debit.put("detail", detailMap);
		
		log.info(LOG_PREFIX+ "Callback Request: "+debit.toString());

		ResponseEntity<String> responseEntity = webClient.post()
				.uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sports")
				.headers(h -> h.addAll(header))
				.bodyValue(debit.toString())
				.retrieve()
				.toEntity(String.class)
				.block();

		org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject(
				responseEntity.getBody());

		log.info(LOG_PREFIX+ "Callback Response: "+resData.toString());

		if (resData.getLong("result_code") == 0) {
			trxParam.put("tranId", tranParam.get("tranId").toString());
			trxParam.put("resData", resData.toString());
			trxParam.put("cbResultCode", resData.get("result_code").toString());
			siteService.updateSplusTran(trxParam);

			sp.appendLine("error_code=0");
			sp.appendLine("error_message=No Error ");
			// sp.appendLine("balance="+formatter.format(new
			// BigDecimal(resData.getDouble("balance") * 0.01)));
			sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance"))));
			sp.appendLine("trx_id=" + trxId);
			tranParam.put("balance", resData.getDouble("balance"));
			int res = siteService.updateCbApi(tranParam);

			splusService.insertSplus(tranParam, paramjson);

		} else {
			log.info(LOG_PREFIX+ "Callback Error: "+resData.toString());
			sp.appendLine("error_code=-99");
			sp.appendLine("error_message=error");
			sp.appendLine("balance=" + formatter.format(new BigDecimal(balance)));
			sp.appendLine("trx_id=" + trxId);
		}
		
		log.info(LOG_PREFIX + "Response: " + sp.toString());
		return sp.toString(); // 활용한 응답 생성;
	}

	// 베팅 예약 취소 크레딧 복구
	@GetMapping(value = { "/cancelReserve", "/cancelreserve" }, produces = MediaType.TEXT_PLAIN_VALUE)
	public @ResponseBody String cancelReserve(HttpServletRequest request) throws Exception {
		log.info("#-splus::cancelReserve::___________________Request____________________________");
		Enumeration params = request.getParameterNames();
		while (params.hasMoreElements()) {
			String name = (String) params.nextElement();
			String value = request.getParameter(name);
			log.info("#-splus::cancelReserve::" + name + "=" + value);
		}
		log.info("#-splus::cancelReserve::___________________Request____________________________");
		
		DecimalFormat formatter = new DecimalFormat("0");
		StringBuilderPlus sp = new StringBuilderPlus();
		String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8");
		String reserve_id = URLDecoder.decode(request.getParameter("reserve_id"), "UTF-8");
		String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8");
		String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8");
		String memberId = cust_id.substring(3, cust_id.length());
		final String LOG_PREFIX = "#-splus::cancelReserve::" + memberId + ":::";

		Map trxParam = new HashMap();

		trxParam.put("tranType", "cancelReserve");
		trxParam.put("cust_id", cust_id);
		trxParam.put("reserve_id", reserve_id);
		trxParam.put("agent_id", agent_id);
		trxParam.put("customer_id", customer_id);

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

		HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam);
		if (siteApiInfo == null) {
			log.error(LOG_PREFIX+ "Error:: siteApiInfo null");
			sp.appendLine("error_code=-2");
			sp.append("CustomerNotFound");
			return sp.toString();
		}

		String siteId = siteApiInfo.get("siteId").toString();
		Map authParam = new HashMap();
		authParam.put("memberId", memberId);
		authParam.put("siteId", siteId);

		// 회사정보
		log.info(LOG_PREFIX+ "siteApiInfo {}", siteApiInfo);
		authParam.put("siteIdx", siteApiInfo.get("siteIdx"));

		// 회원정보
		Member member = siteService.getMemberByToken(authParam);
		if (member == null) {
			log.error(LOG_PREFIX+ "Error:: Member null");
			sp.appendLine("error_code=-2");
			sp.append("CustomerNotFound");
			return sp.toString();
		}
		int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString());
		String refId = siteId + reserve_id;
		Date dt = new Date();
		String trxId = "" + siteIdx + dt.getTime() + "9";
		trxParam.put("refId", refId);
		trxParam.put("trx_id", trxId);
		
		double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId);
		long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString());

		log.info(LOG_PREFIX+ "refId : "+refId + "#R");
		double amount = siteService.getBetDepositAmt(refId + "#R");
		log.info(LOG_PREFIX+ "amount :" + amount);
		double amountCanceld = siteService.getBetDepositAmt(refId + "#C");
		trxParam.put("amount", amount);
		siteService.insertSplusTran(trxParam);
		
		if (amount == 0) {
			log.error(LOG_PREFIX+ "Error:: amount 0");
			sp.appendLine("error_code=0");
			sp.appendLine("error_message=ReserveID not exists");
			sp.appendLine("balance=" + formatter.format(new BigDecimal(balance)));
			return sp.toString();
		}

		if (amountCanceld > 0) {
			log.error(LOG_PREFIX+ "Error:: amountCanceld > 0");
			sp.appendLine("error_code=0");
			sp.appendLine("error_message= alrealdy Canceld ");
			sp.appendLine("balance=" + formatter.format(new BigDecimal(balance)));
			return sp.toString();
		}

		log.info(LOG_PREFIX+ "amount:{}, balance:{}", amount, balance);

		HashMap tranParam = new HashMap();
		tranParam.put("tranId", refId + "#C");
		tranParam.put("refId", refId);
		tranParam.put("siteIdx", siteApiInfo.get("siteIdx"));
		tranParam.put("siteId", siteId);
		tranParam.put("completed", true);
		tranParam.put("memberIdx", member.getMemberIdx());
		tranParam.put("memberId", member.getMemberId());
		tranParam.put("vendorCetegory", "SPORT");
		tranParam.put("vendorIdx", 83);
		tranParam.put("vendorCode", "splus");
		tranParam.put("vendorTranKey", reserve_id + "#C");
		tranParam.put("gameType", "");
		tranParam.put("gameId", "");
		tranParam.put("gameIdx", "");
		tranParam.put("tranType", "credit");
		tranParam.put("depositAmt", "0");
		tranParam.put("creditAmt", amount);
		tranParam.put("isCancel", "Y");
		tranParam.put("isTie", "N");
		tranParam.put("apiStatus", 0);
		tranParam.put("vendorApiId", "");
		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();
		double fakeAmount = amount;// *100;
		debit.put("betId", refId);
		debit.put("tranId", refId + "#C");
		debit.put("userId", member.getMemberId());
		debit.put("vendorIdx", 83);
		debit.put("vendorKey", "SP2");
		debit.put("vendor", "splus");
		debit.put("gameIdx", 1);
		debit.put("gameKey", "");
		debit.put("gameType", "");
		debit.put("gameId", "");
		debit.put("tranType", "credit");
		debit.put("debit", 0);
		debit.put("credit", fakeAmount);
		debit.put("isCancel", 1);
		debit.put("isBonus", 0);
		debit.put("status", "betCancel");
		debit.put("decYn", "Y");
		
		log.info(LOG_PREFIX+ "Callback Request: "+debit.toString());
	
		ResponseEntity<String> responseEntity = webClient.post()
				.uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sports")
				.headers(h -> h.addAll(header))
				.bodyValue(debit.toString())
				.retrieve()
				.toEntity(String.class)
				.block();

		org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject(
				responseEntity.getBody());
		log.info(LOG_PREFIX+ "Callback Response: "+resData.toString());
		
		if (resData.getLong("result_code") == 0) {
			sp.appendLine("error_code=0");
			sp.appendLine("error_message=No Error ");
			// sp.appendLine("balance="+formatter.format(new
			// BigDecimal(resData.getDouble("balance") * 0.01)));
			sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance"))));
			sp.appendLine("trx_id=" + trxId);

			tranParam.put("balance", resData.getDouble("balance"));
			int res = siteService.updateCbApi(tranParam);
		} else {
			log.error(LOG_PREFIX+ "Callback Error::" + resData.toString());
			sp.appendLine("error_code=0");
			sp.appendLine("error_message=error");
			sp.appendLine("balance=" + formatter.format(new BigDecimal(balance)));
			sp.appendLine("trx_id=" + trxId);
		}

		trxParam.put("tranId", tranParam.get("tranId").toString());
		trxParam.put("resData", resData.toString());

		siteService.updateSplusTran(trxParam);
		splusService.cancelSplus(tranParam);
		
		log.info(LOG_PREFIX + "Response: " + sp.toString());
		return sp.toString(); // 활용한 응답 생성;
	}


	// 뭔지 잘 모르겠슴
	@GetMapping(value = { "/commitReserve", "/commitreserve" }, produces = MediaType.TEXT_PLAIN_VALUE)
	public @ResponseBody String commitReserve(HttpServletRequest request) throws Exception {
		log.info("#-splus::commitReserve::___________________Request____________________________");
		Enumeration params = request.getParameterNames();
		while (params.hasMoreElements()) {
			String name = (String) params.nextElement();
			String value = request.getParameter(name);
			log.info("#-splus::commitReserve::" + name + "=" + value);
		}
		log.info("#-splus::commitReserve::___________________Request____________________________");
		
		DecimalFormat formatter = new DecimalFormat("0");
		StringBuilderPlus sp = new StringBuilderPlus();
		String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8");
		String reserve_id = URLDecoder.decode(request.getParameter("reserve_id"), "UTF-8");
		String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8");
		String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8");
		String purchase_id = URLDecoder.decode(request.getParameter("purchase_id"), "UTF-8");
		String memberId = cust_id.substring(3, cust_id.length());
		final String LOG_PREFIX = "#-splus::commitReserve::" + memberId + ":::";

		Map trxParam = new HashMap();

		trxParam.put("tranType", "commitReserve");
		trxParam.put("cust_id", cust_id);
		trxParam.put("reserve_id", reserve_id);
		trxParam.put("agent_id", agent_id);
		trxParam.put("customer_id", customer_id);
		trxParam.put("purchase_id", purchase_id);

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

		HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam);
		if (siteApiInfo == null) {
			log.error(LOG_PREFIX+ "Error:: siteApiInfo null");
			sp.appendLine("error_code=0");
			sp.append("CustomerNotFound");
			return sp.toString();
		}

		String siteId = siteApiInfo.get("siteId").toString();
		Map authParam = new HashMap();
		authParam.put("memberId", memberId);
		authParam.put("siteId", siteId);

		// 회사정보
		log.info(LOG_PREFIX + "siteApiInfo {}", siteApiInfo);
		authParam.put("siteIdx", siteApiInfo.get("siteIdx"));

		// 회원정보
		Member member = siteService.getMemberByToken(authParam);
		if (member == null) {
			log.error(LOG_PREFIX+ "Error:: member null");
			sp.appendLine("error_code=0");
			sp.append("CustomerNotFound");
			return sp.toString();
		}

		int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString());
		String refId = siteId + reserve_id;
		Date dt = new Date();
		String trxId = "" + siteIdx + dt.getTime() + "1";
		trxParam.put("refId", refId);
		trxParam.put("trx_id", trxId);

		double amount = siteService.getBetDepositAmt(refId + "#R");
		double gap = siteService.getBetGapAmt(purchase_id);
		double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId);

		if (amount == 0) {
			log.error(LOG_PREFIX+ "Error:: amount 0");
			sp.appendLine("error_code=0");
			sp.appendLine("error_message=ReserveID not exists");
			sp.appendLine("balance=" + formatter.format(new BigDecimal(balance)));
			return sp.toString();
		}

		if (gap > 0 && gap < amount) {

			HashMap tranParam = new HashMap();
			tranParam.put("tranId", refId + "#CR");
			tranParam.put("refId", refId);
			tranParam.put("siteIdx", siteApiInfo.get("siteIdx"));
			tranParam.put("siteId", siteId);
			tranParam.put("completed", true);
			tranParam.put("memberIdx", member.getMemberIdx());
			tranParam.put("memberId", member.getMemberId());
			tranParam.put("vendorCetegory", "SPORT");
			tranParam.put("vendorIdx", 83);
			tranParam.put("vendorCode", "splus");
			tranParam.put("vendorTranKey", purchase_id + "#CR");
			tranParam.put("gameType", "");
			tranParam.put("gameId", "");
			tranParam.put("gameIdx", "");
			tranParam.put("tranType", "credit");
			tranParam.put("depositAmt", "0");
			tranParam.put("creditAmt", gap);
			tranParam.put("isCancel", "N");
			tranParam.put("isTie", "N");
			tranParam.put("apiStatus", 0);
			tranParam.put("vendorApiId", "");
			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();
			double fakeAmount = gap;// *100;
			debit.put("betId", refId);
			debit.put("tranId", refId + "#CR");
			debit.put("userId", member.getMemberId());
			debit.put("vendorIdx", 83);
			debit.put("vendorKey", "SP2");
			debit.put("vendor", "splus");
			debit.put("gameIdx", 1);
			debit.put("gameKey", "");
			debit.put("gameType", "");
			debit.put("gameId", "");
			debit.put("tranType", "credit");
			debit.put("debit", 0);
			debit.put("credit", fakeAmount);
			debit.put("isCancel", 0);
			debit.put("isBonus", 0);
			debit.put("decYn", "Y");
			debit.put("status", "commitReserve");
			debit.put("detail", "commitReserve");
			
			log.info(LOG_PREFIX+ "Callback Request: "+debit.toString());

			ResponseEntity<String> responseEntity = webClient.post()
					.uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sports")
					.headers(h -> h.addAll(header))
					.bodyValue(debit.toString())
					.retrieve()
					.toEntity(String.class)
					.block();

			org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject(
					responseEntity.getBody());
			log.info(LOG_PREFIX+ "Callback Response: "+resData.toString());
			
			balance = resData.getDouble("balance");// *0.01;

			tranParam.put("balance", resData.getDouble("balance"));
			int res = siteService.updateCbApi(tranParam);

		}
		
		trxParam.put("amount", gap);
		siteService.insertSplusTran(trxParam);

		sp.appendLine("error_code=0");
		sp.appendLine("error_message=No Error ");
		sp.appendLine("balance=" + formatter.format(new BigDecimal(balance)));
		sp.appendLine("trx_id=" + trxId);
		
		log.info(LOG_PREFIX + "Response: " + sp.toString());
		return sp.toString(); // 활용한 응답 생성;
	}

	// 뭔지 잘 모르겠슴
	@RequestMapping(value = { "/debitReserve", "/debitreserve" }, produces = MediaType.TEXT_PLAIN_VALUE)
	public @ResponseBody String debitReserve(HttpServletRequest request,
			@RequestBody(required = false) String parambody) throws Exception {
		log.info("#-splus::debitReserve::___________________Request____________________________");
		Enumeration params = request.getParameterNames();
		while (params.hasMoreElements()) {
			String name = (String) params.nextElement();
			String value = request.getParameter(name);
			log.info("#-splus::debitReserve::" + name + "=" + value);
		}
		log.info("#-splus::debitReserve::___________________Request____________________________");

		DecimalFormat formatter = new DecimalFormat("0");
		StringBuilderPlus sp = new StringBuilderPlus();
		String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8");
		String reserve_id = URLDecoder.decode(request.getParameter("reserve_id"), "UTF-8");
		String req_id = URLDecoder.decode(request.getParameter("req_id"), "UTF-8");
		String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8");
		String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8");
		String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8");
		String purchase_id = URLDecoder.decode(request.getParameter("purchase_id"), "UTF-8");
		String memberId = cust_id.substring(3, cust_id.length());
		final String LOG_PREFIX = "#-splus::debitReserve::" + memberId + ":::";

		Map trxParam = new HashMap();
		trxParam.put("tranType", "debitReserve");
		trxParam.put("cust_id", cust_id);
		trxParam.put("req_id", req_id);
		trxParam.put("reserve_id", reserve_id);
		trxParam.put("amount", amountStr);
		trxParam.put("agent_id", agent_id);
		trxParam.put("customer_id", customer_id);
		trxParam.put("purchase_id", purchase_id);
		try {
			log.info(LOG_PREFIX+ "parambody {}", parambody);
			org.json.JSONObject paramjson = XML.toJSONObject(parambody);
			log.info(LOG_PREFIX+ "parambody {}", paramjson.toString());
			trxParam.put("data", paramjson.toString());
		} catch (Exception e) {
			log.info(LOG_PREFIX+ "error {}", e.getMessage());
		}

		// 사이트정보
		HashMap ssParam = new HashMap();
		ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16));
		ssParam.put("memberId", cust_id.substring(3, cust_id.length()));
		HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam);
		if (siteApiInfo == null) {
			sp.appendLine("error_code=0");
			sp.append("CustomerNotFound");
			return sp.toString();
		}

		String siteId = siteApiInfo.get("siteId").toString();
		Map authParam = new HashMap();
		authParam.put("memberId", memberId);
		authParam.put("siteId", siteId);

		// 회사정보
		log.info("siteApiInfo {}", siteApiInfo);
		authParam.put("siteIdx", siteApiInfo.get("siteIdx"));

		// 회원정보
		Member member = siteService.getMemberByToken(authParam);
		if (member == null) {
			sp.appendLine("error_code=0");
			sp.append("CustomerNotFound");
			return sp.toString();
		}

		int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString());
		String refId = siteId + reserve_id;
		Date dt = new Date();
		String trxId = "" + siteIdx + dt.getTime() + "1";
		trxParam.put("refId", refId);
		trxParam.put("trx_id", trxId);

		int deReverseCnt = splusService.getDeReverseCnt(trxParam);
		if (deReverseCnt == 0) {
			siteService.insertSplusTran(trxParam);
			siteService.updatesPurchaseId(trxParam);
		}
		double balance = 0.0;
		try {
			String cbData = siteService.getCbData(reserve_id);
			org.codehaus.jettison.json.JSONObject cbDataJson = new org.codehaus.jettison.json.JSONObject(cbData);
			balance = cbDataJson.getDouble("balance");// *0.01;
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::001");
			log.error(LOG_PREFIX+ "Exception::" + e.getMessage());
			balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId);
		}
		
		

		// 구매아이디 보내주기
		try {
			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", refId);
			debit.put("purchaseId", purchase_id);
			
			log.info(LOG_PREFIX+ "Callback Request: "+debit.toString());

			ResponseEntity<String> responseEntity = webClient.post()
					.uri(siteApiInfo.get("siteCbUrl") + "/purchaseId")
					.headers(h -> h.addAll(header))
					.bodyValue(debit.toString())
					.retrieve()
					.toEntity(String.class)
					.block();

			org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject(
					responseEntity.getBody());
			log.info(LOG_PREFIX+ "Callback Response: "+resData.toString());

		} catch (Exception e) {
			log.error(LOG_PREFIX+ "Exception::002");
			log.error(LOG_PREFIX+ "Exception::" + e.getMessage());
		}

		sp.appendLine("error_code=0");
		sp.appendLine("error_message=No Error ");
		sp.appendLine("balance=" + formatter.format(new BigDecimal(balance)));
		sp.appendLine("trx_id=" + trxId);
		
		log.info(LOG_PREFIX + "Response: " + sp.toString());
		return sp.toString(); // 활용한 응답 생성;
	}
	

	// 베팅 예약 크레딧 차람
	@RequestMapping(value = { "/debitCustomer", "/debitcustomer" }, produces = MediaType.TEXT_PLAIN_VALUE)
	public @ResponseBody String debitCustomer(HttpServletRequest request,
			@RequestBody(required = false) String parambody) throws Exception {
		log.info("#-splus::debitCustomer::___________________Request____________________________");
		Enumeration params = request.getParameterNames();
		while (params.hasMoreElements()) {
			String name = (String) params.nextElement();
			String value = request.getParameter(name);
			log.info("#-splus::debitCustomer::" + name + "=" + value);
		}
		log.info("#-splus::debitCustomer::___________________Request____________________________");
		
		DecimalFormat formatter = new DecimalFormat("0");
		StringBuilderPlus sp = new StringBuilderPlus();
		String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8");
		String req_id = URLDecoder.decode(request.getParameter("req_id"), "UTF-8");
		String purchase_id = URLDecoder.decode(request.getParameter("purchase_id"), "UTF-8");
		String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8");
		String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8");
		String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8");
		String memberId = cust_id.substring(3, cust_id.length());
		final String LOG_PREFIX = "#-splus::debitCustomer::" + memberId + ":::";

		Map trxParam = new HashMap();
		trxParam.put("tranType", "debitCustomer");
		trxParam.put("cust_id", cust_id);
		trxParam.put("req_id", req_id);
		trxParam.put("purchase_id", purchase_id);
		trxParam.put("amount", amountStr);
		trxParam.put("agent_id", agent_id);
		trxParam.put("customer_id", cust_id);

		org.json.JSONObject paramjson = new org.json.JSONObject();
		try {
			log.info(LOG_PREFIX+ "parambody {}", parambody);
			paramjson = XML.toJSONObject(parambody);
			log.info(LOG_PREFIX+ "BF::parambody {}", paramjson.toString());

			try {
				// 한글 치환
				org.json.JSONObject credits = paramjson.getJSONObject("Credit");
				org.json.JSONObject purchases = credits.getJSONObject("Purchases");
				org.json.JSONObject purchase = purchases.getJSONObject("Purchase");
				org.json.JSONObject selections = purchase.getJSONObject("Selections");
				// 싱글 베팅

				org.json.JSONObject selection = selections.getJSONObject("Selection");
				if (selection == null) {

					org.json.JSONArray selectionArray = selections.getJSONArray("Selection");
					for (int i = 0; i < selectionArray.length(); i++) {
						org.json.JSONObject line = selectionArray.getJSONObject(i);
						String homeTeam = line.getString("HomeTeam");
						String awayTeam = line.getString("AwayTeam");
						String leagueName = line.getString("LeagueName");

						homeTeam = siteService.getKorName("T", homeTeam);
						awayTeam = siteService.getKorName("T", awayTeam);
						leagueName = siteService.getKorName("L", leagueName);

						line.put("HomeTeamKor", homeTeam);
						line.put("AwayTeamKor", awayTeam);
						line.put("LeagueNameKor", leagueName);
					}

				} else {
					String homeTeam = selection.getString("HomeTeam");
					String awayTeam = selection.getString("AwayTeam");
					String leagueName = selection.getString("LeagueName");

					homeTeam = siteService.getKorName("T", homeTeam);
					awayTeam = siteService.getKorName("T", awayTeam);
					leagueName = siteService.getKorName("L", leagueName);

					selection.put("HomeTeamKor", homeTeam);
					selection.put("AwayTeamKor", awayTeam);
					selection.put("LeagueNameKor", leagueName);

				}

			} catch (Exception e) {
				log.error(LOG_PREFIX+ "tranERR");
			}
			trxParam.put("data", paramjson.toString());
			log.info(LOG_PREFIX+ "AF::parambody {}", paramjson.toString());
		} catch (Exception e) {
			log.info(LOG_PREFIX+ "error {}", e.getMessage());
		}

		// 사이트정보
		HashMap ssParam = new HashMap();
		ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16));
		ssParam.put("memberId", cust_id.substring(3, cust_id.length()));
		HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam);
		if (siteApiInfo == null) {
			sp.appendLine("error_code=0");
			sp.append("CustomerNotFound");
			return sp.toString();
		}

		String siteId = siteApiInfo.get("siteId").toString();
		Map authParam = new HashMap();
		authParam.put("memberId", memberId);
		authParam.put("siteId", siteId);

		// 회사정보
		log.info(LOG_PREFIX+ "siteApiInfo {}", siteApiInfo);
		authParam.put("siteIdx", siteApiInfo.get("siteIdx"));

		// 회원정보
		Member member = siteService.getMemberByToken(authParam);
		if (member == null) {
			sp.appendLine("error_code=0");
			sp.append("CustomerNotFound");
			return sp.toString();
		}

		int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString());
		String reserveId = siteService.getRefIdByPurchaseId(purchase_id);
		String refId = siteId + reserveId;
		Date dt = new Date();
		String trxId = "" + siteIdx + dt.getTime() + "3";
		trxParam.put("trxId", trxId);
		trxParam.put("refId", refId + "#DC");

		siteService.insertSplusTran(trxParam);
		if (member == null) {
			sp.appendLine("error_code=-2");
			sp.append("error_message=not validateToken");

			return sp.toString();
		}
		double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId);
		long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString());
		double amount = Double.parseDouble(amountStr);

		HashMap tranParam = new HashMap();
		tranParam.put("tranId", refId + "#DC");
		tranParam.put("refId", refId + "#DC");
		tranParam.put("siteIdx", siteApiInfo.get("siteIdx"));
		tranParam.put("siteId", siteId);
		tranParam.put("completed", true);
		tranParam.put("memberIdx", member.getMemberIdx());
		tranParam.put("memberId", member.getMemberId());
		tranParam.put("vendorCetegory", "SPORT");
		tranParam.put("vendorIdx", 83);
		tranParam.put("vendorCode", "splus");
		tranParam.put("vendorTranKey", purchase_id + "#DC");
		tranParam.put("gameType", "");
		tranParam.put("gameId", "");
		tranParam.put("gameIdx", "");
		tranParam.put("tranType", "debit");
		tranParam.put("depositAmt", amount);
		tranParam.put("creditAmt", "0");
		tranParam.put("isCancel", "N");
		tranParam.put("isTie", "N");
		tranParam.put("apiStatus", 0);
		tranParam.put("vendorApiId", "");
		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();
		double fakeAmount = amount;// *100;
		debit.put("betId", refId + "#DC");
		debit.put("tranId", refId + "#DC");
		debit.put("userId", member.getMemberId());
		debit.put("vendorIdx", 83);
		debit.put("vendorKey", "SP2");
		debit.put("vendor", "splus");
		debit.put("gameIdx", 1);
		debit.put("gameKey", "");
		debit.put("gameType", "");
		debit.put("gameId", "");
		debit.put("tranType", "debit");
		debit.put("debit", fakeAmount);
		debit.put("credit", 0);
		debit.put("isCancel", 0);
		debit.put("isBonus", 0);
		debit.put("minusBalanceYn", "Y");
		HashMap<String, Object> detailMap = new Gson().fromJson(paramjson.toString(), HashMap.class);
		debit.put("status", "debitCustomer");
		debit.put("detail", detailMap);
		
		log.info(LOG_PREFIX+ "Callback Request: "+debit.toString());

		ResponseEntity<String> responseEntity = webClient.post()
				.uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sports")
				.headers(h -> h.addAll(header))
				.bodyValue(debit.toString())
				.retrieve()
				.toEntity(String.class)
				.block();
		
		org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject(
				responseEntity.getBody());
		log.info(LOG_PREFIX+ "Callback Response: "+resData.toString());
		
		if (resData.getLong("result_code") == 0) {
			sp.appendLine("error_code=0");
			sp.appendLine("error_message=No Error ");
			// sp.appendLine("balance="+formatter.format(new
			// BigDecimal(resData.getDouble("balance") * 0.01)));
			sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance"))));
			sp.appendLine("trx_id=" + trxId);

			tranParam.put("balance", resData.getDouble("balance"));
			int res = siteService.updateCbApi(tranParam);
		} else {
			sp.appendLine("error_code=0");
			sp.appendLine("error_message=error");
			sp.appendLine("balance=" + formatter.format(new BigDecimal(balance)));
			sp.appendLine("trx_id=" + trxId);
		}

		trxParam.put("tranId", tranParam.get("tranId").toString());
		trxParam.put("resData", resData.toString());
		siteService.updateSplusTran(trxParam);
		
		log.info(LOG_PREFIX + "Response: " + sp.toString());
		return sp.toString(); // 활용한 응답 생성;
	}

	private double getBalnce(String LOG_PREFIX, String cbUrl, String memId) {
		LOG_PREFIX = LOG_PREFIX + "==> getBalnce::";
		double balance = 0L;

		try {
			log.info(LOG_PREFIX + "Callback Url :" + cbUrl + "/balance/sports");
			JSONObject members = new JSONObject();
			members.put("userId", memId);
			members.put("decYn", "Y");

			// 회원 머니
			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 = webClient.post()
					.uri(cbUrl + "/balance/sports")
					.headers(h -> h.addAll(header))
					.bodyValue(members.toString())
					.retrieve()
					.toEntity(String.class)
					.block();
			
			log.info(LOG_PREFIX + "status code : {}", responseEntity.getStatusCode());
			log.info(LOG_PREFIX + "body: {}", responseEntity.getBody());
			org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject(
					responseEntity.getBody());
			balance = resData.getDouble("balance");// * 0.01;

		} catch (Exception e) {
			log.error(LOG_PREFIX + "Exception :" + e.getMessage());
		}

		return balance;
	}

	// 베팅 예약 크레딧 차람
	@RequestMapping(value = { "/creditCustomer", "/creditcustomer" }, produces = MediaType.TEXT_PLAIN_VALUE)
	public @ResponseBody String creditCustomer(HttpServletRequest request,
			@RequestBody(required = false) String parambody) throws Exception {
		log.info("#-splus::creditCustomer::___________________Request____________________________");
		Enumeration params = request.getParameterNames();
		while (params.hasMoreElements()) {
			String name = (String) params.nextElement();
			String value = request.getParameter(name);
			log.info("#-splus::creditCustomer::" + name + "=" + value);
		}
		log.info("#-splus::creditCustomer::___________________Request____________________________");

		StringBuilderPlus sp = new StringBuilderPlus();
		String cust_id = URLDecoder.decode(request.getParameter("cust_id"), "UTF-8");
		String purchase_id = URLDecoder.decode(request.getParameter("purchase_id"), "UTF-8");
		String req_id = URLDecoder.decode(request.getParameter("req_id"), "UTF-8");
		String amountStr = URLDecoder.decode(request.getParameter("amount"), "UTF-8");
		String agent_id = URLDecoder.decode(request.getParameter("agent_id"), "UTF-8");
		String customer_id = URLDecoder.decode(request.getParameter("customer_id"), "UTF-8");
		String memberId = cust_id.substring(3, cust_id.length());
		final String LOG_PREFIX = "#-splus::creditCustomer::" + memberId + ":::";

		Map trxParam = new HashMap();
		trxParam.put("tranType", "creditCustomer");
		trxParam.put("cust_id", cust_id);
		trxParam.put("req_id", req_id);
		trxParam.put("purchase_id", purchase_id);
		trxParam.put("amount", amountStr);
		trxParam.put("agent_id", agent_id);
		trxParam.put("customer_id", cust_id);
		
		org.json.JSONObject paramjson = new org.json.JSONObject();
		try {
			log.info(LOG_PREFIX+ "parambody {}", parambody);
			paramjson = XML.toJSONObject(parambody);
			log.info(LOG_PREFIX+ "BF::parambody {}", paramjson.toString());

			try {
				// 한글 치환
				org.json.JSONObject credits = paramjson.getJSONObject("Credit");
				org.json.JSONObject purchases = credits.getJSONObject("Purchases");
				org.json.JSONObject purchase = purchases.getJSONObject("Purchase");
				org.json.JSONObject selections = purchase.getJSONObject("Selections");
				// 싱글 베팅

				org.json.JSONObject selection = selections.getJSONObject("Selection");
				if (selection == null) {

					org.json.JSONArray selectionArray = selections.getJSONArray("Selection");
					for (int i = 0; i < selectionArray.length(); i++) {
						org.json.JSONObject line = selectionArray.getJSONObject(i);
						String homeTeam = line.getString("HomeTeam");
						String awayTeam = line.getString("AwayTeam");
						String leagueName = line.getString("LeagueName");

						homeTeam = siteService.getKorName("T", homeTeam);
						awayTeam = siteService.getKorName("T", awayTeam);
						leagueName = siteService.getKorName("L", leagueName);

						line.put("HomeTeamKor", homeTeam);
						line.put("AwayTeamKor", awayTeam);
						line.put("LeagueNameKor", leagueName);
					}

				} else {
					String homeTeam = selection.getString("HomeTeam");
					String awayTeam = selection.getString("AwayTeam");
					String leagueName = selection.getString("LeagueName");

					homeTeam = siteService.getKorName("T", homeTeam);
					awayTeam = siteService.getKorName("T", awayTeam);
					leagueName = siteService.getKorName("L", leagueName);

					selection.put("HomeTeamKor", homeTeam);
					selection.put("AwayTeamKor", awayTeam);
					selection.put("LeagueNameKor", leagueName);

				}

			} catch (Exception e) {
				log.error(LOG_PREFIX+ "tranERR");
			}

			trxParam.put("data", paramjson.toString());
			log.info(LOG_PREFIX+ "AF::parambody {}", paramjson.toString());
		} catch (Exception e) {
			log.info(LOG_PREFIX+ "error {}", e.getMessage());
		}

		// 사이트정보
		HashMap ssParam = new HashMap();
		ssParam.put("siteIdx", Integer.parseInt(cust_id.substring(0, 3), 16));
		ssParam.put("memberId", cust_id.substring(3, cust_id.length()));
		HashMap siteApiInfo = siteService.getSiteApiInfo(ssParam);
		if (siteApiInfo == null) {
			sp.appendLine("error_code=0");
			sp.append("CustomerNotFound");
			return sp.toString();
		}

		String siteId = siteApiInfo.get("siteId").toString();
		Map authParam = new HashMap();
		authParam.put("memberId", memberId);
		authParam.put("siteId", siteId);

		// 회사정보
		log.info(LOG_PREFIX+ "siteApiInfo {}", siteApiInfo);
		authParam.put("siteIdx", siteApiInfo.get("siteIdx"));

		// 회원정보
		Member member = siteService.getMemberByToken(authParam);
		if (member == null) {
			sp.appendLine("error_code=0");
			sp.append("CustomerNotFound");
			return sp.toString();
		}

		int siteIdx = Integer.parseInt(siteApiInfo.get("siteIdx").toString());
		String reserveId = siteService.getRefIdByPurchaseId(purchase_id);
		String refId = siteId + reserveId;
		Date dt = new Date();
		String trxId = "" + dt.getTime() + "4";
		trxParam.put("trxId", trxId);
		trxParam.put("refId", refId);

		double balance = getBalnce(LOG_PREFIX, siteApiInfo.get("siteCbUrl").toString(), memberId);
		long targetSiteCredit = siteService.getSiteCredit(siteApiInfo.get("siteId").toString());
		double amount = Double.parseDouble(amountStr);

		HashMap tranParam = new HashMap();
		tranParam.put("tranId", req_id + "#CC");
		tranParam.put("refId", refId);
		tranParam.put("siteIdx", siteApiInfo.get("siteIdx"));
		tranParam.put("siteId", siteId);
		tranParam.put("completed", true);
		tranParam.put("memberIdx", member.getMemberIdx());
		tranParam.put("memberId", member.getMemberId());
		tranParam.put("vendorCetegory", "SPORT");
		tranParam.put("vendorIdx", 83);
		tranParam.put("vendorCode", "splus");
		tranParam.put("vendorTranKey", purchase_id + "#CC");
		tranParam.put("gameType", "");
		tranParam.put("gameId", "");
		tranParam.put("gameIdx", "");
		tranParam.put("tranType", "credit");
		tranParam.put("depositAmt", "0");
		tranParam.put("creditAmt", amount);
		tranParam.put("isCancel", "N");
		tranParam.put("isTie", "N");
		tranParam.put("apiStatus", 0);
		tranParam.put("vendorApiId", "");
		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();
		double fakeAmount = amount;// *100;
		debit.put("betId", refId);
		debit.put("tranId", req_id + "#CC");
		debit.put("userId", member.getMemberId());
		debit.put("vendorIdx", 83);
		debit.put("vendorKey", "SP2");
		debit.put("vendor", "splus");
		debit.put("gameIdx", 1);
		debit.put("gameKey", "");
		debit.put("gameType", "");
		debit.put("gameId", "");
		debit.put("tranType", "credit");
		debit.put("debit", 0);
		debit.put("credit", fakeAmount);
		debit.put("isCancel", 0);
		debit.put("isBonus", 0);
		debit.put("decYn", "Y");
		HashMap<String, Object> detailMap = new Gson().fromJson(paramjson.toString(), HashMap.class);
		debit.put("status", "end");
		debit.put("detail", detailMap);
		
		log.info(LOG_PREFIX+ "Callback Request: "+debit.toString());

		ResponseEntity<String> responseEntity = webClient.post()
				.uri(siteApiInfo.get("siteCbUrl") + "/changebalance/sports")
				.headers(h -> h.addAll(header))
				.bodyValue(debit.toString())
				.retrieve()
				.toEntity(String.class)
				.block();

		org.codehaus.jettison.json.JSONObject resData = new org.codehaus.jettison.json.JSONObject(
				responseEntity.getBody());
		log.info(LOG_PREFIX+ "Callback Response: "+resData.toString());

		log.info(LOG_PREFIX+ "status code : {}", responseEntity.getStatusCode());
		log.info(LOG_PREFIX+ "body: {}", responseEntity.getBody());
		
		DecimalFormat formatter = new DecimalFormat("0");
		if (resData.getLong("result_code") == 0) {
			sp.appendLine("error_code=0");
			sp.appendLine("error_message=No Error ");
			// sp.appendLine("balance="+formatter.format(new
			// BigDecimal(resData.getDouble("balance") * 0.01)));
			sp.appendLine("balance=" + formatter.format(new BigDecimal(resData.getDouble("balance"))));
			sp.appendLine("trx_id=" + trxId);

			tranParam.put("balance", resData.getDouble("balance"));
			int res = siteService.updateCbApi(tranParam);
		} else {
			sp.appendLine("error_code=0");
			sp.appendLine("error_message=error");
			sp.appendLine("balance=" + formatter.format(new BigDecimal(balance)));
			sp.appendLine("trx_id=" + trxId);
		}

		trxParam.put("tranId", tranParam.get("tranId").toString());
		trxParam.put("resData", resData.toString());
		siteService.updateSplusTran(trxParam);

		splusService.updateSplus(tranParam, paramjson);
		
		log.info(LOG_PREFIX+ "Response: "+sp.toString());
		return sp.toString(); // 활용한 응답 생성;
	}

	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();

	}

}
