package com.bb.front;

import java.io.IOException;
import java.net.InetAddress;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.PostMapping;
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.bind.annotation.RestController;

import com.bb.exception.ApiException;
import com.bb.jwt.JwtManager;
import com.bb.model.ApiResponse;
import com.bb.model.CoinVo;
import com.bb.model.Site;
import com.bb.service.CoinService;
import com.bb.service.SiteService;

import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

@RestController
@Slf4j
@RequestMapping("/api/coin")
@RequiredArgsConstructor
@SecurityRequirement(name = "Authorization")
public class ApiCoinController {
	
	@Autowired
	private final JwtManager jwtManager;

	@Autowired
	SiteService siteService;
	
	@Autowired
	CoinService coinService;
	
	@ResponseBody	
	@PostMapping(value="")
	public ApiResponse getCoinInfo(@RequestHeader String token, HttpServletRequest request) throws Exception {
		ApiResponse apiResponse = new ApiResponse();

		String coinSymbol = request.getParameter("symbol");
		String currency = request.getParameter("currency");
		try {
				
					
			//apiKey 체크
			Site site = siteService.getSiteInfo(request);
			if(site==null) {
				throw new ApiException("1000", "accessDinied");
			}
			if(token==null) {
				throw new ApiException("1000", "accessDinied");
			}			
			
			//토큰체크	
			JwtManager.TokenInfo tokenInfo = jwtManager.getTokenInfo(token);
			if(token == null) {
				log.error("#-p1::agentBalance::"+ "access denied token");
				throw new ApiException("1000", "access denied token");
			}
			
			              
			 CoinVo coinVo = coinService.getCoinInfo(coinSymbol, currency);
			
		
			apiResponse.put("info",coinVo);
			apiResponse.success();
			return apiResponse;

		
		}catch(Exception e) {
			log.info("ddd" +e.toString());
			apiResponse.fail();
			return apiResponse;
		}
	}
	
	@Scheduled(fixedDelay = 300*1000) // 5분
	public void getCoinAllInfo() throws Exception {
		
//		Authentication auth = 
//		        new UsernamePasswordAuthenticationToken("system", null, 
//		            AuthorityUtils.createAuthorityList("ROLE_ADMIN"));
//		    SecurityContextHolder.getContext().setAuthentication(auth);
		
		String hostname = InetAddress.getLocalHost().getHostName();
		if("ip-172-31-40-216.ap-northeast-3.compute.internal".equals(hostname)) { // 3번 서버 호스트 네임으로 빠꺼야함
			String[] currency = {"usd","krw"};
			String cgApiKey = "CG-wJAwrJWZCSbzmBhk545CTcR3";
			try {
					
				for(int cu=0;cu<currency.length;cu++) {		
				
				
				OkHttpClient client = new OkHttpClient();
	
				Request req = new Request.Builder()
				  .url("https://pro-api.coingecko.com/api/v3/coins/markets?vs_currency="+currency[cu])
				  .get()
				  .addHeader("accept", "application/json")
				  .addHeader("x-cg-pro-api-key", cgApiKey)
				  .build();	
				
				try (Response response = client.newCall(req).execute()) {
					
				    if (!response.isSuccessful()) {
				        log.info("Request failed with code: " + response.code());
				    } else {
				    	  String responseBody = response.body().string(); // 응답 본문 저장
				          // log.info("Response: " + responseBody);
	
				          // JSON 처리 예제
				          JSONArray coinList = new JSONArray(responseBody);
				          for (int c = 0; c < coinList.length(); c++) {
				              // log.info(coinList.get(c).toString());
				              JSONObject coinjson = new JSONObject(coinList.get(c).toString());
				              CoinVo coinInfo = new CoinVo();
				              
				              coinInfo.setId(coinjson.getString("id"));
				              coinInfo.setSymbol(coinjson.getString("symbol"));
				              coinInfo.setName(coinjson.getString("name"));
				              coinInfo.setCurrency(currency[cu]);
				              coinInfo.setImage(coinjson.getString("image"));
				              coinInfo.setCurrentPrice(String.valueOf(coinjson.get("current_price")));
				              coinInfo.setMarketCap(String.valueOf(coinjson.get("market_cap")));
				              coinInfo.setMarketCapRank(coinjson.getInt("market_cap_rank"));
				              coinInfo.setFullyDilutedValuation(String.valueOf(coinjson.get("fully_diluted_valuation")));
				              coinInfo.setTotalVolume(String.valueOf(coinjson.get("total_volume")));
				              coinInfo.setHigh24h(String.valueOf(coinjson.get("high_24h")));
				              coinInfo.setLow24h(String.valueOf(coinjson.get("low_24h")));
				              coinInfo.setPriceChange24h(String.valueOf(coinjson.get("price_change_24h")));
				              coinInfo.setPriceChangePercentage24h(String.valueOf(coinjson.get("price_change_percentage_24h")));
				              coinInfo.setMarketCapChange24h(String.valueOf(coinjson.get("market_cap_change_24h")));
				              coinInfo.setMarketCapChangePercentage24h(String.valueOf(coinjson.get("market_cap_change_percentage_24h")));
				              coinInfo.setCirculatingSupply(String.valueOf(coinjson.get("circulating_supply")));
				              coinInfo.setTotalSupply(String.valueOf(coinjson.get("total_supply")));
				              coinInfo.setMaxSupply(String.valueOf(coinjson.get("max_supply")));
				              coinInfo.setAth(String.valueOf(coinjson.get("ath")));
				              coinInfo.setAthChangePercentage(String.valueOf(coinjson.get("ath_change_percentage")));
				              coinInfo.setAthDate(LocalDateTime.parse(coinjson.getString("ath_date"), DateTimeFormatter.ISO_DATE_TIME));
				              coinInfo.setAtl(String.valueOf(coinjson.get("atl")));
				              coinInfo.setAtlChangePercentage(String.valueOf(coinjson.get("atl_change_percentage")));
				              coinInfo.setAtlDate(LocalDateTime.parse(coinjson.getString("atl_date"), DateTimeFormatter.ISO_DATE_TIME));
				              coinInfo.setRoi(coinjson.isNull("roi") ? null : coinjson.get("roi").toString());
				              coinInfo.setLastUpdated(LocalDateTime.parse(coinjson.getString("last_updated"), DateTimeFormatter.ISO_DATE_TIME));
				              
				              coinService.saveCoinInfo(coinInfo);
				          }
				    }
				} catch (IOException e) {
				    log.error("Error during API call", e);
				}
		
				}
			}catch(Exception e) {
				log.info("ddd" +e.toString());
				
			}
		}
		
//		SecurityContextHolder.clearContext();
	}
}
