package com.bb.api;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;

import org.codehaus.jettison.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.bb.jwt.JwtManager;
import com.bb.model.ApiResponse;
import com.bb.model.CashParam;
import com.bb.model.Credit;
import com.bb.model.Member;
import com.bb.model.PageFormVO;
import com.bb.model.Site;
import com.bb.model.UserSearch;
import com.bb.service.CreditService;
import com.bb.service.SiteService;
import com.bb.service.StatService;
import com.bb.util.IPKit;
import com.bb.util.PagingUtil;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
@RequiredArgsConstructor
@RequestMapping(value = "/api/v1/user")
public class ApiUserController {

	@Autowired
	SiteService siteService;

	@Autowired
	StatService statService;

	@Autowired
	CreditService creditService;

	@Autowired
	private final JwtManager jwtManager;


	@ResponseBody
	@PostMapping("/list")
    public ApiResponse userList(@RequestHeader String token, HttpServletRequest request, @Valid @RequestBody UserSearch search) throws Exception {
		ApiResponse apiResponse = new ApiResponse();

		try {
			Site site = siteService.getSiteInfoAPI(request);
			if(site == null) {
				apiResponse.setResultCode("9999");
				apiResponse.setResultMessage("Authorization apiKey check");
				return apiResponse;
			}

			if( !( site.getSiteIp()==null || "".equals(site.getSiteIp())
					|| "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) {
				log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request));
				apiResponse.setResultCode("10001");
				return apiResponse;
			}

			// TO DO 토큰체크
			Map responseData = new HashMap();

			try {
				JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token);
				final String LOG_PREFIX = "#-API::USER::userList::"+tokenInfo.getSid()+"::::";

				// 여기서 부터 로직

		    	PageFormVO pageVo= new PageFormVO();
		    	search.setSiteId(site.getSiteId());
		    	search.setSiteIdx((long) site.getSiteIdx());
		    	search.setTopId(tokenInfo.getSid());

		    	log.info(LOG_PREFIX+ "UserSearch::"+search.toString());

		    	int totalCount = siteService.getUserListCnt(search);
				if (totalCount != 0) {
					PageFormVO commonForm = new PageFormVO();
					commonForm.setFunction_name("goPage");
					commonForm.setPage(search.getPage());
					commonForm.setCount_per_page(20);
					if(search.getCount_per_list()==0) {
						commonForm.setCount_per_list(30);
					} else {
						commonForm.setCount_per_list(search.getCount_per_list());
					}
					commonForm.setTatal_list_count(totalCount);
					pageVo = PagingUtil.setPageUtil(commonForm);
					search.setLimit(pageVo.getLimit());
					search.setOffset(pageVo.getOffset());
					search.setTatal_list_count(totalCount);

					responseData.put("pageInfo", pageVo);
				}

				List<HashMap<String, Object>> list = siteService.getUserList(search);
				responseData.put("list", list);


			} catch(Exception e) {
				log.info(e.toString());
				apiResponse.setResultCode("99995");
				apiResponse.setResultMessage("token is no valid");
				return apiResponse;
			}

			apiResponse.setData(responseData);
			apiResponse.success();

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

		return apiResponse;
	}



	@ResponseBody
	@GetMapping("/detail/{siteIdx}/{memberIdx}")
	public ApiResponse userDetail( @RequestHeader String token, HttpServletRequest request, @PathVariable long siteIdx, @PathVariable long memberIdx) throws Exception {

		ApiResponse apiResponse = new ApiResponse();
		try {
			log.info(token.toString());
			Site site = siteService.getSiteInfoAPI(request);

			if(site == null) {
				apiResponse.setResultCode("9999");
				apiResponse.setResultMessage("Authorization apiKey check");
				return apiResponse;
			}


			if( !( site.getSiteIp() == null  ||  "".equals(site.getSiteIp())  ||  "3.3.3.3".equals(site.getSiteIp())  ||  site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0 ) ) {
				log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request));
				apiResponse.setResultCode("10001");
				apiResponse.setResultMessage("access denied IP");
				return apiResponse;
			}
			// TO DO 토큰체크
			Map responseData = new HashMap();

			try {
				JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token);
				final String LOG_PREFIX = "#-API::USER::userDetail::"+tokenInfo.getSid()+"::::";

			    // 여기서 부터 로직
				UserSearch search = new UserSearch();
		    	search.setSiteIdx(siteIdx);
		    	search.setMemberIdx(memberIdx);
		    	search.setTopId(tokenInfo.getSid());

		    	log.info(LOG_PREFIX+ "UserSearch::"+search.toString());

		    	HashMap<String, Object> targetUser = siteService.getUserDetail(search);
		    	responseData.put("targetUser", targetUser);		// 유저 상세정보

		    	boolean isMyAgent = false;
		    	List<HashMap> treeInfo = (List<HashMap>) targetUser.get("treeInfo");
		    	for(HashMap item : treeInfo) {
		    		if(tokenInfo.getSid().equals(item.get("upperSiteId").toString())) {
		    			isMyAgent = true;
		    		}
		    	}
		    	if(!isMyAgent) {
		    		apiResponse.setResultCode("99995");
					apiResponse.setResultMessage("token is no valid");
					return apiResponse;
		    	}

		    	// TODO : 에이전트 상세 베팅통계 데이터
		    	// TODO : 에이전트 상세 베팅통계 데이터
		    	HashMap ydayBetInfo = statService.getYdayBetInfoByUser(targetUser);
		    	log.info(LOG_PREFIX+ "ydayBetInfo {}", ydayBetInfo);
		    	HashMap monthBetInfo = statService.getMonthBetInfoByUser(targetUser);
		    	log.info(LOG_PREFIX+ "monthBetInfo {}", monthBetInfo);
		    	responseData.put("ydayBetInfo", ydayBetInfo);			// 어제 배팅통계
		    	responseData.put("monthBetInfo", monthBetInfo);			// 이번달 배팅통계


			} catch(Exception e) {
				log.info(e.toString());
				apiResponse.setResultCode("99995");
				apiResponse.setResultMessage("token is no valid");
				return apiResponse;
			}

			apiResponse.setData(responseData);
			apiResponse.success();

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

		return apiResponse;
    }


	@ResponseBody
	@PostMapping("/cashInOut")
    public ApiResponse cashInOut(@RequestHeader String token, HttpServletRequest request, @RequestBody CashParam param) throws Exception {
		ApiResponse apiResponse = new ApiResponse();

		try {
			Site site = siteService.getSiteInfoAPI(request);
			if(site == null) {
				apiResponse.setResultCode("9999");
				apiResponse.setResultMessage("Authorization apiKey check");
				return apiResponse;
			}

			if( !( site.getSiteIp()==null || "".equals(site.getSiteIp())
					|| "3.3.3.3".equals(site.getSiteIp()) || site.getSiteIp().indexOf(IPKit.getIpAddressByRequest(request)) >= 0) ) {
				log.error("site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request));
				apiResponse.setResultCode("10001");
				return apiResponse;
			}

			// TO DO 토큰체크
			Map data = new HashMap();

			try {
				JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token);
				final String LOG_PREFIX = "#-API::CASH::cashInOut::"+tokenInfo.getSid()+"::::";

				// 여기서 부터 로직
				ObjectMapper objectMapper = new ObjectMapper();
				String reqJsonStr = objectMapper.writeValueAsString(param);
				JSONObject reqObj = new JSONObject(reqJsonStr);
				log.info(LOG_PREFIX+ "Request {}", reqObj);

				if("tripleSuper".equals(site.getSiteId())){
					apiResponse.setResultCode("9991");
					apiResponse.setResultMessage("Super admin is not allow");
					return apiResponse;
				}

				if("N".equals(site.getIsTransfer())) {
					apiResponse.setResultCode("9992");
					apiResponse.setResultMessage("NOT_TRANSFER_SITE");
					return apiResponse;
				}

				//회원정보
				param.setSiteIdx(site.getSiteIdx());
				Member member = siteService.getMember2(param);
				if(member == null) {
					// Fail
					log.error(LOG_PREFIX+ "9993:NOT_FOUND_USER");
					apiResponse.setResultCode("9993");
					apiResponse.setResultMessage("NOT_FOUND_USER");
					return apiResponse;
				}
				log.info(LOG_PREFIX+ "Member::"+member.toString());

				long amount = Long.parseLong(param.getAmount());

				// Insert credit_info : MAI, IN / MAO, OUT
				Credit credit = new Credit();
				credit.setSiteIdx(site.getSiteIdx());
				credit.setSiteId(site.getSiteId());
				credit.setTargetSiteIdx(member.getMemberIdx());
				credit.setTargetSiteId(member.getMemberId());
				credit.setCreditType(param.getCreditType());
				if("MAI".equals(credit.getCreditType())) {
					// 관리자 > 회원 보유금 지급
					long siteCredit = site.getCredit();
					if(siteCredit < amount) {
						log.error(LOG_PREFIX+ "9994:사이트 크레딧 부족");
						apiResponse.setResultCode("9994");
						apiResponse.setResultMessage("사이트 크레딧 부족");
						return apiResponse;
					}
					credit.setCreditRate(null);
					credit.setInOut("IN");
					credit.setTranId("회원 보유금 지급");
					credit.setCreditAmt(Long.parseLong(param.getAmount()));
					credit.setUserAmt(Long.parseLong(param.getAmount()));
			    	credit.setCreditStatus(1);
					credit.setWaitTime(-5);	// 재요청 대기시간 5초
					credit.setPreBalance(member.getUserBalance());
					int cnt = creditService.checkRequestTime(credit);
					if(cnt > 0) {
						// Fail
						log.error(LOG_PREFIX+ "T1005:재요청 대기시간 5초");
						apiResponse.setResultCode("T1005");
						apiResponse.setResultMessage("재요청 대기시간 5초");
						return apiResponse;
					}

					log.info(LOG_PREFIX+ "Credit::"+credit.toString());
					int result = creditService.insertCreditByCash(credit);
					log.info(LOG_PREFIX+ "insertCredit result::"+result);
					if(result < 0) {
						// Fail
						log.error(LOG_PREFIX+ "T1009:DEPOSIT_FAIL");
						apiResponse.setResultCode("T1009");
						apiResponse.setResultMessage("DEPOSIT_FAIL");
						return apiResponse;
					}

				} else if("MAO".equals(credit.getCreditType())) {
					// 관리자 < 회원 보유금 회수
					long userBalance = member.getUserBalance();
					if(param.getWithAll() != null && param.getWithAll().equals("Y")) {
						amount = userBalance;
						param.setAmount(Long.toString(amount));
					}

					if(userBalance < amount) {
						log.error(LOG_PREFIX+ "9995:유저 잔액 부족");
						apiResponse.setResultCode("9995");
						apiResponse.setResultMessage("유저 잔액 부족");
						return apiResponse;
					}
					credit.setCreditRate(null);
					credit.setInOut("OUT");
					credit.setTranId("회원 보유금 회수");
					credit.setCreditAmt(Long.parseLong(param.getAmount()));
					credit.setUserAmt(Long.parseLong(param.getAmount()));
			    	credit.setCreditStatus(1);
			    	credit.setWaitTime(-5);	// 재요청 대기시간 5초
			    	credit.setPreBalance(member.getUserBalance());
					int cnt = creditService.checkRequestTime(credit);
					if(cnt > 0) {
						// Fail
						log.error(LOG_PREFIX+ "T1005:재요청 대기시간 5초");
						apiResponse.setResultCode("T1005");
						apiResponse.setResultMessage("재요청 대기시간 5초");
						return apiResponse;
					}

					log.info(LOG_PREFIX+ "Credit::"+credit.toString());
					int result = creditService.insertCreditByCash(credit);
					log.info(LOG_PREFIX+ "insertCredit result::"+result);
					if(result < 0) {
						// Fail
						log.error(LOG_PREFIX+ "T1009:WITHDRAW_FAIL");
						apiResponse.setResultCode("T1009");
						apiResponse.setResultMessage("WITHDRAW_FAIL");
						return apiResponse;
					}

				} else {
					apiResponse.setResultCode("9999");
					apiResponse.setResultMessage("알 수 없는 요청");
					return apiResponse;
				}

			} catch(Exception e) {
				log.error(e.toString());
				e.printStackTrace();
				apiResponse.setResultCode("99995");
				apiResponse.setResultMessage("token is no valid");
				return apiResponse;
			}

			apiResponse.success();

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

		return apiResponse;
	}

}
