package com.bb.front;

import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.UUID;

import org.apache.http.conn.ConnectTimeoutException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
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.client.ResourceAccessException;

import com.bb.service.CallBackService;
import com.bb.service.SiteService;

import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;

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

	@Autowired
	SiteService siteService;
	
	@Autowired
	CallBackService callBackService;
	
	
	@ResponseBody
	@RequestMapping(path = "/balance")
	public ResponseEntity<JSONObject> balance(HttpServletRequest request, @RequestBody net.sf.json.JSONObject requestBody) throws Exception {
		JSONObject resData  = new JSONObject();
		HttpStatus httpStatus = null;
		String userId = requestBody.getString("userId");

		long siteIdx = Long.parseLong(userId.substring(0, 3), 16);
		String memberId = userId.substring(3, userId.length());
		final String LOG_PREFIX = "#-CB::PBG::balance::"+memberId+":::";
		
		try {
			//사이트정보
			HashMap sParam = new HashMap();
			sParam.put("siteIdx", siteIdx);
			sParam.put("memberId",  memberId);
			
			HashMap siteApiInfo = siteService.getSiteApiInfo(sParam);
			if(siteApiInfo==null) {
				log.error(LOG_PREFIX+ "Error Msg: NOT_FOUND_SITE_INFO");				
				return new ResponseEntity<JSONObject>(resData, HttpStatus.INTERNAL_SERVER_ERROR);
			}
			
			org.codehaus.jettison.json.JSONObject member = new org.codehaus.jettison.json.JSONObject();
			member.put("userId", memberId);
			log.info(LOG_PREFIX+ "Callback URL::" + siteApiInfo.get("siteCbUrl")+"/balance");
			log.info(LOG_PREFIX+ "Callback Param::" + member.toString());
		
			member.put("userId", memberId);			
			org.codehaus.jettison.json.JSONObject resBalancedData  = callBackService.getBalance(siteApiInfo, member);
			if(resBalancedData == null) {
				log.error(LOG_PREFIX+ "Error Msg: BALANCE_CALLBACK_ERROR");				
				return new ResponseEntity<JSONObject>(resData, HttpStatus.INTERNAL_SERVER_ERROR);
			}
			int balance = resBalancedData.getInt("balance");
			resData.put("success", true);
			
			JSONObject data  = new JSONObject();
			
			data.put("balance", balance);
			resData.put("data", data);
			httpStatus = HttpStatus.OK;
			
		} catch (ResourceAccessException rae) {
            if(rae.getCause() instanceof ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "[ConnectTimeoutException]"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof SocketTimeoutException) {
            	log.error(LOG_PREFIX+ "[SocketTimeoutException]"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "[InterruptedException]"+rae.getMessage());
            }
            
            log.error(LOG_PREFIX+ "[ResourceAccessException]"+rae.getMessage());
            httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
        	resData.put("success", false);
			
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "[Exception]"+e.getMessage());
			resData.put("success", false);
			httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
		}
		
		ResponseEntity<JSONObject> res = new ResponseEntity<JSONObject>(resData, httpStatus);
		log.info(LOG_PREFIX+ "Response: "+resData.toString());
		
		return new ResponseEntity<JSONObject>(resData, HttpStatus.OK);
	}
	
	
	@ResponseBody
	@PostMapping(path = "/bet", produces = "application/json") // JSON만 생산	
	public ResponseEntity<JSONObject> bet(HttpServletRequest request, @RequestBody JSONObject requestBody) throws Exception {
		
		String userId = requestBody.getString("userId");
		//JSONObject transaction =  requestBody.getJSONObject("transaction");
		String tranType = "bet";
		long siteIdx = Long.parseLong(userId.substring(0, 3), 16);
		String memberId = userId.substring(3, userId.length());
		final String LOG_PREFIX = "#-CB::PBG::bet::"+memberId+"::"+tranType+":::";
		log.info(LOG_PREFIX+ "Request Body: "+requestBody.toString());
		
		JSONObject resData  = new JSONObject();
		HttpStatus httpStatus = null;
		
		try {
			//사이트정보
			HashMap sParam = new HashMap();
			sParam.put("siteIdx", siteIdx);
			sParam.put("memberId",  memberId);
			sParam.put("vendor", "pbg");
			sParam.put("vendorGameCode", "pbg");
			HashMap siteApiInfo = siteService.getSiteVendorInfo(sParam);
			if(siteApiInfo==null) {
				log.error(LOG_PREFIX+ "siteApiInfo is null "+tranType+" "+userId+"::"+ "Error Msg: NOT_FOUND_SITE_INFO");				
				return new ResponseEntity<JSONObject>(resData, HttpStatus.INTERNAL_SERVER_ERROR);
			}
			
			long amount = requestBody.getLong("betAmt");
		
			long memberIdx = Long.parseLong(siteApiInfo.get("memberIdx").toString());
			long vendorIdx = Long.parseLong(siteApiInfo.get("vendorIdx").toString());
			
			String siteId = siteApiInfo.get("siteId").toString();
			String vendorApiId = siteApiInfo.get("vendorApiId").toString();
			String vendorKey = siteApiInfo.get("vendorKey").toString();
			
			// 2025-06-10T07:12:54.355000Z
			
			String betDateTimeStr = requestBody.getString("betDate")+".000";
			
			
			if(amount < 0) {
				long siteCredit = Long.parseLong(siteApiInfo.get("credit").toString());
				if(siteCredit < amount) {
					log.error(LOG_PREFIX+ "SITE_IDX: "+siteIdx+" NO_SITE_CREDIT");
					return new ResponseEntity<JSONObject>(resData, HttpStatus.INTERNAL_SERVER_ERROR);
				}
				
				long siteMaxBet = Long.parseLong(siteApiInfo.get("siteMaxBet").toString());
				if(siteMaxBet < amount) {
					log.error(LOG_PREFIX+ "SITE_IDX: "+siteIdx+"MAX_BET_AMOUNT_OVER");
					return new ResponseEntity<JSONObject>(resData, HttpStatus.INTERNAL_SERVER_ERROR);
				}
			}
			UUID uuid = UUID.randomUUID();
			String uid = uuid.toString();
			
			String vendorTranKey =  requestBody.getString("gameId")+uid;
			String tranId = requestBody.getString("gameId")+uid;
			String betId = requestBody.getString("gameId");
			
			String gameName = requestBody.getString("gameType") +"_"+requestBody.getString("betType");
			String gameId = "1";
			String gameType = "minigame";
			
						
			HashMap tranParam = new HashMap();
			tranParam.put("tranId", tranId);
			tranParam.put("refId",  betId);
			tranParam.put("siteIdx", siteIdx);
			tranParam.put("siteId", siteId);
			tranParam.put("memberIdx", memberIdx);
			tranParam.put("memberId", memberId);
			tranParam.put("vendorCetegory", "MINIGAME");
			tranParam.put("vendorIdx", vendorIdx);
			tranParam.put("vendorCode", "pbg");
			tranParam.put("vendorTranKey", vendorTranKey);
			tranParam.put("gameType", gameType);
			tranParam.put("gameId", "");
			tranParam.put("gameIdx", gameName);
			
			tranParam.put("tranType", "debit");
			tranParam.put("depositAmt", Math.abs(amount));
			tranParam.put("creditAmt", "0");
		
		//tranParam.put("isCancel", "N");
	
			tranParam.put("isCancel", "N");
		
			tranParam.put("isTie", "N");
			tranParam.put("apiStatus", 0);
			tranParam.put("vendorApiId", vendorApiId);
			log.info(LOG_PREFIX+ "-----INSERT_BET_START-----");
			siteService.commonBetinsert(tranParam);
			log.info(LOG_PREFIX+ "-----INSERT_BET_END-----");
			
			org.codehaus.jettison.json.JSONObject callBackObj = new org.codehaus.jettison.json.JSONObject();
			callBackObj.put("betId", betId);
			callBackObj.put("tranId", tranId);
			callBackObj.put("userId", memberId);
			callBackObj.put("vendorIdx", vendorIdx);
			callBackObj.put("vendorKey", vendorKey);
			callBackObj.put("vendor", "pbg");
			callBackObj.put("gameIdx", 1);
			callBackObj.put("gameKey", gameName);
			callBackObj.put("gameId", gameId);
			callBackObj.put("gameType", gameType);
			
			callBackObj.put("tranType", "debit");
			callBackObj.put("debit", Math.abs(amount));
			callBackObj.put("credit", 0);		
			callBackObj.put("isCancel", 0);	
			callBackObj.put("isBonus", 0);
			
			callBackObj.put("requestAt", "");
			log.info(LOG_PREFIX+ "SEND_BET request body: " + callBackObj.toString());
			org.codehaus.jettison.json.JSONObject resTranData = callBackService.changeBalance(LOG_PREFIX, siteApiInfo, callBackObj);
			log.info(LOG_PREFIX+ "SEND_BET response body: " + resTranData.toString());
			
			if(resTranData.getLong("result_code") == 0) {
				// 성공
				tranParam.put("balance", resTranData.getLong("balance"));
				int res = siteService.updateCbApi(tranParam);
				log.info(LOG_PREFIX+ "UPDATE_CALLBACK_API_STATUS END");
				
				long balance = resTranData.getLong("balance");
				JSONObject data = new JSONObject();
				data.put("balance", balance);
				
				resData.put("success", true);
				resData.put("data", data);
				httpStatus = HttpStatus.OK;
				
			} else if(resTranData.getLong("result_code") == 98) {
				// 중복
				
				
				resData.put("success", false);
				
				httpStatus = HttpStatus.OK;
			} else {
				// 실패
				log.error(LOG_PREFIX+ "CALLBACK_ERROR");
				httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
			}
			
		} catch (ResourceAccessException rae) {
            if(rae.getCause() instanceof ConnectTimeoutException) {
            	log.error(LOG_PREFIX+  "::"+userId+"::"+ "[ConnectTimeoutException]"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof SocketTimeoutException) {
            	log.error(LOG_PREFIX+ "::"+userId+"::"+ "[SocketTimeoutException]"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "::"+userId+"::"+ "[InterruptedException]"+rae.getMessage());
            }
            
            log.error(LOG_PREFIX+  "::"+userId+"::"+ "[ResourceAccessException]"+rae.getMessage());
			
            httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
            resData.put("success", false);
			
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "#-PBG::::"+userId+"::"+ "[Exception]"+e.getMessage());
			
			httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
			 resData.put("success", false);
		}
		
		ResponseEntity<JSONObject> res = new ResponseEntity<JSONObject>(resData, httpStatus);
		log.info(LOG_PREFIX+ "::"+userId+"::"+ "Response: "+resData.toString());
		
		return new ResponseEntity<JSONObject>(resData, httpStatus);
	}
	
	@ResponseBody
	@PostMapping(path = "/result", produces = "application/json") // JSON만 생산	
	public ResponseEntity<JSONObject> result(HttpServletRequest request, @RequestBody JSONObject requestBody) throws Exception {
		
		String userId = requestBody.getString("userId");
		//JSONObject transaction =  requestBody.getJSONObject("transaction");
		String tranType = "result";
		long siteIdx = Long.parseLong(userId.substring(0, 3), 16);
		String memberId = userId.substring(3, userId.length());
		final String LOG_PREFIX = "#-CB::PBG::RESULT::"+memberId+"::"+tranType+":::";
		log.info(LOG_PREFIX+ "Request Body: "+requestBody.toString());
		
		JSONObject resData  = new JSONObject();
		HttpStatus httpStatus = null;
		
		net.sf.json.JSONArray resultList = requestBody.getJSONArray("result");
		Long lastBalance =0L;
		
		try {
			for(int r=0;r<resultList.size();r++) {
				try {
					JSONObject tranbet = resultList.getJSONObject(r);
					//사이트정보
					HashMap sParam = new HashMap();
					sParam.put("siteIdx", siteIdx);
					sParam.put("memberId",  memberId);
					sParam.put("vendor", "pbg");
					sParam.put("vendorGameCode", "pbg");
					HashMap siteApiInfo = siteService.getSiteVendorInfo(sParam);
					if(siteApiInfo==null) {
						log.error(LOG_PREFIX+ "siteApiInfo is null "+tranType+" "+userId+"::"+ "Error Msg: NOT_FOUND_SITE_INFO");				
						return new ResponseEntity<JSONObject>(resData, HttpStatus.INTERNAL_SERVER_ERROR);
					}
					
					long amount = tranbet.getLong("betWinAmt");
				
					long memberIdx = Long.parseLong(siteApiInfo.get("memberIdx").toString());
					long vendorIdx = Long.parseLong(siteApiInfo.get("vendorIdx").toString());
					
					String siteId = siteApiInfo.get("siteId").toString();
					String vendorApiId = siteApiInfo.get("vendorApiId").toString();
					String vendorKey = siteApiInfo.get("vendorKey").toString();
					
					// 2025-06-10T07:12:54.355000Z
					
					String betDateTimeStr = tranbet.getString("betDate")+".000";
					
				
					UUID uuid = UUID.randomUUID();
					String uid = uuid.toString();
					
					String vendorTranKey =  tranbet.getString("gameId")+uid;
					String tranId = tranbet.getString("gameId")+uid;
					String betId = tranbet.getString("gameId");
					
					String gameName = tranbet.getString("gameType") +"_"+tranbet.getString("betType");
					String gameId = "1";
					String gameType = "minigame";
					
								
					HashMap tranParam = new HashMap();
					tranParam.put("tranId", tranId);
					tranParam.put("refId",  betId);
					tranParam.put("siteIdx", siteIdx);
					tranParam.put("siteId", siteId);
					tranParam.put("memberIdx", memberIdx);
					tranParam.put("memberId", memberId);
					tranParam.put("vendorCetegory", "MINIGAME");
					tranParam.put("vendorIdx", vendorIdx);
					tranParam.put("vendorCode", "pbg");
					tranParam.put("vendorTranKey", vendorTranKey);
					tranParam.put("gameType", gameType);
					tranParam.put("gameId", "");
					tranParam.put("gameIdx", gameName);
					
					tranParam.put("tranType", "credit");
					tranParam.put("depositAmt", 0);
					tranParam.put("creditAmt", Math.abs(amount));
				
				//tranParam.put("isCancel", "N");
			
					tranParam.put("isCancel", "N");
				
					tranParam.put("isTie", "N");
					tranParam.put("apiStatus", 0);
					tranParam.put("vendorApiId", vendorApiId);
					log.info(LOG_PREFIX+ "-----RESULT-----");
					siteService.commonBetinsert(tranParam);
					log.info(LOG_PREFIX+ "-----INSERT_RESULT_END-----");
					
					org.codehaus.jettison.json.JSONObject callBackObj = new org.codehaus.jettison.json.JSONObject();
					callBackObj.put("betId", betId);
					callBackObj.put("tranId", tranId);
					callBackObj.put("userId", memberId);
					callBackObj.put("vendorIdx", vendorIdx);
					callBackObj.put("vendorKey", vendorKey);
					callBackObj.put("vendor", "pbg");
					callBackObj.put("gameIdx", 1);
					callBackObj.put("gameKey", gameName);
					callBackObj.put("gameId", gameId);
					callBackObj.put("gameType", gameType);
					
					callBackObj.put("tranType", "credit");
					callBackObj.put("debit", 0);
					callBackObj.put("credit", Math.abs(amount));		
					callBackObj.put("isCancel", 0);	
					callBackObj.put("isBonus", 0);
					
					callBackObj.put("requestAt", "");
					log.info(LOG_PREFIX+ "SEND_RESULT request body: " + callBackObj.toString());
					org.codehaus.jettison.json.JSONObject resTranData = callBackService.changeBalance(LOG_PREFIX, siteApiInfo, callBackObj);
					log.info(LOG_PREFIX+ "SEND_RESULT response body: " + resTranData.toString());
				
					if(resTranData.getLong("result_code") == 0) {
						// 성공
						tranParam.put("balance", resTranData.getLong("balance"));
						int res = siteService.updateCbApi(tranParam);
						log.info(LOG_PREFIX+ "UPDATE_CALLBACK_API_STATUS END");
						
						lastBalance = resTranData.getLong("balance");
						
						
					} else if(resTranData.getLong("result_code") == 98) {
						// 중복					
						//resData.put("success", false);					
					} else {
						// 실패
					//	log.error(LOG_PREFIX+ "CALLBACK_ERROR");
						httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
					}
					Thread.sleep(300);
				} catch (Exception e) {
					log.error(LOG_PREFIX+ "#-POWER RESULT ERROR::::"+userId+"::"+ "[Exception]"+e.getMessage());
					
					//httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
					// resData.put("success", false);
				}
			}
			
			JSONObject data = new JSONObject();
			data.put("balance", lastBalance);
			
			resData.put("success", true);
			resData.put("data", data);
			httpStatus = HttpStatus.OK;
			
		} catch (ResourceAccessException rae) {
            if(rae.getCause() instanceof ConnectTimeoutException) {
            	log.error(LOG_PREFIX+  "::"+userId+"::"+ "[ConnectTimeoutException]"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof SocketTimeoutException) {
            	log.error(LOG_PREFIX+ "::"+userId+"::"+ "[SocketTimeoutException]"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "::"+userId+"::"+ "[InterruptedException]"+rae.getMessage());
            }
            
            log.error(LOG_PREFIX+  "::"+userId+"::"+ "[ResourceAccessException]"+rae.getMessage());
			
            httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
            resData.put("success", false);
			
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "#-Grand::::"+userId+"::"+ "[Exception]"+e.getMessage());
			
			httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
			 resData.put("success", false);
		}
		
		ResponseEntity<JSONObject> res = new ResponseEntity<JSONObject>(resData, httpStatus);
		log.info(LOG_PREFIX+ "::"+userId+"::"+ "Response: "+resData.toString());
		
		return new ResponseEntity<JSONObject>(resData, httpStatus);
	}
	
}
