package com.bb.service;

import java.net.SocketTimeoutException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;

import org.apache.http.conn.ConnectTimeoutException;
import io.netty.handler.timeout.ReadTimeoutException;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientRequestException;
import org.springframework.web.reactive.function.client.WebClientResponseException;

import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class PowerBallServiceImpl implements PowerBallService {

	@Autowired
	WebClient webClient;
/*
	@Override
	public JSONObject registSite(HashMap<String, String> param, String LOG_PREFIX) {
		JSONObject jsonObj = null;
		// https://api.tpower.cc
		final String apiBaseUrl = "https://api.tpower.cc";
		
		try {
			HttpHeaders headers = new HttpHeaders();
    		headers.setContentType(MediaType.APPLICATION_JSON);
    		headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
    		headers.set("User-Agent", "PostmanRuntime/7.28.4");
    		headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
    		
    		JSONObject params = new JSONObject();
			params.put("siteName", param.get("apiSiteId").toString());
			params.put("siteUrl", "http://lbc.toserver.cc/api/callback/powerball");
			params.put("callbackUrl", "http://lbc.toserver.cc/api/callback/powerball");
			params.put("apiKey", param.get("apiKey").toString());
			
			// String apiUrl = param.get("apiBaseUrl").toString() + "/registSite";
			String apiUrl = apiBaseUrl + "/registSite";
			log.info(LOG_PREFIX+ "PowerBall::registSite::"+ "Url: " + apiUrl);
			log.info(LOG_PREFIX+ "PowerBall::registSite::"+ "Headers: " + headers.toString());
			log.info(LOG_PREFIX+ "PowerBall::registSite::"+ "Params: " + params.toString());
			
			HttpEntity<String> entity = new HttpEntity<String>(params.toString(), headers);
			ResponseEntity<String> res = restTemplate.exchange(apiUrl, HttpMethod.POST, entity, String.class);
			log.info(LOG_PREFIX+ "PowerBall::registSite::"+ "response : " + res.getBody());
			jsonObj = new JSONObject(res.getBody());
    		
		} catch (ResourceAccessException rae) {
            if(rae.getCause() instanceof ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "PowerBall::registSite::"+ "[ConnectTimeoutException]"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof SocketTimeoutException) {
            	log.error(LOG_PREFIX+ "PowerBall::registSite::"+ "[SocketTimeoutException]"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "PowerBall::registSite::"+ "[InterruptedException]"+rae.getMessage());
            }
		} catch(HttpClientErrorException hee) {
			String str = hee.getResponseBodyAsString();
			log.error(LOG_PREFIX+ "PowerBall::registSite::"+ "[HttpClientErrorException]"+str);
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "PowerBall::registSite::"+ "[Exception]"+e.toString());
			e.printStackTrace();
        }
		
		return jsonObj;
	}

	@Override
	public String getLaunchUrl(HashMap<String, String> param, String LOG_PREFIX) {
		String gameUrl = null;
		// https://user.tpower.cc
		final String apiBaseUrl = "https://user.tpower.cc";
		
		try {
			HttpHeaders headers = new HttpHeaders();
    		headers.setContentType(MediaType.APPLICATION_JSON);
    		headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
    		headers.set("User-Agent", "PostmanRuntime/7.28.4");
    		headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
    		headers.set("apikey", param.get("apiKey").toString());
    		
    		JSONObject params = new JSONObject();
			params.put("id", param.get("apiUserId").toString());
			params.put("siteName", param.get("apiSiteId").toString());
			params.put("device", param.get("device").toString());
			
			// String apiUrl = param.get("apiBaseUrl").toString() + "/auth/" + param.get("apiGameName").toString();
			String apiUrl = apiBaseUrl + "/auth/" + param.get("apiGameName").toString();
			log.info(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "Url: " + apiUrl);
			log.info(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "Headers: " + headers.toString());
			log.info(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "Params: " + params.toString());
			
			HttpEntity<String> entity = new HttpEntity<String>(params.toString(), headers);
			ResponseEntity<String> res = restTemplate.exchange(apiUrl, HttpMethod.POST, entity, String.class);
			
			JSONObject resObj = new JSONObject(res.getBody());
			if(resObj.getString("result").equals("SUCCESS")) {
				JSONObject dataObj = resObj.getJSONObject("data");
				gameUrl = dataObj.getString("url");
				log.info(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "gameUrl: " + gameUrl);
			} else {
				log.error(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "ERROR::result : " + resObj.getString("result") + ", message: " + resObj.getString("message"));
			}
			
		} catch (ResourceAccessException rae) {
            if(rae.getCause() instanceof ConnectTimeoutException) {
            	log.error(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[ConnectTimeoutException]"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof SocketTimeoutException) {
            	log.error(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[SocketTimeoutException]"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[InterruptedException]"+rae.getMessage());
            }
		} catch(HttpClientErrorException hee) {
			String str = hee.getResponseBodyAsString();
			log.error(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[HttpClientErrorException]"+str);
		} catch (Exception e) {
			log.error(LOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[Exception]"+e.toString());
			e.printStackTrace();
        }
		
		return gameUrl;
	}
*/
	@Override
	public String getGameUrl(HashMap venderInfo, String lOG_PREFIX) {
	    String gameUrl = "";
	    try {
	        
	        HttpHeaders headers = new HttpHeaders();
	        headers.setContentType(MediaType.APPLICATION_JSON);
	        headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
	        headers.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
	        
	        // 실제 브라우저와 동일한 헤더 순서와 값으로 설정
	        headers.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
	        headers.set("Accept", "application/json, text/plain, */*");
	        headers.set("Accept-Language", "ko-KR,ko;q=0.9,en;q=0.8");
	        // Accept-Encoding 헤더 제거 또는 단순화 (압축 해제 문제 방지)
	        // headers.set("Accept-Encoding", "gzip, deflate, br");
	        headers.set("Connection", "keep-alive");
	        
	        // Cloudflare 우회를 위한 추가 헤더
	        headers.set("Cache-Control", "no-cache");
	        headers.set("Pragma", "no-cache");
	        headers.set("DNT", "1");
	        
	        // 실제 POST 요청에 맞는 Sec-Fetch 헤더
	        headers.set("Sec-Fetch-Dest", "empty");
	        headers.set("Sec-Fetch-Mode", "cors");
	        headers.set("Sec-Fetch-Site", "same-origin");
	        
	        // Origin과 Referer를 더 구체적으로 설정
	        headers.set("Origin", "https://api.tpower.cc");
	        headers.set("Referer", "https://api.tpower.cc/api/v1/auth");
	        
	        // JA3 fingerprint 우회를 위한 추가 헤더
	        headers.set("sec-ch-ua", "\"Not_A Brand\";v=\"8\", \"Chromium\";v=\"120\", \"Google Chrome\";v=\"120\"");
	        headers.set("sec-ch-ua-mobile", "?0");
	        headers.set("sec-ch-ua-platform", "\"Windows\"");
	        
	        
	        JSONObject params = new JSONObject();
	        params.put("userId", venderInfo.get("userId").toString());
	        params.put("siteKey", venderInfo.get("vendorApiId").toString());
	        params.put("gameKey", venderInfo.get("vendorGameCode").toString());
	        
	        log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "venderInfo: " + venderInfo.toString());
	        
	        HttpEntity<String> entity = new HttpEntity<String>(params.toString(), headers);
	        
	        // 307 리다이렉트 처리를 위한 수정된 로직
	        ResponseEntity<String> res = null;
	        int maxRetries = 3;
	        int retryCount = 0;
	        
	        while (retryCount < maxRetries) {
	            try {
	                if (retryCount > 0) {
	                    Thread.sleep(2000); // 2초 대기
	                    log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Retrying... attempt: " + (retryCount + 1));
	                }
	                
	                // 307 리다이렉트를 수동으로 처리
	                // res = restTemplate.exchange("https://api.tpower.cc/api/v1/auth", HttpMethod.POST, entity, String.class);
	                
	                res = webClient.post()
	                		.uri("https://api.tpower.cc/api/v1/auth")
	                		.headers(h -> h.addAll(headers))
	                		.bodyValue(params.toString())
	                		.retrieve()
	                		.toEntity(String.class)
	                		.block();
	                
	                log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Response status: " + res.getStatusCode());
	                log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Response headers: " + res.getHeaders());
	                
	                // 307 리다이렉트 처리
	                if (res.getStatusCode().value() == 307) {
	                    String locationHeader = res.getHeaders().getFirst("Location");
	                    log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "307 Redirect to: " + locationHeader);
	                    
	                    if (locationHeader != null && !locationHeader.isEmpty()) {
	                        // 리다이렉트된 URL로 다시 요청
	                        log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Following redirect to: " + locationHeader);
	                        
	                        // 새로운 URL이 상대 경로인 경우 절대 경로로 변환
	                        String redirectUrl = locationHeader;
	                        if (locationHeader.startsWith("/")) {
	                            redirectUrl = "https://api.tpower.cc" + locationHeader;
	                        }
	                        
	                        // HTTP를 HTTPS로 변경 (보안상 더 안전)
	                        if (redirectUrl.startsWith("http://")) {
	                            redirectUrl = redirectUrl.replace("http://", "https://");
	                        }
	                        
	                        // 인코딩 문제 해결을 위한 새로운 헤더 설정
	                        HttpHeaders redirectHeaders = new HttpHeaders();
	                        redirectHeaders.setContentType(MediaType.APPLICATION_JSON);
	                        redirectHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
	                        redirectHeaders.setAcceptCharset(Arrays.asList(Charset.forName("UTF-8")));
	                        redirectHeaders.set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
	                        redirectHeaders.set("Accept", "application/json, text/plain, */*");
	                        redirectHeaders.set("Accept-Language", "ko-KR,ko;q=0.9,en;q=0.8");
	                        redirectHeaders.set("Connection", "keep-alive");
	                        redirectHeaders.set("Cache-Control", "no-cache");
	                        
	                        // HttpEntity<String> redirectEntity = new HttpEntity<String>(params.toString(), redirectHeaders);
	                        
	                        // 리다이렉트된 URL로 재요청
	                        // res = restTemplate.exchange(redirectUrl, HttpMethod.POST, redirectEntity, String.class);
	                        
	                        res = webClient.post()
	                        		.uri(redirectUrl)
	                        		.headers(h -> h.addAll(redirectHeaders))
	                        		.bodyValue(params.toString())
	                        		.retrieve()
	                        		.toEntity(String.class)
	                        		.block();
	                        
	                        log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Redirect response status: " + res.getStatusCode());
	                        
	                        // 응답 본문 길이 체크 후 로그 출력
	                        String responseBody = res.getBody();
	                        if (responseBody != null) {
	                            // UTF-8으로 다시 디코딩 시도
	                            try {
	                                byte[] bytes = responseBody.getBytes("ISO-8859-1");
	                                String utf8Body = new String(bytes, "UTF-8");
	                                log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "UTF-8 decoded response body: " + 
	                                        (utf8Body.length() > 1000 ? utf8Body.substring(0, 1000) + "..." : utf8Body));
	                                responseBody = utf8Body;
	                            } catch (Exception encodingEx) {
	                                log.warn(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "UTF-8 decoding failed, using original: " + 
	                                        (responseBody.length() > 1000 ? responseBody.substring(0, 1000) + "..." : responseBody));
	                            }
	                        }
	                        
	                        // 수정된 응답을 다시 설정
	                        if (responseBody != null) {
	                            res = new ResponseEntity<>(responseBody, res.getHeaders(), res.getStatusCode());
	                        }
	                        
	                    } else {
	                        log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "307 Redirect but no Location header found");
	                        retryCount++;
	                        continue;
	                    }
	                }
	                
	                break; // 성공하면 루프 탈출
	                
	            } catch (WebClientResponseException e) {
	                retryCount++;
	                if (e.getStatusCode().is5xxServerError()) {
	                    log.warn(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Server error. Status: " + e.getStatusCode() + ", attempt: " + retryCount);
	                    if (retryCount >= maxRetries) {
	                        log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Max retries reached. Server error: " + e.getStatusCode());
	                        throw e;
	                    }
	                    continue;
	                } else if (e.getStatusCode().is4xxClientError()) {
	                    log.warn(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Client error. Status: " + e.getStatusCode() + ", attempt: " + retryCount);
	                    if (e.getStatusCode().value() == 403 || e.getStatusCode().value() == 429) {
	                        if (retryCount >= maxRetries) {
	                            throw e;
	                        }
	                        continue;
	                    } else {
	                        throw e;
	                    }
	                } else {
	                    throw e;
	                }
	            } catch (Exception e) {
	                retryCount++;
	                log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Exception in retry loop: " + e.getMessage());
	                if (retryCount >= maxRetries) {
	                    throw e;
	                }
	            }
	        }
	        
	        // 응답 처리
	        if (res != null && res.getBody() != null) {
	            log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Final response body: " + res.getBody());
	            
	            JSONObject resObj = new JSONObject(res.getBody());
	            if (resObj.has("success") && resObj.getBoolean("success")) {
	                JSONObject dataObj = resObj.getJSONObject("data");
	                gameUrl = dataObj.getString("url");
	                log.info(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "gameUrl: " + gameUrl);
	            } else {
	                // success가 false인 경우 상세 에러 로그
	                log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "API returned success=false");
	                if (resObj.has("result")) {
	                    log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "result: " + resObj.getString("result"));
	                }
	                if (resObj.has("message")) {
	                    log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "message: " + resObj.getString("message"));
	                }
	                if (resObj.has("error")) {
	                    log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "error: " + resObj.getString("error"));
	                }
	            }
	        } else {
	            log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Response is null or empty");
	        }
	        
	    } catch (WebClientResponseException e) {
	        String str = e.getResponseBodyAsString();
	        if (e.getStatusCode().is5xxServerError()) {
	            log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "[HttpServerErrorException] Status: " + 
	                     e.getStatusCode() + ", Body: " + (str != null && str.length() > 500 ? str.substring(0, 500) + "..." : str));
	            
	            // Cloudflare 502 에러 감지
	            if (str != null && (str.contains("cloudflare") || str.contains("Bad Gateway") || str.contains("502"))) {
	                log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Cloudflare 502 Bad Gateway detected!");
	            }
	        } else if (e.getStatusCode().is4xxClientError()) {
	            log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "[HttpClientErrorException] Status: " + 
	                     e.getStatusCode() + ", Body: " + str);
	            
	            // Cloudflare 차단 여부 확인
	            if (str != null && (str.contains("cloudflare") || str.contains("Access denied") || str.contains("blocked"))) {
	                log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "Cloudflare protection detected!");
	            }
	        }
	        
	    } catch (WebClientRequestException rae) {
            if(rae.getCause() instanceof ConnectTimeoutException) {
            	log.error(lOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[ConnectTimeoutException]"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof ReadTimeoutException) {
            	log.error(lOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[SocketTimeoutException]"+rae.getMessage());
            }
        
            if(rae.getCause() instanceof InterruptedException) {
            	log.error(lOG_PREFIX+ "PowerBall::getLaunchUrl::"+ "[InterruptedException]"+rae.getMessage());
            }
	    } catch (Exception e) {
	        log.error(lOG_PREFIX + "PowerBall::getLaunchUrl::" + "[Exception]" + e.toString());
	        e.printStackTrace();
	    }
	    
	    return gameUrl;
	}
}