package com.bb.admin.controller;

import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.reactive.function.client.WebClientRequestException;
import org.springframework.web.reactive.function.client.WebClientResponseException;

import com.bb.exception.ApiException;
import com.bb.model.ApiResponse;
import com.bb.model.BetParam;
import com.bb.model.NexusApiInfo;
import com.bb.model.PageFormVO;
import com.bb.model.Site;
import com.bb.model.SiteSearch;
import com.bb.model.TplusApiInfo;
import com.bb.service.SiteService;
import com.bb.service.StatService;
import com.bb.util.PagingUtil;
import com.bb.util.StringUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;

@Slf4j
@Controller
@RequestMapping(value = "/guest")
public class GuestController {

	@Autowired
	StatService statService;

	@Autowired
	SiteService siteService;
	
	@GetMapping("/guestLogin")
    public String guestLogin(HttpServletRequest request, ModelMap model) throws Exception {
    	
    	return "admin/guestLogin";        
    }
	
	@GetMapping("/simpleReport")
	//@Secured("ROLE_GUEST")
	public String simpleReport(HttpServletRequest request, ModelMap model, @ModelAttribute("searchVO") SiteSearch search)
			throws Exception {
		final String LOG_PREFIX = "#-SUPER::simpleReport::::";
		
		if(search.getSearchSiteId() != null && !"".equals(search.getSearchSiteId())) {
			Site targetSite = siteService.getSiteSimpleDetail(search);
			if(targetSite != null) {
				search.setSearchSiteIdx(targetSite.getSiteIdx());
			} else {
				search.setSearchSiteIdx(0);
			}
		} else {
			search.setSearchSiteIdx(0);
		}
		
		String toDay = new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis()));
		String startDay = "";
    	String endDay = "";
		if(search.getStartDate() == null || "".equals(search.getStartDate())) {
			startDay = toDay;
			search.setStartDate(startDay);
		} else {
			startDay = search.getStartDate().substring(0, 10);
		}
		
		if(search.getEndDate() == null || "".equals(search.getEndDate())) {
			endDay = toDay;
			search.setEndDate(endDay);
		} else {
			endDay = search.getEndDate().substring(0, 10);
		}
		
		log.info(LOG_PREFIX+ "startDay::"+startDay);
    	log.info(LOG_PREFIX+ "endDay::"+endDay);
    	log.info(LOG_PREFIX+ "toDay::"+toDay);
    	search.setSiteDispYn("N");
		if(startDay.equals(toDay) || endDay.equals(toDay)) {
			search.setSiteDispYn("Y");
		}
		
		ObjectMapper objectMapper = new ObjectMapper();
		String reqJsonStr = objectMapper.writeValueAsString(search);
		JSONObject reqObj = new JSONObject(reqJsonStr);
		log.info(LOG_PREFIX+ "Request {}", reqObj);
		
		PageFormVO pageVo= new PageFormVO();
		int totalCount = statService.getAgentReportCnt(search);
		if (totalCount != 0) {
			PageFormVO commonForm = new PageFormVO();
			commonForm.setFunction_name("goPage");
			commonForm.setPage(search.getPage());
			commonForm.setCount_per_page(20);
			commonForm.setCount_per_list(30);
			commonForm.setTatal_list_count(totalCount);
			pageVo = PagingUtil.setPageUtil(commonForm);
			search.setLimit(pageVo.getLimit());
			search.setOffset(pageVo.getOffset());
			search.setTatal_list_count(totalCount);
			
			model.put("pageInfo", pageVo.getPagination());
		}
		log.info(LOG_PREFIX+ "search.getStartDate {}", search.getStartDate());
		log.info(LOG_PREFIX+ "search.getEndDate {}", search.getEndDate());
		log.info(LOG_PREFIX+ "search.getSearchSiteIdx {}", search.getSearchSiteIdx());
		log.info(LOG_PREFIX+ "search.getPage {}", search.getPage());
		log.info(LOG_PREFIX+ "search.getLimit {}", search.getLimit());
		log.info(LOG_PREFIX+ "search.getOffset {}", search.getOffset());
		
		List<HashMap> siteList = statService.getAgentReportList(search);
		model.put("siteList", siteList);
		HashMap siteTotal = statService.getAgentReportTotal(search);
		model.put("siteTotal", siteTotal);

		return "admin/simpleReport";
	}
	
	/*
	@ResponseBody
	@GetMapping(value="/betDetail")
	public ApiResponse betDetail(HttpServletRequest request, @RequestParam("betId") String betId) throws Exception {
		ApiResponse apiResponse = new ApiResponse();
		final String LOG_PREFIX = "#-CMN::BET-DETAIL::"+betId+":::";
		JSONObject saveObj = null;
		JSONArray saveObjs = null;
		boolean isSaveEvoDetail = false;

		try {
			// apiKey 체크
			Site site = siteService.getSiteInfo(request);
			if(site ==null) {
				throw new ApiException("1000", "accessDinied");
			}

			// 결과보내기
			String dType = "detail_0";

			HashMap betInfo = transService.getBetInfoByBetId(param);
			log.info(LOG_PREFIX+ "betInfo {}", betInfo);

			if(betInfo == null) betInfo = transService.getSiteBetByRefIdFromOld(param);
			log.info(LOG_PREFIX+ "betInfo_OLD {}", betInfo);

			if(betInfo != null) {
				String category = betInfo.get("vendorCetegory").toString();
				log.info(LOG_PREFIX+ "Game category : " + category);

				if("svendor".equals(betInfo.get("vendorCode").toString())
                        || "pink".equals(betInfo.get("vendorCode").toString())) {
					String jsonStr = siteService.getOrgDetailData(param);
					log.info(LOG_PREFIX+ "jsonStr : " + jsonStr);
					if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) {
						dType = "detail_6";
						apiResponse.put("dType", dType);
						HashMap<String, Object> detailMap = new Gson().fromJson(jsonStr, HashMap.class);
						apiResponse.put("detail", detailMap);
					} else {
						isSaveEvoDetail = true;
						JSONObject dataObj = svendorService.getDetail(LOG_PREFIX, betInfo);
						if(dataObj == null) {
							apiResponse.put("detail", "betId is not exist");
						} else {
							if(dataObj.has("gameDetail") && !dataObj.isNull("gameDetail")) {
								String detailType = StringUtils.getType(dataObj.getString("gameDetail"));
								if(detailType.equals("URL")) {
									dType = "detail_2";
									apiResponse.put("dType", dType);
									String detailUrl = dataObj.getString("gameDetail");
									apiResponse.put("detail", detailUrl);
								} else if(detailType.equals("JSON")) {
									dType = "detail_6";
									apiResponse.put("dType", dType);
									JSONObject detailObj = dataObj.getJSONObject("gameDetail");
									saveObj = detailObj;
									HashMap<String, Object> detailMap = new Gson().fromJson(detailObj.toString(), HashMap.class);
									apiResponse.put("detail", detailMap);
								} else {
									apiResponse.put("detail", "betId is not exist");
								}
							} else {
								apiResponse.put("detail", "betId is not exist");
							}
						}
					}

				} else if("nexus".equals(betInfo.get("vendorCode").toString()) || "ace2".equals(betInfo.get("vendorCode").toString())) {
					String jsonStr = siteService.getOrgDetailData(param);
					log.info(LOG_PREFIX+ "jsonStr : " + jsonStr);
					if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) {
						dType = "detail_3";
						apiResponse.put("dType", dType);
						HashMap<String, Object> detailMap = new Gson().fromJson(jsonStr, HashMap.class);
						apiResponse.put("detail", detailMap);
					}
				} else if("prime".equals(betInfo.get("vendorCode").toString())
						|| "dpcore".equals(betInfo.get("vendorCode").toString())) {
					log.info(LOG_PREFIX+ "========== BetDetail::PRIME ==========");
					dType = "detail_9";
					apiResponse.put("dType", dType);

					String jsonStr = siteService.getOrgDetailData(param);
					if(jsonStr != null && !"".equals(jsonStr) && !"{}".equals(jsonStr)) {
						HashMap<String, Object> detailMap = new Gson().fromJson(jsonStr, HashMap.class);
						apiResponse.put("detail", detailMap);
					}
				} else if("onix".equals(betInfo.get("vendorCode").toString())) {
					log.info(LOG_PREFIX+ "========== BetDetail::ONIX ==========");
					dType = "detail_8";
					apiResponse.put("dType", dType);

					String apiBaseUrl = betInfo.get("vendorApiUrl").toString();

					// Step 1: Get round info from /csapi/getBetting
					String bettingUrl = apiBaseUrl + "/csapi/getBetting";
					JSONObject bettingBody = new JSONObject();
					bettingBody.put("userid", betInfo.get("memberId").toString());
					bettingBody.put("sdate", "2000-01-01 00:00:00.000");
					bettingBody.put("edate", "2099-12-31 23:59:59.999");
					bettingBody.put("pagesize", "1");
					bettingBody.put("gameid", "0");
					bettingBody.put("tranid", param.getBetId());

					HttpHeaders headers = new HttpHeaders();
					headers.setContentType(MediaType.APPLICATION_JSON);
					headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));

					log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Url: " + bettingUrl);
					log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Body: " + bettingBody.toString());

					try {
						ResponseEntity<String> bettingRes = webClient.post()
								.uri(bettingUrl)
								.headers(h -> h.addAll(headers))
								.bodyValue(bettingBody.toString())
								.retrieve()
								.toEntity(String.class)
								.block();
						if(bettingRes != null && bettingRes.getBody() != null) {
							JSONObject bettingObj = new JSONObject(bettingRes.getBody());
							log.info(LOG_PREFIX+ "ONIX::Step1 getBetting Response: " + bettingObj.toString());

							int bettingResult = bettingObj.getInt("result");
							if(bettingResult == 1 && bettingObj.has("data")) {
								JSONArray dataArray = bettingObj.getJSONArray("data");
								if(dataArray.length() > 0) {
									JSONObject betData = dataArray.getJSONObject(0);
									String round = betData.has("round") ? betData.getString("round") : "";
									String realround = betData.has("realround") ? betData.getString("realround") : "";
									String game = betData.has("game") ? betData.getString("game") : "";

									log.info(LOG_PREFIX+ "ONIX::Betting Info - round: " + round + ", realround: " + realround + ", game: " + game);

									// Step 2: Get detail link from /api/apigamedetail.aspx
									if(!round.isEmpty() && !realround.isEmpty()) {
										String gtype = game.toLowerCase().contains("slot") || game.toLowerCase().contains("prg") ? "sxprg" : "apievo";
										String detailUrl = apiBaseUrl + "/api/apigamedetail.aspx?gtype=" + gtype;

										if(gtype.equals("apievo")) {
											detailUrl += "&round=" + round + "&realround=" + realround;
										} else {
											detailUrl += "&roundid=" + realround;
										}

										log.info(LOG_PREFIX+ "ONIX::Step2 Detail Url: " + detailUrl);

										try {
											ResponseEntity<String> detailRes = webClient.get()
													.uri(detailUrl)
													.retrieve()
													.toEntity(String.class)
													.block();

											if(detailRes != null && detailRes.getBody() != null) {
												JSONObject detailObj = new JSONObject(detailRes.getBody());
												log.info(LOG_PREFIX+ "ONIX::Step2 Detail Response: " + detailObj.toString());

												if(detailObj.getInt("result") == 1 && detailObj.has("link")) {
													isSaveEvoDetail = true;
													JSONObject saveData = new JSONObject();
													saveData.put("link", detailObj.getString("link"));
													saveData.put("betInfo", betData);
													saveObj = saveData;

													HashMap<String, Object> detailMap = new HashMap<>();
													detailMap.put("link", detailObj.getString("link"));
													detailMap.put("betInfo", new Gson().fromJson(betData.toString(), HashMap.class));
													apiResponse.put("detail", detailMap);
													log.info(LOG_PREFIX+ "ONIX::Detail loaded successfully");
												} else {
													apiResponse.put("detail", "betId is not exist");
													String msg = detailObj.has("msg") ? detailObj.getString("msg") : "Unknown error";
													log.error(LOG_PREFIX+ "ONIX::Detail Error: " + msg);
												}
											} else {
												apiResponse.put("detail", "betId is not exist");
											}
										} catch(Exception detailEx) {
											log.error(LOG_PREFIX+ "ONIX::Detail Exception: " + detailEx.getMessage());
											apiResponse.put("detail", "betId is not exist");
										}
									} else {
										// No round info, use betting data only
										isSaveEvoDetail = true;
										saveObj = betData;
										HashMap<String, Object> detailMap = new Gson().fromJson(betData.toString(), HashMap.class);
										apiResponse.put("detail", detailMap);
										log.info(LOG_PREFIX+ "ONIX::Betting data loaded (no round info)");
									}
								} else {
									apiResponse.put("detail", "betId is not exist");
								}
							} else {
								apiResponse.put("detail", "betId is not exist");
								String errorMsg = bettingObj.has("msg") ? bettingObj.getString("msg") : "Unknown error";
								log.error(LOG_PREFIX+ "ONIX::Betting Error: " + errorMsg);
							}
						} else {
							apiResponse.put("detail", "betId is not exist");
							log.error(LOG_PREFIX+ "ONIX::Betting Response is null");
						}
					} catch(WebClientResponseException e) {
						log.error(LOG_PREFIX+ "ONIX::Betting HttpClientErrorException : " + e.getMessage());
						log.error(LOG_PREFIX+ "ONIX::Betting status code : " + e.getStatusCode().value());
						log.error(LOG_PREFIX+ "ONIX::Betting response body : " + e.getResponseBodyAsString());
						JSONObject errorJson = new JSONObject(e.getResponseBodyAsString());
						String errorMsg = errorJson.has("msg") ? errorJson.getString("msg") : "Betting API error";
						log.error(LOG_PREFIX+ "ONIX::Betting error : " + errorMsg);
						throw new ApiException("P209", errorMsg);
					} catch (WebClientRequestException rae) {
						if(rae.getCause() instanceof io.netty.channel.ConnectTimeoutException) {
							log.error(LOG_PREFIX+ "ONIX::Betting ConnectTimeoutException::" + rae.getMessage());
						}
						if(rae.getCause() instanceof io.netty.handler.timeout.ReadTimeoutException) {
							log.error(LOG_PREFIX+ "ONIX::Betting ReadTimeoutException::" + rae.getMessage());
						}
						if(rae.getCause() instanceof InterruptedException) {
							log.error(LOG_PREFIX+ "ONIX::Betting InterruptedException::" + rae.getMessage());
						}
						throw new ApiException("P210", rae.getMessage());
					} catch(Exception e) {
						log.error(LOG_PREFIX+ "ONIX::Betting Exception : " + e.getMessage());
						throw new ApiException("P211", e.getMessage());
					}
				} else if("bet_radar".equals(betInfo.get("vendorCode").toString())) {
					log.info(LOG_PREFIX+ "========== BetDetail::BET_RADAR ==========");
					// bet_radar_log 테이블에서 조회
					String radarLogJson = siteService.getMergedBetRadarLog(param.getBetId());
					if(radarLogJson != null && !radarLogJson.isEmpty()) {
						log.info(LOG_PREFIX+ "bet_radar_log found, returning merged json");
						dType = "detail_radar";
						apiResponse.put("dType", dType);
						HashMap<String, Object> detailMap = new Gson().fromJson(radarLogJson, HashMap.class);
						apiResponse.put("detail", detailMap);
						apiResponse.success();
						return apiResponse;
					}
				} else {
					apiResponse.put("dType", dType);
					apiResponse.put("detail", "betId is not exist");
				}
			} else {
				apiResponse.put("dType", dType);
				apiResponse.put("detail", "betId is not exist");
			}

			apiResponse.success();
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "[Exception]::"+e.toString());
			e.printStackTrace();
			apiResponse.fail();
		}

		return apiResponse;
	}
	*/
}
