package com.bb.admin.controller;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.reactive.function.client.WebClient;

import com.bb.model.ApiTestVO;
import com.bb.model.Site;
import com.bb.service.SiteService;

import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;

@Slf4j
@Controller
@RequestMapping(value = "")
public class MainController {

	@Autowired
	SiteService siteService;

	@Autowired
	private WebClient webClient; // 싱글톤 WebClient 주입

	@GetMapping("/")
	@PreAuthorize("permitAll()")
	public String first(HttpServletRequest request, ModelMap model) throws Exception {
		System.out.println("error/404");

		String code = request.getParameter("code");
		model.put("code", code);

		return "error/404";
	}

	@GetMapping("/lg")
	public String loginsForm(HttpServletRequest request, ModelMap model) throws Exception {
		System.out.println("login");

		return "admin/lg";
	}

	@GetMapping("/index")
	@PreAuthorize("hasRole('ADMIN')")
	public String index(HttpServletRequest request, ModelMap model) throws Exception {

		System.out.println("index");

		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		Site loginSite = (Site) authentication.getDetails();
		model.put("loginSite", loginSite);
		long siteCredit = siteService.getSiteCredit(loginSite.getSiteId());
		long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId());
		model.put("underSiteCredit", underSiteCredit);
		model.put("siteCredit", siteCredit);
		// long sitePoint = siteService.getSitePoint(loginSite.getSiteId());
		model.put("sitePoint", 0);
		// HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx());
		model.put("creditWait", 0);
		// pot 정보 가져오기

		// long insureAmt = siteService.getInsureAmt(loginSite.getSiteId());
		// long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId());
		model.put("insureAmt", 0);
		model.put("insurePointAmt", 0);

		Map dashInfo = siteService.getDashInfo(loginSite); // 베팅정보
		Map dashInfo2 = siteService.getDashInfo2(loginSite); // 하부에이전수 수.

		model.put("dashInfo", dashInfo);
		model.put("dashInfo2", dashInfo2);

		return "admin/index";
	}

	@GetMapping("/mypage")
	@PreAuthorize("hasRole('ADMIN')")
	public String mypage(HttpServletRequest request, ModelMap model) throws Exception {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		Site loginSite = (Site) authentication.getDetails();
		model.put("loginSite", loginSite);
		long siteCredit = siteService.getSiteCredit(loginSite.getSiteId());
		long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId());
		log.info("underSiteCredit" + underSiteCredit);
		model.put("siteCredit", siteCredit);
		model.put("underSiteCredit", underSiteCredit);
		Site mypageInfo = siteService.getSiteInfoMypage(loginSite);
		model.put("mypageInfo", mypageInfo);
		long sitePoint = siteService.getSitePoint(loginSite.getSiteId());
		model.put("sitePoint", sitePoint);
		HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx());
		model.put("creditWait", creditWait);
		long insureAmt = siteService.getInsureAmt(loginSite.getSiteId());
		long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId());
		model.put("insureAmt", insureAmt);
		model.put("insurePointAmt", insurePointAmt);

		return "admin/mypage";
	}

	@RequestMapping("/mypage/pwdUpdate")
	@PreAuthorize("hasRole('ADMIN')")
	public @ResponseBody JSONObject pwdUpdate(HttpServletRequest request, ModelMap model, Site site) throws Exception {
		JSONObject obj = new JSONObject();
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		Site loginSite = (Site) authentication.getDetails();
		site.setUpperSiteId(loginSite.getSiteId());
		site.setUpperSiteIdx(loginSite.getSiteIdx());

		Map siteParam = new HashMap();
		siteParam.put("siteId", loginSite.getSiteId());
		siteParam.put("sitePass", site.getNowPass());

		Site checkSite = siteService.getSiteBypassword(siteParam);

		if (checkSite == null) {

			obj.put("RES", "FAIL");
			obj.put("MSG", "현재 비밀번호를 확인해주세요.");
			return obj;
		} else {
			siteParam.put("newPass", site.getNewPass());
			siteService.updatePass(siteParam);
		}

		obj.put("RES", "SUCCESS");

		return obj;
	}

	@RequestMapping("/mypage/siteUpdate")
	@PreAuthorize("hasRole('ADMIN')")
	public @ResponseBody JSONObject siteUpdate(HttpServletRequest request, ModelMap model, Site site) throws Exception {
		JSONObject obj = new JSONObject();
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		Site loginSite = (Site) authentication.getDetails();
		site.setSiteId(loginSite.getSiteId());
		final String LOG_PREFIX = "#-super::mySiteUpdate:::";

		String siteKey = loginSite.getSiteKey();
		if ("new".equals(site.getSiteKey())) {
			siteKey = makeApiKey(loginSite.getSiteId());
			site.setSiteKey(siteKey);
		}

		log.info(LOG_PREFIX + "Site Info: " + site.toString());
		log.info(LOG_PREFIX + "Site IP: " + site.getSiteIp());
		siteService.siteUpdate(LOG_PREFIX, site);

		obj.put("RES", "SUCCESS");
		obj.put("DATA", siteKey);

		return obj;
	}

	@RequestMapping(value = "/manual/apiTest")
	@PreAuthorize("hasRole('ADMIN')")
	public @ResponseBody JSONObject apiTest(HttpServletRequest request, ModelMap model, ApiTestVO param)
			throws Exception {

		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		Site loginSite = (Site) authentication.getDetails();
		JSONObject obj = new JSONObject();

		try {
			log.info("##### API Test 시작: {}", param.toString());

			String apiUrl = param.getApiUrl();

			// 1. 전송할 바디 데이터 구성
			JSONObject paraJson = new JSONObject();
			paraJson.put("userId", param.getUserId());
			paraJson.put("nickName", param.getNickName());
			paraJson.put("userIp", param.getUserIp());
			paraJson.put("balance", param.getBalance());

			// 빈 값이 아닐 때만 파라미터 추가
			if (param.getVendorKey() != null && !"".equals(param.getVendorKey()))
				paraJson.put("vendorKey", param.getVendorKey());
			if (param.getBetId() != null && !"".equals(param.getBetId()))
				paraJson.put("betId", param.getBetId());
			if (param.getStartDate() != null && !"".equals(param.getStartDate()))
				paraJson.put("startDate", param.getStartDate());
			if (param.getEndDate() != null && !"".equals(param.getEndDate()))
				paraJson.put("endDate", param.getEndDate());
			if (param.getGameKey() != null && !"".equals(param.getGameKey()))
				paraJson.put("gameKey", param.getGameKey());
			if (param.getIsMobile() != null && !"".equals(param.getIsMobile()))
				paraJson.put("isMobile", param.getIsMobile());
			if (param.getLanguage() != null && !"".equals(param.getLanguage()))
				paraJson.put("language", param.getLanguage());

			// 2. WebClient를 이용한 호출 (동기 방식 .block())
			String responseBody = webClient.post().uri(apiUrl).contentType(MediaType.APPLICATION_JSON)
					.accept(MediaType.APPLICATION_JSON).header("User-Agent", "PostmanRuntime/7.28.4")
					.header("Authorization", loginSite.getSiteKey())
					// 토큰이 있을 경우에만 헤더 추가
					.headers(headers -> {
						if (param.getToken() != null && !"".equals(param.getToken())) {
							headers.add("token", param.getToken());
						}
					}).bodyValue(paraJson.toString()).retrieve().bodyToMono(String.class).block(); // 응답이 올 때까지 대기

			// 3. 응답 결과 처리
			JSONObject resJson = JSONObject.fromObject(responseBody);

			obj.put("RES", "SUCCESS");
			obj.put("DATA", resJson);

			log.info("##### API Test 응답 완료: {}", resJson.toString());

		} catch (Exception e) {
			log.error("##### API Test 에러 발생: {}", e.toString());
			e.printStackTrace();
			obj.put("RES", "FAIL");
			obj.put("MESSAGE", e.getMessage()); // 에러 메시지도 화면에 전달
		}

		return obj;
	}

	@GetMapping("/limit")
	@PreAuthorize("hasRole('ADMIN')")
	public String limit(HttpServletRequest request, ModelMap model) throws Exception {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		Site loginSite = (Site) authentication.getDetails();
		model.put("loginSite", loginSite);
		long siteCredit = siteService.getSiteCredit(loginSite.getSiteId());
		long underSiteCredit = siteService.getUnderSiteCredit(loginSite.getSiteId());
		model.put("underSiteCredit", underSiteCredit);
		model.put("siteCredit", siteCredit);
		long sitePoint = siteService.getSitePoint(loginSite.getSiteId());
		model.put("sitePoint", sitePoint);
		HashMap creditWait = siteService.getCreditWait(loginSite.getSiteIdx());
		model.put("creditWait", creditWait);
		long insureAmt = siteService.getInsureAmt(loginSite.getSiteId());
		long insurePointAmt = siteService.getInsurePointAmt(loginSite.getSiteId());
		model.put("insureAmt", insureAmt);
		model.put("insurePointAmt", insurePointAmt);

		return "admin/limit";
	}

	private String makeApiKey(String param) {

		int n = 10; // n자리 쿠폰
		char[] chs = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
				'J', 'K', 'L', 'M', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'N', 'O', 'P', 'Q',
				'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
				'z' };

		Random rd = new Random();
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < n; i++) {
			char ch = chs[rd.nextInt(chs.length)];
			sb.append(ch);
		}
		return param + sb.toString();

	}
}
