package com.bb.api;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

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

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.bb.jwt.JwtManager;
import com.bb.model.ApiResponse;
import com.bb.model.CallbackTestResult;
import com.bb.model.Site;
import com.bb.service.CallBackTestService;
import com.bb.service.SiteService;
import com.bb.util.IPKit;

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

@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping(value = "/api/v1/spdtest")
public class ApiCallbackSpeedTestController {

	@Autowired
	SiteService siteService;
	
	@Autowired
	CallBackTestService callBackService;
	
	@Autowired
	private final JwtManager jwtManager;
	
	private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    private static final SecureRandom random = new SecureRandom();

    public static List<String> generateRandomStrings(int stringLength, int count) {
        Set<String> uniqueStrings = new HashSet<>();

        while (uniqueStrings.size() < count) {
            StringBuilder sb = new StringBuilder(stringLength);
            for (int i = 0; i < stringLength; i++) {
                sb.append(CHARACTERS.charAt(random.nextInt(CHARACTERS.length())));
            }

            // 시간 기반으로 중복 확률 줄이기 (나노타임 일부 추가)
            sb.append(Long.toHexString(System.nanoTime()).substring(0, 4));

            uniqueStrings.add(sb.toString());
        }

        return new ArrayList<>(uniqueStrings);
    }
	
	
	@GetMapping("/testBalance")
    public ApiResponse testBalance(HttpServletRequest request, @RequestHeader String token, @Valid @RequestParam String memberId) throws Exception {
		ApiResponse apiResponse = new ApiResponse();
		
		Site site = siteService.getSiteInfoAPI(request);
		if(site == null) {
			log.error("#-API::SPD_TEST::testBalance::Authorization apiKey check");
			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("#-API::SPD_TEST::testBalance::site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request));
			apiResponse.setResultCode("10001");
			return apiResponse;
		}
		
		if(token == null || token.equals("")) {
			log.error("#-API::SPD_TEST::testBalance::Authorization apiKey check");
			apiResponse.setResultCode("9999");
			apiResponse.setResultMessage("Authorization token check");
			return apiResponse;
		}
		
		try {
			// TO DO 토큰체크 
			Map responseData = new HashMap();
			
			try {
				JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token);
				final String LOG_PREFIX = "#-API::SPD_TEST::testBalance::"+tokenInfo.getSid()+"::";
				
				// 여기서 부터 로직
				List<CallbackTestResult> resultList = new ArrayList<>();
				
				log.info(LOG_PREFIX+ "callBackService.getTestBalance() START--");
				JSONObject responseObj = callBackService.getTestBalance(LOG_PREFIX, memberId, token, request.getHeader("Authorization").toString());
				log.info(LOG_PREFIX+ "callBackService.getTestBalance() END--");
				
				JSONObject dataObj = responseObj.getJSONObject("data");
				JSONArray resultArray = dataObj.getJSONArray("resultList");
				for(int i=0; i<resultArray.length(); i++) {
					JSONObject item = resultArray.getJSONObject(i);
					CallbackTestResult result = new CallbackTestResult();
					result.setIndex(item.getInt("index"));
					result.setStatus(item.getString("status"));
					result.setMsg(item.getString("msg"));
					result.setCallbackUrl(item.getString("callbackUrl"));
					result.setRequestBody(item.getString("requestBody"));
					result.setResponseData(item.getString("responseData"));
					result.setTimeMs(item.getLong("timeMs"));
					resultList.add(result);
				}
				
				responseData.put("resultList", resultList);

				apiResponse.setData(responseData);
				apiResponse.success();
				
			} catch(Exception e) {
				log.error("#-API::SPD_TEST::testBalance::"+ e.toString());
				apiResponse.setResultCode("99995");
				apiResponse.setResultMessage("token is no valid");
				return apiResponse;
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			apiResponse.fail();
		}
		
		return apiResponse;
	}
	
	
	@GetMapping("/testCasino")
    public ApiResponse testCasino(HttpServletRequest request, @RequestHeader String token, @Valid @RequestParam String memberId) throws Exception {
		ApiResponse apiResponse = new ApiResponse();
		
		Site site = siteService.getSiteInfoAPI(request);
		if(site == null) {
			log.error("#-API::SPD_TEST::testCasino::Authorization apiKey check");
			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("#-API::SPD_TEST::testCasino::site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request));
			apiResponse.setResultCode("10001");
			return apiResponse;
		}
		
		if(token == null || token.equals("")) {
			log.error("#-API::SPD_TEST::testCasino::Authorization apiKey check");
			apiResponse.setResultCode("9999");
			apiResponse.setResultMessage("Authorization token check");
			return apiResponse;
		}
		
		try {
			// TO DO 토큰체크 
			Map responseData = new HashMap();
			
			try {
				JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token);
				final String LOG_PREFIX = "#-API::SPD_TEST::testCasino::"+tokenInfo.getSid()+"::";
				
				// 여기서 부터 로직
				List<CallbackTestResult> resultList = new ArrayList<>();
				
				log.info(LOG_PREFIX+ "callBackService.getTestChangeBalance() START--");
				JSONObject responseObj = callBackService.getTestChangeBalance(LOG_PREFIX, memberId, token, request.getHeader("Authorization").toString());
				log.info(LOG_PREFIX+ "callBackService.getTestChangeBalance() END--");
				
				JSONObject dataObj = responseObj.getJSONObject("data");
				JSONArray resultArray = dataObj.getJSONArray("resultList");
				for(int i=0; i<resultArray.length(); i++) {
					JSONObject item = resultArray.getJSONObject(i);
					CallbackTestResult result = new CallbackTestResult();
					result.setIndex(item.getInt("index"));
					result.setStatus(item.getString("status"));
					result.setMsg(item.getString("msg"));
					result.setCallbackUrl(item.getString("callbackUrl"));
					result.setRequestBody(item.getString("requestBody"));
					result.setResponseData(item.getString("responseData"));
					result.setTimeMs(item.getLong("timeMs"));
					resultList.add(result);
				}
				
				responseData.put("resultList", resultList);

				apiResponse.setData(responseData);
				apiResponse.success();
				
			} catch(Exception e) {
				log.error("#-API::SPD_TEST::testBalance::"+ e.toString());
				apiResponse.setResultCode("99995");
				apiResponse.setResultMessage("token is no valid");
				return apiResponse;
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			apiResponse.fail();
		}
		
		return apiResponse;
	}
	
	
	@GetMapping("/testSlot")
    public ApiResponse testSlot(HttpServletRequest request, @RequestHeader String token, @Valid @RequestParam String memberId) throws Exception {
		ApiResponse apiResponse = new ApiResponse();
		
		Site site = siteService.getSiteInfoAPI(request);
		if(site == null) {
			log.error("#-API::SPD_TEST::testSlot::Authorization apiKey check");
			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("#-API::SPD_TEST::testSlot::site.getSiteIp("+site.getSiteIp()+"), denied" + IPKit.getIpAddressByRequest(request));
			apiResponse.setResultCode("10001");
			return apiResponse;
		}
		
		if(token == null || token.equals("")) {
			log.error("#-API::SPD_TEST::testSlot::Authorization apiKey check");
			apiResponse.setResultCode("9999");
			apiResponse.setResultMessage("Authorization token check");
			return apiResponse;
		}
		
		try {
			// TO DO 토큰체크 
			Map responseData = new HashMap();
			
			try {
				JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token);
				final String LOG_PREFIX = "#-API::SPD_TEST::testSlot::"+tokenInfo.getSid()+"::";
				
				// 여기서 부터 로직
				List<CallbackTestResult> resultList = new ArrayList<>();
				
				log.info(LOG_PREFIX+ "callBackService.getTestChangeBalanceSlot() START--");
				JSONObject responseObj = callBackService.getTestChangeBalanceSlot(LOG_PREFIX, memberId, token, request.getHeader("Authorization").toString());
				log.info(LOG_PREFIX+ "callBackService.getTestChangeBalanceSlot() END--");
				
				JSONObject dataObj = responseObj.getJSONObject("data");
				JSONArray resultArray = dataObj.getJSONArray("resultList");
				for(int i=0; i<resultArray.length(); i++) {
					JSONObject item = resultArray.getJSONObject(i);
					CallbackTestResult result = new CallbackTestResult();
					result.setIndex(item.getInt("index"));
					result.setStatus(item.getString("status"));
					result.setMsg(item.getString("msg"));
					result.setCallbackUrl(item.getString("callbackUrl"));
					result.setRequestBody(item.getString("requestBody"));
					result.setResponseData(item.getString("responseData"));
					result.setTimeMs(item.getLong("timeMs"));
					resultList.add(result);
				}
				
				responseData.put("resultList", resultList);

				apiResponse.setData(responseData);
				apiResponse.success();
				
			} catch(Exception e) {
				log.error("#-API::SPD_TEST::testBalance::"+ e.toString());
				apiResponse.setResultCode("99995");
				apiResponse.setResultMessage("token is no valid");
				return apiResponse;
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			apiResponse.fail();
		}
		
		return apiResponse;
	}
	
}
