package com.bb.front;

import java.text.SimpleDateFormat;
import java.util.HashMap;

import jakarta.servlet.http.HttpServletRequest;

import org.codehaus.jettison.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.bb.jwt.JwtManager;
import com.bb.model.BombAuthVO;
import com.bb.model.BombReponseVo;
import com.bb.model.CommonParam;
import com.bb.model.Member;
import com.bb.model.PlayParam;
import com.bb.service.CallBackService;
import com.bb.service.SiteService;
import com.bb.util.AesUtil;
import com.google.gson.Gson;

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

@RestController
@Slf4j
@RequestMapping("/api/cb/pbomb")
@RequiredArgsConstructor
@SecurityRequirement(name = "Authorization")
public class CallBackBombController {

	// https://oprvender.com/api/cb/live

	@Autowired
	private final JwtManager jwtManager;

	@Autowired
	SiteService siteService;

	@Autowired
	CallBackService callBackService;

	@ResponseBody
	@RequestMapping(value = "/loginAuth", method = RequestMethod.POST)
	public BombReponseVo minegameLoginAuth(@RequestBody BombAuthVO bombAuthVO, HttpServletRequest request)
			throws Exception {
		BombReponseVo bombReponseVo = new BombReponseVo();
		log.info("#bomb::loginAuth::" + "bombAuthVO" + bombAuthVO.toString());
		Gson gson = new Gson();
		bombAuthVO = gson.fromJson(AesUtil.getAES128_Decode(bombAuthVO.getEp()), BombAuthVO.class);
		log.info("#bomb::loginAuth::" + "dec bombAuthVO" + bombAuthVO.toString());

		HashMap memParam = new HashMap();
		memParam.put("bombAccId", bombAuthVO.getLoginToken());

		Member member = siteService.getMemByBombAccId(memParam);

		try {
			String accID = bombAuthVO.getAccID();
			String token = bombAuthVO.getLoginToken();

			log.info("#bomb::loginAuth::" + accID);
			log.info("#bomb::loginAuth::" + token);
			log.info("#bomb::loginAuth::" + member);

			if (member.getBombAccId().equals(token)) {

				log.info("#bomb::loginAuth::" + 1111111);

				bombReponseVo.setAccId(accID);
				bombReponseVo.setNickName(member.getMemberNick());
				bombReponseVo.setCode(0);
				bombReponseVo.setDemo(false);

				// 밸런스 가져오기

				HashMap sParam = new HashMap();
				// String[] usrinfo = accID.split("_");

				// String memberId ="";
				// String siteId ="";
				sParam.put("siteIdx", Integer.parseInt(accID.substring(0, 3), 16));
				sParam.put("memberId", accID.substring(3, accID.length()));
				String memberId = accID.substring(3, accID.length());

				HashMap siteApiInfo = siteService.getSiteApiInfo(sParam);

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

				// 밸런스가져오기
				JSONObject resData = callBackService.getBalance(siteApiInfo, parammember);
				if(resData == null) {
					log.info("#bomb::debit::" + "balance callback error");
					bombReponseVo.setCode(-1);
					return bombReponseVo;
				}

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

				if (resData.getInt("result_code") == 0) {

					if ("Y".equals(siteApiInfo.getOrDefault("bombDecYn", "").toString())) {
						bombReponseVo.setBalance("" + (resData.getDouble("balance") * 0.01));
					} else {
						bombReponseVo.setBalance("" + resData.getDouble("balance"));
					}
				} else {
					bombReponseVo.fail();
				}

			} else {
				bombReponseVo.fail();
			}
		} catch (Exception e) {
			bombReponseVo.fail();
		}

		log.info("#bomb::loginAuth::" + "BOMB AUTH RESbody: {}", bombReponseVo);
		return bombReponseVo;
	}

	@ResponseBody
	@RequestMapping(value = "/bet", method = RequestMethod.POST)
	public BombReponseVo minegameEncBet(@RequestBody BombAuthVO bombAuthVO, HttpServletRequest request)
			throws Exception {
		BombReponseVo bombReponseVo = new BombReponseVo();

		Gson gson = new Gson();
		bombAuthVO = gson.fromJson(AesUtil.getAES128_Decode(bombAuthVO.getEp()), BombAuthVO.class);

		JSONObject obj = new JSONObject();

		HashMap memParam = new HashMap();
		memParam.put("bombAccId", bombAuthVO.getLoginToken());
		Member member = siteService.getMemByBombAccId(memParam);

		try {
			String accID = bombAuthVO.getAccID();
			String userID = bombAuthVO.getUserID();
			String token = bombAuthVO.getLoginToken();
			String transferId = bombAuthVO.getTransferId();
			Integer roomNo = bombAuthVO.getRoomNo();
			double betAmount = (double) bombAuthVO.getAmount();

			log.info("#bomb::debit::" + "bombgame bet accID : " + accID);
			log.info("#bomb::debit::" + "bombgame bet userID : " + userID);
			log.info("#bomb::debit::" + "bombgame bet token : " + token);
			log.info("#bomb::debit::" + "bombgame bet roomNo : " + roomNo);
			log.info("#bomb::debit::" + "bombgame bet transferId : " + transferId);
			log.info("#bomb::debit::" + "bombgame bet betAmount : " + betAmount);

			// 밸런스 가져오기

			HashMap sParam = new HashMap();

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

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

			// 사이트에 크레딧이 없을경우 에러 보냄 베팅막음
			long targetSiteCredit = siteService.getSiteCredit(siteId);
			if (targetSiteCredit < betAmount) {
				log.info("#bomb::debit::" + "no siteCredit");
				bombReponseVo.setCode(-1);
				return bombReponseVo;
			}

			// 최대베팅액 (userMaxBet 우선 적용)
			sParam.put("vendorIdx", 5);
			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("#bomb::debit::MaxBet Info - siteMaxBet: " + maxBet + ", userMaxBet: " + userMaxBet + ", finalMaxBet: " + finalMaxBet);

			if (betAmount > finalMaxBet) {
				log.info("#bomb::debit::" + "Over bet money - finalMaxBet: " + finalMaxBet);
				bombReponseVo.setCode(-1);
				return bombReponseVo;
			}

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

			log.info("#bomb::debit::" + siteApiInfo);
			JSONObject resData2 = callBackService.getBalance(siteApiInfo, parammember);
			if(resData2 == null) {
				log.info("#bomb::debit::" + "balance callback error");
				bombReponseVo.setCode(-1);
				return bombReponseVo;
			}

			if (resData2.getInt("result_code") == 0) {

				if ("Y".equals(siteApiInfo.getOrDefault("bombDecYn", "").toString())) {
					bombReponseVo.setBalance("" + (resData2.getDouble("balance") * 0.01));
				} else {
					bombReponseVo.setBalance("" + resData2.getDouble("balance"));
				}

			} else {
				bombReponseVo.fail();
			}

			if (betAmount < 0) {

				bombReponseVo.setCode(-99);

			} else {
				if (member.getBombAccId().equals(token)) {
					double curCashAmount = resData2.getDouble("balance");

					if (curCashAmount >= betAmount) {

						// betAmount 만큼 cashAmt 차감
						// memberService.updateMineMemCashAmt(bombAuthVO);

						HashMap tranParam = new HashMap();
						tranParam.put("tranId", siteId + "D" + bombAuthVO.getTransferId());
						tranParam.put("refId", siteId + bombAuthVO.getTransferId());
						tranParam.put("siteIdx", siteApiInfo.get("siteIdx"));

						tranParam.put("siteId", siteId);

						tranParam.put("memberIdx", siteApiInfo.get("memberIdx"));
						tranParam.put("memberId", memberId);
						tranParam.put("vendorCetegory", "MINIGAME");
						tranParam.put("vendorIdx", 5);
						tranParam.put("vendorCode", "tpabomb");
						tranParam.put("vendorTranKey", bombAuthVO.getTransferId());
						tranParam.put("gameType", "");
						tranParam.put("gameId", "");
						tranParam.put("gameIdx", ""+roomNo);
						tranParam.put("tranType", "debit");
						tranParam.put("depositAmt", betAmount);
						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("M01");
							commonParam.setPlayParam(param);
							HashMap venderInfo = siteService.getVenderApiInfo(commonParam);
							tranParam.put("vendorApiId", venderInfo.get("vendorApiId").toString());
						} catch (Exception e) {
							log.info("#bomb::debit::" + "VI ERR:" + e.toString());
						}
						siteService.commonBetinsert(tranParam);

					
						JSONObject debit = new JSONObject();
						debit.put("betId", siteId + bombAuthVO.getTransferId());
						debit.put("tranId", siteId + "D" + bombAuthVO.getTransferId());
						debit.put("userId", memberId);
						debit.put("vendorIdx", 5);
						debit.put("vendorKey", "M01");
						debit.put("vendor", "tpabomb");
						debit.put("gameIdx", 1);
						debit.put("gameKey", ""+roomNo);
						debit.put("gameId", "");
						debit.put("gameType", "");
						debit.put("tranType", "debit");

						if ("Y".equals(siteApiInfo.getOrDefault("bombDecYn", "").toString())) {
							Double betAmountD = betAmount * 100;
							debit.put("debit", betAmountD.longValue());
						} else {
							debit.put("debit", betAmount);
						}

						debit.put("credit", 0);
						debit.put("isCancel", 0);
						debit.put("isBonus", 0);
						SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
						long nDate = System.currentTimeMillis();
						String betDateTimeStr = sdf.format(nDate);
						debit.put("requestAt", betDateTimeStr);

						JSONObject resData = callBackService.changeBalance("#bomb::", siteApiInfo, debit);
						
						log.info("#bomb::debit::" + "result_Dcode: {}", resData.getInt("result_code"));

						if (resData.getLong("result_code") == 0) {
							bombReponseVo.setCode(0);
							bombReponseVo.setBalance("" + resData.getDouble("balance"));

							if ("Y".equals(siteApiInfo.getOrDefault("bombDecYn", "").toString())) {
								bombReponseVo.setBalance("" + (resData.getDouble("balance") * 0.01));
							} else {
								bombReponseVo.setBalance("" + resData.getDouble("balance"));
							}
							
							tranParam.put("balance", bombReponseVo.getBalance());
							int res = siteService.updateCbApi(tranParam);
							log.info("#bomb::debit::" + "result_Dcode: {}2");

						} else if (resData.getLong("result_code") == 80) {
							bombReponseVo.setCode(-1);

						} else if (resData.getLong("result_code") == 98) {
							log.info("#bomb::debit::" + "result_Dcode 98: {}1");
							bombReponseVo.setCode(-1);
						} else {
							bombReponseVo.setCode(-1);
						}

					} else {
						bombReponseVo.setCode(-1);
						obj.put("code", -1);
						log.info("#bomb::debit::" + "bombgame info curr cash : " + curCashAmount + ", reqest : "
								+ betAmount);
					}

				} else {
					bombReponseVo.setCode(-99);
					log.info("#bomb::debit::" + "bombgame info token : " + member.getBombAccId() + ", reqest : "
							+ token);
				}
			}

		} catch (Exception e) {
			bombReponseVo.setCode(-1);
			log.info("#bomb::debit::" + e);
		}

		return bombReponseVo;
	}

	@ResponseBody
	@RequestMapping(value = { "/payout", "/end" }, method = RequestMethod.POST)
	public BombReponseVo minegameEncCredit(@RequestBody BombAuthVO bombAuthVO, HttpServletRequest request)
			throws Exception {
		BombReponseVo bombReponseVo = new BombReponseVo();
		log.info("#bomb::credit::" + "bombAuthVO" + bombAuthVO.toString());
		Gson gson = new Gson();
		bombAuthVO = gson.fromJson(AesUtil.getAES128_Decode(bombAuthVO.getEp()), BombAuthVO.class);

		JSONObject obj = new JSONObject();

		HashMap memParam = new HashMap();
		memParam.put("bombAccId", bombAuthVO.getLoginToken());
		Member member = siteService.getMemByBombAccId(memParam);

		try {
			String accID = bombAuthVO.getAccID();
			String userID = bombAuthVO.getUserID();
			String token = bombAuthVO.getLoginToken();
			String transferId = bombAuthVO.getTransferId();
			Integer roomNo = bombAuthVO.getRoomNo();
			double betAmount = (double) bombAuthVO.getAmount();

			String bombs = bombAuthVO.getBombs();
			String play = bombAuthVO.getPlay();
			String endDate = bombAuthVO.getEndDate();

			log.info("#bomb::credit::" + "bombgame bet accID : " + accID);
			log.info("#bomb::credit::" + "bombgame bet userID : " + userID);
			log.info("#bomb::credit::" + "bombgame bet token : " + token);
			log.info("#bomb::credit::" + "bombgame bet roomNo : " + roomNo);
			log.info("#bomb::credit::" + "bombgame bet transferId : " + transferId);
			log.info("#bomb::credit::" + "bombgame bet betAmount : " + betAmount);

			log.info("#bomb::credit::" + "bombgame bet bombs : " + bombs);
			log.info("#bomb::credit::" + "bombgame bet play : " + play);

			// 밸런스 가져오기

			HashMap sParam = new HashMap();
			sParam.put("siteIdx", Integer.parseInt(accID.substring(0, 3), 16));
			sParam.put("memberId", accID.substring(3, accID.length()));
			String memberId = accID.substring(3, accID.length());

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

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

			JSONObject resData2 = callBackService.getBalance(siteApiInfo, parammember);
			if(resData2 == null) {
				log.info("#bomb::credit::" + "balance callback error");
				bombReponseVo.setCode(-1);
				return bombReponseVo;
			}

			if (resData2.getInt("result_code") == 0) {

				if ("Y".equals(siteApiInfo.getOrDefault("bombDecYn", "").toString())) {
					bombReponseVo.setBalance("" + (resData2.getDouble("balance") * 0.01));
				} else {
					bombReponseVo.setBalance("" + resData2.getDouble("balance"));
				}

			} else {
				bombReponseVo.fail();
			}

			if (betAmount < 0) {

				bombReponseVo.setCode(-99);

			} else {
				if (member.getBombAccId().equals(token)) {
					double curCashAmount = resData2.getDouble("balance");

					if (betAmount >= 0) {

						// betAmount 만큼 cashAmt 차감
						// memberService.updateMineMemCashAmt(bombAuthVO);

						HashMap tranParam = new HashMap();
						tranParam.put("tranId", siteId + "C" + bombAuthVO.getTransferId());
						tranParam.put("refId", siteId + bombAuthVO.getTransferId());
						tranParam.put("siteIdx", siteApiInfo.get("siteIdx"));

						tranParam.put("siteId", siteId);

						tranParam.put("memberIdx", siteApiInfo.get("memberIdx"));
						tranParam.put("memberId", memberId);
						tranParam.put("vendorCetegory", "MINIGAME");
						tranParam.put("vendorIdx", 5);
						tranParam.put("vendorCode", "tpabomb");
						tranParam.put("vendorTranKey", bombAuthVO.getTransferId());
						tranParam.put("gameType", "");
						tranParam.put("gameId", "");
						tranParam.put("gameIdx", ""+roomNo);
						tranParam.put("tranType", "credit");
						tranParam.put("depositAmt", 0);
						tranParam.put("creditAmt", betAmount);
						tranParam.put("isCancel", "N");
						tranParam.put("isTie", "N");
						tranParam.put("apiStatus", 0);

						tranParam.put("completed", true);

						// 게임별로 상세내역 넣어주기 있을 경우에만
						JSONObject detail = new JSONObject();

						detail.put("roomNo ", roomNo);
						detail.put("play", play);
						detail.put("bombs", bombs);
						tranParam.put("detail", detail.toString());

						try {
							CommonParam commonParam = new CommonParam();
							commonParam.setSiteIdx(Integer.parseInt(siteApiInfo.get("siteIdx").toString()));
							PlayParam param = new PlayParam();
							param.setVendorKey("M01");
							commonParam.setPlayParam(param);
							HashMap venderInfo = siteService.getVenderApiInfo(commonParam);
							tranParam.put("vendorApiId", venderInfo.get("vendorApiId").toString());
						} catch (Exception e) {
							log.info("#bomb::credit::" + "VI ERR:" + e.toString());
						}
						siteService.commonBetinsert(tranParam);
						JSONObject debit = new JSONObject();

						debit.put("betId", siteId + bombAuthVO.getTransferId());
						debit.put("tranId", siteId + "C" + bombAuthVO.getTransferId());
						debit.put("userId", memberId);
						debit.put("vendorIdx", 5);
						debit.put("vendorKey", "M01");
						debit.put("vendor", "tpabomb");
						debit.put("gameIdx", 1);
						debit.put("gameKey", roomNo);
						debit.put("gameId", "");
						debit.put("gameType", "");
						debit.put("tranType", "credit");
						debit.put("debit", 0);

						if ("Y".equals(siteApiInfo.getOrDefault("bombDecYn", "").toString())) {
							Double betAmountD = betAmount * 100;
							debit.put("credit", betAmountD.longValue());
						} else {

							debit.put("credit", betAmount);
						}
						SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
						long nDate = System.currentTimeMillis();
						String betDateTimeStr = sdf.format(nDate);
						debit.put("requestAt", betDateTimeStr);
						debit.put("isCancel", 0);
						debit.put("isBonus", 0);
						debit.put("detail", detail);



						JSONObject resData = callBackService.changeBalance("#bomb::", siteApiInfo, debit);
						log.info("#bomb::credit::" + "result_Dcode: {}", resData.getInt("result_code"));

						if (resData.getLong("result_code") == 0) {

							bombReponseVo.setCode(0);

							if ("Y".equals(siteApiInfo.getOrDefault("bombDecYn", "").toString())) {
								bombReponseVo.setBalance("" + (resData.getDouble("balance") * 0.01));
							} else {
								bombReponseVo.setBalance("" + resData.getDouble("balance"));
							}
							
							tranParam.put("balance", bombReponseVo.getBalance());
							int res = siteService.updateCbApi(tranParam);
							log.info("#bomb::debit::" + "result_Dcode: {}2");

						} else if (resData.getLong("result_code") == 80) {
							bombReponseVo.setCode(-1);

						} else if (resData.getLong("result_code") == 98) {
							log.info("#bomb::credit::" + "result_Dcode 98: {}1");
							bombReponseVo.setCode(-1);
						} else {
							bombReponseVo.setCode(-1);
						}

					} else {
						bombReponseVo.setCode(-1);
						obj.put("code", -1);
						log.info("#bomb::credit::" + "bombgame info curr cash : " + curCashAmount + ", reqest : "
								+ betAmount);
					}

				} else {
					bombReponseVo.setCode(-99);
					log.info("#bomb::credit::" + "bombgame info token : " + member.getBombAccId() + ", reqest : "
							+ token);
				}
			}

		} catch (Exception e) {
			bombReponseVo.setCode(-1);
			log.info("#bomb::credit::" + e);
		}

		return bombReponseVo;
	}

}
