package com.bb.api;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
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.ModelAttribute;
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 org.springframework.web.reactive.function.client.WebClient;

import com.bb.jwt.JwtManager;
import com.bb.model.ApiResponse;
import com.bb.model.CommonParamAdmin;
import com.bb.model.PageFormVO;
import com.bb.model.Site;
import com.bb.model.SitePwdVO;
import com.bb.model.SiteSearch;
import com.bb.model.Vendor;
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.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

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



@Slf4j
@Controller
@RequiredArgsConstructor
@RequestMapping(value = "/api/v1/agent")
public class ApiAgentController {
	
	
	@Autowired
	SiteService siteService;
	
	@Autowired
	StatService statService;
	
	@Autowired
	CreditService creditService;
	
	@Autowired
	private final JwtManager jwtManager;

	@Autowired
    private WebClient webClient; // 싱글톤 WebClient 주입	
	
	@ResponseBody	
	@PostMapping("/list")
	public ApiResponse list( @RequestHeader String token, HttpServletRequest request, @RequestBody SiteSearch 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");
				apiResponse.setResultMessage("access denied IP");
				return apiResponse;
			}
			
			// TO DO 토큰체크 
			Map data = new HashMap();
			
			try {
				JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token);
				final String LOG_PREFIX = "#-API::AGENT::list::"+tokenInfo.getSid()+"::::";
				
				// POJO to JSON
				ObjectMapper objectMapper = new ObjectMapper();
				String reqJsonStr = objectMapper.writeValueAsString(search);
				org.codehaus.jettison.json.JSONObject reqObj = new org.codehaus.jettison.json.JSONObject(reqJsonStr);
				log.info(LOG_PREFIX+ "Request {}", reqObj);
				
				// 여기서 부터 로직  
				PageFormVO pageVo= new PageFormVO();
				if(search.getUpperSiteId() == null || search.getUpperSiteId().equals("")) {
					search.setUpperSiteId(tokenInfo.getSid());
				}
				
				search.setTopId(tokenInfo.getSid());
				
				//아이디
				log.info(LOG_PREFIX+ "SiteSearch::"+search.toString());
				
				int totalCount = siteService.getSiteListCntForApi(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(10);
					} 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);
					
					data.put("pageInfo", pageVo);
				}
				
				List<HashMap> siteList = siteService.getSiteListForApi(search);
				data.put("siteList", siteList);
				
				List<HashMap> downSiteList = siteService.getMyDownSite(search);		 
				data.put("downSiteList", downSiteList);
			
			} catch(Exception e) {
				log.info(e.toString());
				apiResponse.setResultCode("99995");
				apiResponse.setResultMessage("token is no valid");
				return apiResponse;
			}
			
			apiResponse.setData(data);
			apiResponse.success();
		
		} catch (Exception e) {
			e.printStackTrace();
			apiResponse.fail();
		}
		
		return apiResponse;
	}
	  
	@ResponseBody
	@GetMapping("/detail/{siteIdx}")
	public ApiResponse detail( @RequestHeader String token, HttpServletRequest request, @PathVariable long siteIdx ) 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 data = new HashMap();
			
			
			try {
				JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token);
				
				log.info(tokenInfo.getSid());
			    // 여기서 부터 로직  
				SiteSearch search = new SiteSearch();					
				log.info("siteIdx {}" , site.getSiteIdx());		    	
		    	search.setUpperSiteId(""+site.getSiteId());
		    	
		    	search.setSiteIdx(siteIdx);
		    	search.setTopId(tokenInfo.getSid());
		    	
		    	Site targetSite = siteService.getSiteDetailForApi(search);
		    	data.put("targetSite", targetSite);
		    	data.put("uppersiteIdx", site.getSiteIdx());
		    	
		    	boolean isMyAgent = false;
		    	List<HashMap> treeInfo = targetSite.getTreeInfo();
		    	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;
		    	}
		    	
		    	HashMap<String, String> creditInfo = siteService.getCreditInfo(targetSite.getSiteId());
		    	data.put("creditInfo", creditInfo);
		    	
		    	List<HashMap> vederRateList = siteService.getVenderRateList(targetSite);
		    	List<HashMap> vendorlist = siteService.getVendorListForApi(search);
		    	SiteSearch mySearch = new SiteSearch();
		    	mySearch.setSiteIdx(site.getSiteIdx());
		    	List<HashMap> myVendorlist = siteService.getVendorListForApi(mySearch);
		    	
		    	data.put("vederRateList", vederRateList);
		    	data.put("vendorlist", vendorlist);
		    	data.put("myVendorlist", myVendorlist);
		    	log.info("vederRateList {}", vederRateList.size());
		    	log.info("vederRateList {}", vederRateList);
		    	
		    	// TODO : 에이전트 상세 베팅통계 데이터
		    	
		    	HashMap ydayBetInfo = statService.getYdayBetInfoBySite(targetSite);
		    	log.info("ydayBetInfo {}", ydayBetInfo);
		    	HashMap monthBetInfo = statService.getMonthBetInfoBySite(targetSite);
		    	log.info("monthBetInfo {}", monthBetInfo);
		    	data.put("ydayBetInfo", ydayBetInfo);			// 어제 배팅통계
		    	data.put("monthBetInfo", monthBetInfo);			// 이번달 배팅통계
		
			
			}catch(Exception e) {
				log.info(e.toString());
				apiResponse.setResultCode("99995");
				apiResponse.setResultMessage("token is no valid");
				return apiResponse;
			}
			   
				
			apiResponse.setData(data);
			apiResponse.success();
				
		} catch (Exception e) {
			
			e.printStackTrace();
			apiResponse.fail();
		}
		
		return apiResponse;
		
    }
	
	@ResponseBody
	@GetMapping("/myInfo")
	public ApiResponse myInfo( @RequestHeader String token, HttpServletRequest request) 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 data = new HashMap();
			
			
			try {
				JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token);
				
				log.info(tokenInfo.getSid());
			    // 여기서 부터 로직  
				SiteSearch search = new SiteSearch();					
				log.info("siteIdx {}" , site.getSiteIdx());		    	
		    	
		    	
		    	search.setSiteIdx(site.getSiteIdx());
		    	search.setTopId(tokenInfo.getSid());
		    	
		    	Site targetSite = siteService.getSiteDetailForApi(search);
		    	data.put("targetSite", targetSite);		
		    	data.put("uppersiteIdx", site.getSiteIdx());
		    	
		    	HashMap<String, String> creditInfo = siteService.getCreditInfo(targetSite.getSiteId());
		    	data.put("creditInfo", creditInfo);
		    	
		    	List<HashMap> vederRateList = siteService.getVenderRateList(targetSite);
		    	List<HashMap> vendorlist = siteService.getVendorListForApi(search);
		    	SiteSearch mySearch = new SiteSearch();
		    	mySearch.setSiteIdx(site.getSiteIdx());
		    	List<HashMap> myVendorlist = siteService.getVendorListForApi(mySearch);
		    	
		    	data.put("vederRateList", vederRateList);
		    	data.put("vendorlist", vendorlist);
		    	data.put("myVendorlist", myVendorlist);
		    	log.info("vederRateList {}", vederRateList.size());
		    	log.info("vederRateList {}", vederRateList);
		    	
		    	// TODO : 에이전트 상세 베팅통계 데이터
		    	HashMap ydayBetInfo = statService.getYdayBetInfoBySite(targetSite);
		    	HashMap monthBetInfo = statService.getMonthBetInfoBySite(targetSite);
		    	data.put("ydayBetInfo", ydayBetInfo);			// 어제 배팅통계
		    	data.put("monthBetInfo", monthBetInfo);			// 이번달 배팅통계
		
			
			}catch(Exception e) {
				log.info(e.toString());
				apiResponse.setResultCode("99995");
				apiResponse.setResultMessage("token is no valid");
				return apiResponse;
			}
			   
				
			apiResponse.setData(data);
			apiResponse.success();
				
		} catch (Exception e) {
			
			e.printStackTrace();
			apiResponse.fail();
		}
		
		return apiResponse;
		
    }
	
	
	
	@ResponseBody
	@GetMapping("/tree")
	public ApiResponse tree( @RequestHeader String token, HttpServletRequest request ) 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 data = new HashMap();
			
			
			try {
				JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token);
				
				log.info(tokenInfo.getSid());
			  
				// 하위 사이트 여부체크
				Map checkDown =  new HashMap();
				checkDown.put("me", site.getSiteId());
				checkDown.put("target", site.getSiteId());
				int downCnt = siteService.checkDownSite(checkDown);
				if(downCnt ==0) {
					apiResponse.setResultCode("99993");
					apiResponse.setResultMessage("agent is not valid");
					return apiResponse;
				}
				List<HashMap> treeList = siteService.getSiteTreeList(site.getSiteId());
				data.put("list", treeList);
			
			}catch(Exception e) {
				log.info(e.toString());
				apiResponse.setResultCode("99995");
				apiResponse.setResultMessage("token is no valid");
				return apiResponse;
			}
			   
				
			apiResponse.setData(data);
			apiResponse.success();
				
		} catch (Exception e) {
			
			e.printStackTrace();
			apiResponse.fail();
		}
		
		return apiResponse;
		
    }
	
	
	@ResponseBody
	@GetMapping("/tree/{siteId}")
	public ApiResponse tree( @RequestHeader String token, HttpServletRequest request, @PathVariable String siteId ) 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 data = new HashMap();
			
			
			try {
				JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token);
				
				log.info(tokenInfo.getSid());
			  
				// 하위 사이트 여부체크
				Map checkDown =  new HashMap();
				checkDown.put("me", site.getSiteId());
				checkDown.put("target", siteId);
				int downCnt = siteService.checkDownSite(checkDown);
				if(downCnt ==0) {
					apiResponse.setResultCode("99993");
					apiResponse.setResultMessage("agent is not valid");
					return apiResponse;
				}
				List<HashMap> treeList = siteService.getSiteTreeList(siteId);
				data.put("list", treeList);
			
			}catch(Exception e) {
				log.info(e.toString());
				apiResponse.setResultCode("99995");
				apiResponse.setResultMessage("token is no valid");
				return apiResponse;
			}
			   
				
			apiResponse.setData(data);
			apiResponse.success();
				
		} catch (Exception e) {
			
			e.printStackTrace();
			apiResponse.fail();
		}
		
		return apiResponse;
		
    }
	  
		  
	@ResponseBody
	@RequestMapping("/update")
	public  ApiResponse  siteUpdate( @RequestHeader String token,  HttpServletRequest request, ModelMap model, @RequestBody  Site targetsite) 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 data = new HashMap();
		
		
		try {
			JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token);
			
			log.info(tokenInfo.getSid());
		    // 여기서 부터 로직  
			
			    targetsite.setUpperSiteId(site.getSiteId());
			    targetsite.setUpperSiteIdx(site.getSiteIdx());
			    targetsite.setSiteId(targetsite.getSiteId());
			    
			    int myDownSiteCheck = siteService.getMyDownSiteCheck(targetsite);
			 	if(myDownSiteCheck >0) {
			 		apiResponse.setResultCode("10009");
					apiResponse.setResultMessage("not your bottom sites");
					return apiResponse;
			 	}
			    siteService.siteUpdateForAPI(targetsite)  ;
	
		
		}catch(Exception e) {
			log.info(e.toString());
			apiResponse.setResultCode("99995");
			apiResponse.setResultMessage("token is no valid");
				return apiResponse;
			}
			   
				
			apiResponse.setData(data);
			apiResponse.success();
				
		} catch (Exception e) {
			
			e.printStackTrace();
			apiResponse.fail();
		}
		
		return apiResponse;
  
	
	}
	
	
	@ResponseBody
	@RequestMapping("/updateSitePwd")
	public ApiResponse updateSitePwd(HttpServletRequest request, @RequestHeader String token, @RequestBody SitePwdVO sitePwdVO) 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::Agent::updateSitePwd::"+tokenInfo.getSid()+"::::";
				sitePwdVO.setSiteId(tokenInfo.getSid());
				
				// 여기서 부터 로직
				log.info(LOG_PREFIX + "SitePwdVO::"+sitePwdVO);
				
				int result = siteService.updateSitePwd(sitePwdVO);
				log.info(LOG_PREFIX + "updateSitePwd result::"+result);
				
				if(result > 0) {
					log.info(LOG_PREFIX + "Site password update succ");
					apiResponse.success();
				} else {
					log.error(LOG_PREFIX + "Site password update fail");
					apiResponse.fail();
				}
				
			} catch(Exception e) {
				log.info(e.toString());
				apiResponse.setResultCode("99995");
				apiResponse.setResultMessage("token is no valid");
				return apiResponse;
			}
		} catch (Exception e) {
			e.printStackTrace();
			apiResponse.fail();
		}
		
		return apiResponse;
	}
	
	
	@ResponseBody
	@RequestMapping("/add")
	public ApiResponse add(@RequestHeader String token, HttpServletRequest request, ModelMap model, @RequestBody Site addsite) 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 data = new HashMap();
		
		
		try {
			JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfoAdmin(token);
			final String LOG_PREFIX = "#-API::AGENT_ADD::"+tokenInfo.getSid()+"::";
			
			// POJO to JSON
			ObjectMapper objectMapper = new ObjectMapper();
			String reqJsonStr = objectMapper.writeValueAsString(addsite);
			org.codehaus.jettison.json.JSONObject reqObj = new org.codehaus.jettison.json.JSONObject(reqJsonStr);
			log.info(LOG_PREFIX+ "Request {}", reqObj);
			
			log.info(tokenInfo.getSid());
		    // 하부사이트 체크
			Site targetsite = new Site();
			targetsite.setUpperSiteId(site.getSiteId());
		    targetsite.setUpperSiteIdx(site.getSiteIdx());
		    targetsite.setSiteId(addsite.getUpperSiteId());
		    
		    if(addsite.getIsTransfer() == null || "".equals(addsite.getIsTransfer())) {
		    	addsite.setIsTransfer("N");
		    }
		    
		    int myDownSiteCheck = siteService.getMyDownSiteCheck(targetsite);
		 	if(myDownSiteCheck >0) {
		 		apiResponse.setResultCode("10009");
				apiResponse.setResultMessage("not your bottom sites");
				return apiResponse;
		 	}
			
			
			addsite.setUpperSiteId(addsite.getUpperSiteId());
			addsite.setUpperSiteIdx(addsite.getUpperSiteIdx());
			addsite.setSiteKey(makeApiKey(addsite.getSiteId()));
			log.info(LOG_PREFIX+ "addsite {}", addsite);
			
			Site dupSite = siteService.getSite(addsite);
			
			log.info(LOG_PREFIX+ "dupSite []", dupSite);
			if(dupSite!=null) {
				apiResponse.setResultCode("99990");
				apiResponse.setResultMessage("already siteId");
					return apiResponse;
				 
			} else {
				
				Site upperSite = new Site();
				upperSite.setSiteId(addsite.getUpperSiteId());
				upperSite = siteService.getSite(upperSite);
				
				addsite.setSiteLevel(upperSite.getSiteLevel()+1);
				siteService.addProcAPI(addsite);		
			}
		
		} catch(Exception e) {
			log.error("#-API::AGENT_ADD::"+ e.toString());
			apiResponse.setResultCode("99995");
			apiResponse.setResultMessage("token is no valid");
				return apiResponse;
			}
			   
				
			apiResponse.setData(data);
			apiResponse.success();
				
		} catch (Exception e) {
			
			e.printStackTrace();
			apiResponse.fail();
		}
		
		return apiResponse;
  
	
	}
	  	
	/**
	 * 외부 API 호출 공통 프라이빗 메서드 (중복 코드 방지용)
	 */
	private void sendExternalRateChange(String url, String siteKey, String vendorName, Object vendorIdx, Object rate) {
		try {
			log.info("##### WebClient External Call Start ##### URL: {}", url);
			
			JSONObject paramBody = new JSONObject();
			paramBody.put("siteApiKey", siteKey);
			paramBody.put("vendor", vendorName);
			paramBody.put("vendorIdx", vendorIdx);
			paramBody.put("gameRate", rate);

			String response = webClient.post()
					.uri(url)
					.contentType(MediaType.APPLICATION_JSON)
					.accept(MediaType.APPLICATION_JSON)
					.header("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36")
					.bodyValue(paramBody.toString())
					.retrieve()
					.bodyToMono(String.class)
					.block(); // 동기 방식

			log.info("##### WebClient Response: {}", response);
		} catch (Exception e) {
			log.error("##### WebClient Call Error: {}", e.getMessage());
		}
	}

	@RequestMapping("/creditRateSave")
	public @ResponseBody JSONObject creditRateSave(HttpServletRequest request, ModelMap model, CommonParamAdmin commonParamAdmin) throws Exception {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		Site loginSite = (Site) authentication.getDetails();
		
		Site site = siteService.getSiteInfoAPI(request);
		String siteUrl = site.getSiteCbUrl() + "/gameRateChange";
		
		JSONObject obj = new JSONObject();
		log.info("#-CREDIT_RATE_SAVE::: CommonParamAdmin: {}", commonParamAdmin.toString());
		
		for (int i = 0; i < commonParamAdmin.getParamlist().length; i++) {
			JSONObject paramData = commonParamAdmin.getParamlist()[i];
			paramData.put("siteIdx", commonParamAdmin.getParam().get("targetSiteIdx"));
			paramData.put("insureUpSiteIdX", loginSite.getSiteIdx());
			
			ObjectMapper mapper = new ObjectMapper();
			HashMap paramMap = mapper.readValue(paramData.toString(), new TypeReference<HashMap>() {});
			
			if (paramMap.get("vendorIdx") != null) {
				int type = Integer.parseInt(paramMap.get("type").toString());
				if (type == 0) {
					siteService.saveVendorRate(paramMap);
				}
				siteService.saveSvcr(paramMap, 1); // 1로 고정된 비즈니스 로직 유지
				
				if (type == 0) {
					String siteKey = siteService.getSiteKey(paramMap);
					String vendorName = siteService.getVendorTitle(paramMap);
					sendExternalRateChange(siteUrl, siteKey, vendorName, paramMap.get("vendorIdx"), paramMap.get("rate"));
				}
				
				if (loginSite.getSiteLevel() < 1) {
					siteService.updateVendorUseYn(paramMap);
				}
			}
		}
		obj.put("RES", "SUCCESS");
		return obj;
	}

	@RequestMapping("/saveSvcr")
	public @ResponseBody JSONObject saveSvcr(HttpServletRequest request, ModelMap model, CommonParamAdmin commonParamAdmin) throws Exception {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		Site loginSite = (Site) authentication.getDetails();
		
		JSONObject obj = new JSONObject();
		ObjectMapper mapper = new ObjectMapper();
		HashMap paramMap = mapper.readValue(commonParamAdmin.getParam().toString(), new TypeReference<HashMap>() {});
		
		String siteUrl = loginSite.getSiteCbUrl() + "/gameRateChange";
		
		if (paramMap.get("vendorIdx") != null) {
			paramMap.put("siteIdx", commonParamAdmin.getParam().get("targetSiteIdx"));  
			int type = Integer.parseInt(paramMap.get("type").toString());
			
			if (type == 0) {
				siteService.saveVendorRate(paramMap);               
			}
			siteService.saveSvcr(paramMap, type);
			
			if (type == 0) {
				String siteKey = siteService.getSiteKey(paramMap);
				String vendorName = siteService.getVendorTitle(paramMap);
				sendExternalRateChange(siteUrl, siteKey, vendorName, paramMap.get("vendorIdx"), paramMap.get("rate"));
			}           
			
			if (loginSite.getSiteLevel() < 1) {
				siteService.updateVendorUseYn(paramMap);
			}
		}
		obj.put("RES", "SUCCESS");
		return obj;
	}

	@RequestMapping("/saveSvcrAll")
	public @ResponseBody JSONObject saveSvcrAll(HttpServletRequest request, ModelMap model, CommonParamAdmin commonParamAdmin) throws Exception {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		Site loginSite = (Site) authentication.getDetails();
		
		JSONObject obj = new JSONObject();
		String siteUrl = loginSite.getSiteCbUrl() + "/gameRateChange";
		
		for (int i = 0; i < commonParamAdmin.getParamlist().length; i++) {
			JSONObject paramData = commonParamAdmin.getParamlist()[i];
			paramData.put("siteIdx", commonParamAdmin.getParam().get("targetSiteIdx"));
				
			ObjectMapper mapper = new ObjectMapper();
			HashMap paramMap = mapper.readValue(paramData.toString(), new TypeReference<HashMap>() {});
		
			if (paramMap.get("vendorIdx") != null) {
				int type = Integer.parseInt(paramMap.get("type").toString());
				if (type == 0) {
					siteService.saveVendorRate(paramMap);               
				}
				siteService.saveSvcr(paramMap, type);
				
				if (type == 0) {
					String siteKey = siteService.getSiteKey(paramMap);
					String vendorName = siteService.getVendorTitle(paramMap);
					sendExternalRateChange(siteUrl, siteKey, vendorName, paramMap.get("vendorIdx"), paramMap.get("rate"));
				}           
				
				if (loginSite.getSiteLevel() < 1) {
					siteService.updateVendorUseYn(paramMap);
				}
			}
		}
		obj.put("RES", "SUCCESS");
		return obj;
	}

	@RequestMapping("/siteVenderUpdate")
	public @ResponseBody JSONObject siteVenderUpdate(HttpServletRequest request, ModelMap model, Vendor vendor) throws Exception {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		Site loginSite = (Site) authentication.getDetails();
		
		Site site = siteService.getSiteInfoAPI(request);
		String siteUrl = site.getSiteCbUrl() + "/gameRateChange";
			
		JSONObject obj = new JSONObject();          
		vendor.setSiteIdx(loginSite.getSiteIdx());
		
		try {
			siteService.siteVenderUpdate(vendor);
			
			String siteKey = loginSite.getSiteKey();
			String vendorName = vendor.getVendorCode();
			
			// 벤더 이름 가공 로직
			if (vendorName.startsWith("gsoft_")) vendorName = "gsoft";
			if (vendorName.startsWith("trump_")) vendorName = "trump";
			if (vendorName.startsWith("ppk_")) vendorName = "ppk";
			if (vendorName.startsWith("sg_")) vendorName = "sg";
			
			String venderRate = siteService.siteVenderRate(vendor);
			
			// 공통 메서드 호출
			sendExternalRateChange(siteUrl, siteKey, vendorName, vendor.getVendorIdx(), venderRate);
			
			obj.put("RES", "SUCCESS");
		} catch (Exception e) {
			log.error("#-SITE_VENDOR_UPDATE Error: {}", e.toString());
			obj.put("RES", "FAIL"); 
		}
		return obj;
	}

	  @RequestMapping("/insurePoinRateSave")
	     public @ResponseBody JSONObject  insurePointRateSave( HttpServletRequest request, ModelMap model,  CommonParamAdmin commonParamAdmin ) throws Exception {
			  
			Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		    Site loginSite = (Site)authentication.getDetails();
		    
		   
		    
		    
			JSONObject obj = new JSONObject();
	     	log.info(commonParamAdmin.toString());
	     	
	     	for(int i=0;i<commonParamAdmin.getParamlist().length;i++) {
	     		JSONObject paramData = commonParamAdmin.getParamlist()[i];
	     		paramData.put("siteIdx", commonParamAdmin.getParam().get("targetSiteIdx"));
	     		paramData.put("insureUpSiteIdX", loginSite.getSiteIdx());
	     		log.info(paramData.toString());
	     		
	     		ObjectMapper mapper = new ObjectMapper();
				HashMap paramMap = mapper.readValue(paramData.toString(), new TypeReference<HashMap>() {});
	     		
	     		siteService.saveVendorInsurePointRate(paramMap);
	     	}
	     	
	     	
	     	
	     	  		      	
	     
		           
	     	obj.put("RES", "SUCCESS");
	     
	 		return obj;
	     }
	  
	  
	  @RequestMapping("/addProc")
      public @ResponseBody JSONObject  addProc( HttpServletRequest request, ModelMap model,  Site site) throws Exception {
		  
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
	    Site loginSite = (Site)authentication.getDetails();
	    site.setUpperSiteId(loginSite.getSiteId());
	    site.setUpperSiteIdx(loginSite.getSiteIdx());
	    
	    
	    
	    site.setSiteKey(makeApiKey(site.getSiteId()));
	    
	    
      	JSONObject obj = new JSONObject();      	
  		
      	log.info(site.toString());
      	siteService.addProcAPI(site);		 
	           
      	obj.put("RES", "SUCCESS");
      
  		return obj;
      }
	  
	  @GetMapping("/transaction")
	    public String transaction( HttpServletRequest request , ModelMap model , @ModelAttribute("searchVO") SiteSearch search) 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());
	    	long sitePoint = siteService.getSitePoint(loginSite.getSiteId());
	    	model.put("sitePoint", sitePoint);	
	    	model.put("siteCredit", siteCredit);	
	    	model.put("underSiteCredit", underSiteCredit);
	    	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);	  
	    	
	    	
	    	String nowtime = new SimpleDateFormat("yyyy-MM-dd").format(new Date(System.currentTimeMillis()));	
	    	if(search.getStartDate() == null || "".equals(search.getStartDate())) {
	    		search.setStartDate(nowtime);
	    	}
	    	
	    	if(search.getEndDate() == null || "".equals(search.getEndDate())) {
	    		search.setEndDate(nowtime);
	    	}
	    	
	    	if(search.getSearchSiteId() == null || "".equals(search.getSearchSiteId())) {
	    		search.setSearchSiteId(loginSite.getSiteId());
	    	}
	    	 
	    	
	    	PageFormVO pageVo= new PageFormVO();	    	
	    	search.setSiteId(loginSite.getSiteId());
	    	search.setSiteIdx(loginSite.getSiteIdx());
	    	
						
			int totalCount = creditService.getSiteTranListCnt(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);
				
				model.put("pageInfo", pageVo);
			}
			
		
			List<HashMap> list = creditService.getSiteTranList(search);
			log.debug(""+list.size());
			model.put("list", list);
			
			List<HashMap> downSiteList = siteService.getMyDownSite(search);		 
			model.put("downSiteList", downSiteList);
			
	    	
	    	return "admin/transaction";        
	    }  
	  
	  
	  @GetMapping("/gamelink")
	    public String gamelink( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) 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());
	    	long sitePoint = siteService.getSitePoint(loginSite.getSiteId());
	    	model.put("sitePoint", sitePoint);	
	    	model.put("siteCredit", siteCredit);	
	    	model.put("underSiteCredit", underSiteCredit);
	    	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);	 
	    	
	    	search.setSiteIdx(loginSite.getSiteIdx());
	    	List<HashMap> mylist = siteService.getSiteVendorListForApi(search);
	    	
	    	
	    	List<HashMap> vendorlist = siteService.getVendorListForApi(search);
	    	
	    	model.put("mylist", mylist);	  
	    	model.put("vendorlist", vendorlist);	 
		  
	    	return "admin/gamelink";        
	    }
	  
	  @GetMapping("/venderset")
	    public String venderset( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) 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());
	    	long sitePoint = siteService.getSitePoint(loginSite.getSiteId());
	    	model.put("sitePoint", sitePoint);	
	    	model.put("siteCredit", siteCredit);	
	    	model.put("underSiteCredit", underSiteCredit);
	    	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);	 
	    	
	    	search.setSiteIdx(loginSite.getSiteIdx());
	    	List<HashMap> mylist = siteService.getSiteVendorListForApi(search);
	    	
	    	
	    	List<HashMap> vendorlist = siteService.getVendorListForApi(search);
	    	
	    	model.put("mylist", mylist);	  
	    	model.put("vendorlist", vendorlist);	 
		  
	    	return "admin/venderset";        
	    }
	  
	  @GetMapping("/gameCompanySet")
	    public String gameCompanySet( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) 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());
	    	long sitePoint = siteService.getSitePoint(loginSite.getSiteId());
	    	model.put("sitePoint", sitePoint);	
	    	model.put("siteCredit", siteCredit);	
	    	model.put("underSiteCredit", underSiteCredit);
	    	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);	 
	    	
	    	search.setSiteIdx(loginSite.getSiteIdx());
	    	List<HashMap> mylist = siteService.getSiteVendorListForApi(search);
	    	
	    	
	    	List<HashMap> vendorlist = siteService.getVendorListForApi(search);
	    	
	    	model.put("mylist", mylist);	  
	    	model.put("vendorlist", vendorlist);	 
		  
	    	return "admin/gameCompanySet";        
	    }
	  
	  @GetMapping("/gameSet")
	    public String gameSet( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) 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());
	    	long sitePoint = siteService.getSitePoint(loginSite.getSiteId());
	    	model.put("sitePoint", sitePoint);	
	    	model.put("siteCredit", siteCredit);	
	    	model.put("underSiteCredit", underSiteCredit);
	    	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);	 
	    	
	    	search.setSiteIdx(loginSite.getSiteIdx());
	    	List<HashMap> mylist = siteService.getSiteVendorListForApi(search);
	    	
	    	
	    	List<HashMap> vendorlist = siteService.getVendorListForApi(search);
	    	
	    	model.put("mylist", mylist);	  
	    	model.put("vendorlist", vendorlist);	 
		  
	    	return "admin/gameSet";        
	    }
	  
	  
	  
	  @GetMapping("/betlimit")
	    public String betlimit( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) 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());
	    	long sitePoint = siteService.getSitePoint(loginSite.getSiteId());
	    	model.put("sitePoint", sitePoint);	
	    	model.put("siteCredit", siteCredit);	
	    	model.put("underSiteCredit", underSiteCredit);
	    	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);	 
	    	
	    	search.setSiteIdx(loginSite.getSiteIdx());
	    	List<HashMap> mylist = siteService.getSiteVendorListForApi(search);
	    	
	    	search.setSearchType("union");
	    	search.setSiteIdx(loginSite.getSiteIdx());
	    	List<HashMap> vendorMaplist = siteService.getVendorMapList(search);
	    	
	    	model.put("mylist", mylist);	  
	    	model.put("vendorlist", vendorMaplist);	 
		  
	    	return "admin/betlimit";        
	    }
	  
	  @RequestMapping("/betlimitUpdate")
      public @ResponseBody JSONObject  betlimitUpdate( HttpServletRequest request, ModelMap model,  Vendor vendor) throws Exception {
		  
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
	    Site loginSite = (Site)authentication.getDetails();
		    
      	JSONObject obj = new JSONObject();      	
  		
      	vendor.setSiteIdx(loginSite.getSiteIdx());
      	try {
      		siteService.siteVenderLobbyUpdate(vendor);		 
	           
      	obj.put("RES", "SUCCESS");
      	}catch(Exception e) {
      		System.out.print(e.toString());
      		obj.put("RES", "FAIL");	
      	}
  		return obj;
      }
	  
	  @GetMapping("/gamemanage")
	  public String gameManage( HttpServletRequest request , ModelMap model, @ModelAttribute("searchVO") SiteSearch search) 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());
	    	long sitePoint = siteService.getSitePoint(loginSite.getSiteId());
	    	model.put("sitePoint", sitePoint);	
	    	model.put("siteCredit", siteCredit);	
	    	model.put("underSiteCredit", underSiteCredit);
	    	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);	 
	    	
	    	search.setSiteIdx(loginSite.getSiteIdx());
	    	List<HashMap> mylist = siteService.getSiteVendorListForApi(search);
	    	
	    	
	    	List<HashMap> vendorlist = siteService.getVendorListForApi(search);
	    	
	    	model.put("mylist", mylist);	  
	    	model.put("vendorlist", vendorlist);
	    	
	    	return "admin/gameManage";        
	    }
	  
	  
	  @RequestMapping("/getMyDownSite")
      public @ResponseBody JSONObject  getMyDownSite( HttpServletRequest request, ModelMap model,  SiteSearch search) throws Exception {
		  
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
	    Site loginSite = (Site)authentication.getDetails();
		    
      	JSONObject obj = new JSONObject();      	
      	search.setSiteId(loginSite.getSiteId());
  		
      	try {
      		List<HashMap> downSiteList = siteService.getMyDownSite(search);		 
      		obj.put("downSiteList", downSiteList);
      	obj.put("RES", "SUCCESS");
      	}catch(Exception e) {
      		obj.put("RES", "FAIL");	
      	}
  		return obj;
      }
	  
	  
	 
	 
	  
	  
	  
	 
	  private String makeApiKey(String param) {
		  
		   int n = 24; // 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  sb.toString();
		  
		  
	  }
	  
	
}
