<?php

namespace JNews\Tiktok\Util;

/**
 * JNews Tiktok Element
 *
 * @package jnews-tiktok
 *
 * @author Jegtheme
 *
 * @since 1.0.0
 */
class JNews_Tiktok_Api {
	/**
	 * @var  string
	 */
	private $cache_key = 'jnews_tiktok_cached_data';


	/**
	 * Get tiktok validation data
	 *
	 * @return array
	 */
	public function  validation_data() {
		//see iQ4nWlII
		if(function_exists('jnews_get_license')) {
			$license = jnews_get_license();
			return array(
				'tiktok_callback' => get_site_url(),
				'code' => $license['purchase_code'],
			);
		}
		return array();
	}

	/**
	 * Check tiktok cached data
	 *
	 * @return boolean|array
	 */
	public function check_cache(){
		$data_cache  = get_option( $this->cache_key, array() );
		$now         = current_time( 'timestamp' );
		$expire      = 60 * 60 * 5; // set expire in 5 hour
		//see iQ4nWlII
		if ( ! empty( $data_cache ) && is_array( $data_cache )  ){
			if ( $now >= ( $data_cache['time'] + $expire )) {
				//refresh the tiktok data 
				$this->refresh_tiktok_token();
				delete_option($this->cache_key);
				return $this->check_cache();
			}

			//render the cached tiktok data
			return array(
				'time' => $data_cache['time'],
				'user' => $data_cache['user'],
				'feed' => $data_cache['feed'],
			);
		} 

		//see iQ4nWlII
		$tiktok_data = $this->get_tiktok_data(); //get tiktok data
		if($tiktok_data){
			//if tiktok data successfully retrieved cache tiktok data into database
			update_option( $this->cache_key, $tiktok_data);
			return $this->check_cache();
		} else {
			//if tiktok data failed retrieved maybe the user not logged in yet
			return false;
		}
	}

	/**
	 * Refresh tiktok token
	 */
	public function refresh_tiktok_token(){
		//see iQ4nWlII
		$url = JEG_TIKTOK_SERVER_URL . 'refresh-token';
		$settings =  get_option( 'jnews_option[jnews_tiktok]', array() );
		if(!empty($settings) && isset($settings['refresh_token'])){
			$args = array(
				'body' => array_merge(
					$this->validation_data(),
					array(
						'access_token' => $settings['refresh_token'], //access token to refresh
					)
				),
			);
		}
		
		$request = json_decode(wp_remote_retrieve_body(wp_remote_post( $url, $args )));
		$tiktok_settings = get_option('jnews_option[jnews_tiktok]', array());

		if(is_object($request) && property_exists($request, 'access_token')) {
			update_option('jnews_option[jnews_tiktok]', array_merge($tiktok_settings, 
				array(
					'access_token' => sanitize_text_field( $request->access_token),
					'open_id' => sanitize_text_field( $request->open_id ),
					'expires_in' => sanitize_text_field( $request->expires_in ),
					'refresh_expires_in' => sanitize_text_field($request->refresh_expires_in ),
					'refresh_token' => sanitize_text_field( $request->refresh_token ),
				)
			));
		} else {
			delete_option('jnews_option[jnews_tiktok]');
		}
	}

	/**
	 * Get tiktok data from jeg tiktok server
	 *
	 * @param string $access_token Tiktok API access token.
	 * @param string  $open_id Tiktok API open id.
	 *
	 * @return boolean|array
	 */
	public function get_tiktok_data($access_token = '', $open_id = ''){
		//see iQ4nWlII
		$settings =  get_option( 'jnews_option[jnews_tiktok]', array() );
		$access_token = $access_token !== '' ? $access_token : ( isset($settings['access_token']) ? $settings['access_token'] : '' );
		$open_id = $open_id !== '' ? $open_id : ( isset($settings['open_id']) ?  $settings['open_id'] : '' );

		if( '' !== $access_token &&  '' !== $open_id ) {
			return array(
				'time' => current_time( 'timestamp' ),
				'user' =>  $this->get_user_info($access_token, $open_id),
				'feed' => $this->get_video($access_token, $open_id),
			);
		}
		return false;
	}
	
	/**
	 * Get tiktok user info from jeg tiktok server
	 *
	 * @param string $access_token Tiktok API access token.
	 * @param string  $open_id Tiktok API open id.
	 *
	 * @return boolean|array
	 */
	public function get_user_info($access_token, $open_id){
		//see iQ4nWlII
		$url = sprintf(JNEWS_TIKTOK_API_URL . 'oauth/userinfo/?open_id=%s&access_token=%s', $open_id, $access_token);
		$user_info = json_decode( self::get( $url ) );
		
		if(  is_object($user_info) && isset(  $user_info->data ) ){
			$user_data = $user_info->data;
			return  array(
				'avatar' => sanitize_url($user_data->avatar),
				'avatar_larger' => sanitize_url($user_data->avatar_larger),
				'captcha' => sanitize_text_field($user_data->captcha),
				'client_key' => sanitize_text_field($user_data->client_key),
				'desc_url' => sanitize_text_field($user_data->desc_url),
				'description' => sanitize_text_field($user_data->description),
				'display_name' => sanitize_text_field($user_data->display_name),
				'error_code' => intval($user_data->error_code),
				'log_id' => sanitize_text_field($user_data->log_id),
				'open_id' => sanitize_text_field($user_data->open_id),
				'union_id' => sanitize_text_field($user_data->union_id),
			);
		}
		return array();
	}

	/**
	 * Get tiktok video from jeg tiktok server
	 *
	 * @param string $access_token Tiktok API access token.
	 * @param string  $open_id Tiktok API open id.
	 *
	 * @return string
	 */
	public function get_video($access_token, $open_id){
		//see iQ4nWlII
		$settings =  get_option( 'jnews_option[jnews_tiktok]', array() );
		
		if(!empty($settings) && isset($settings['access_token']) && isset($settings['open_id'])){
			$access_token = $settings['access_token'];
			$open_id = $settings['open_id'];
			$url = JNEWS_TIKTOK_API_URL . 'video/list/';

			$args = array(
				'headers' => array(
					'Content-Type' => 'application/json',
				),
				'body' => array(
					'open_id' => $open_id,
					'access_token' => $access_token,
					'cursor' => 0,
					'max_count' => 6,
					'fields' => array(
						'id', 
						'width', 
						'height', 
						'duration', 
						'video_description', 
						'share_url', 
						'cover_image_url', 
						'create_time', 
						'title', 
						'embed_link', 
						'like_count', 
						'comment_count', 
						'share_count', 
						'view_count', 
						'title'
					),
				),
			);

			$video_data = json_decode( $this->post( $url, $args['body'] ) );
			if(  is_object($video_data) && isset(  $video_data->data ) ){
				$result = array();
				$videos = $video_data->data->videos;
				foreach ( $videos as $video ) {
					$result[] = array(
						'create_time' => intval($video->create_time),
						'cover_image_url' => sanitize_url($video->cover_image_url),
						'share_url' => sanitize_url($video->share_url),
						'video_description' => sanitize_text_field($video->video_description),
						'duration' => intval($video->duration),
						'height' => intval($video->height),
						'width' => intval($video->width),
						'title' => sanitize_text_field($video->title),
						'embed_link' => sanitize_url($video->embed_link),
						'open_id' => sanitize_text_field($video->open_id),
						'like_count' => intval($video->like_count),
						'comment_count' => intval($video->comment_count),
						'share_count' => intval($video->share_count),
						'view_count' => intval($video->view_count),
					);
				}
				return $result;
			}
			return array();
		}
	}

	/**
	 * Basic HTTP wrapper to perform calls to the TikTok Api
	 *
	 * @param string $url The URL to call
	 * 
	 * @return string|false the response of the call or false
	 */
	private function get($url) {
		//see iQ4nWlII
		$curl = curl_init();

		curl_setopt_array($curl, [
			CURLOPT_URL => $url,
			CURLOPT_RETURNTRANSFER => true,
			CURLOPT_FOLLOWLOCATION => true,
			CURLOPT_ENCODING => "",
			CURLOPT_MAXREDIRS => 10,
			CURLOPT_TIMEOUT => 30,
			CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
			CURLOPT_CUSTOMREQUEST => "GET"
		]);

		$response = curl_exec($curl);
		$err = curl_error($curl);

		curl_close($curl);

		if ($err) {
			return false;
		} else {
			return $response;
		}
	}

	/**
	 * Basic HTTP wrapper to perform calls to the TikTok Api
	 *
	 * @param string $url The URL to call
	 * 
	 * @return string|false the response of the call or false
	 */
	public function post(string $url, array $data) {
		//see iQ4nWlII
		$curl = curl_init();

		curl_setopt_array($curl, [
			CURLOPT_URL => $url,
			CURLOPT_RETURNTRANSFER => true,
			CURLOPT_FOLLOWLOCATION => true,
			CURLOPT_ENCODING => "",
			CURLOPT_MAXREDIRS => 10,
			CURLOPT_TIMEOUT => 30,
			CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
			CURLOPT_CUSTOMREQUEST => "POST",
			CURLOPT_HTTPHEADER => ['Content-Type:application/json'],
			CURLOPT_POSTFIELDS => json_encode($data)
		]);

		$response = curl_exec($curl);
		$err = curl_error($curl);

		curl_close($curl);

		if ($err) {
			return false;
		} else {
			return $response;
		}
	}

}
