<?php
/**
 * Bestbuy Class
 *
 * @package     WP Content Pilot Pro
 * @subpackage  Feed
 * @copyright   Copyright (c) 2019, MD Sultan Nasir Uddin(manikdrmc@gmail.com)
 * @license     http://opensource.org/licenses/gpl-2.0.php GNU Public License
 * @since       1.1.0
 */
defined( 'ABSPATH' ) || exit();

class WPCP_Bestbuy extends WPCP_Module {
	/**
	 * The single instance of the class
	 *
	 * @var $this ;
	 */
	protected static $_instance = null;

	/**
	 * WPCP_Bestbuy constructor.
	 */
	public function __construct() {
		//option fields
		add_action( 'wpcp_bestbuy_campaign_options_meta_fields', 'wpcp_keyword_suggestion_field' );
		add_action( 'wpcp_bestbuy_campaign_options_meta_fields', 'wpcp_keyword_field' );
		parent::__construct( 'bestbuy' );
	}


	/**
	 * @return string
	 */
	public function get_module_icon() {
		return '';
	}

	/**
	 * @return array
	 * @since 1.1.0
	 */
	public function get_template_tags() {
		return array(
			'title'                     => __( 'Title', 'wp-content-pilot-pro' ),
			'excerpt'                   => __( 'Short Description', 'wp-content-pilot-pro' ),
			'content'                   => __( 'Long Description', 'wp-content-pilot-pro' ),
			'image_url'                 => __( 'Main image url', 'wp-content-pilot-pro' ),
			'source_url'                => __( 'Source link', 'wp-content-pilot-pro' ),
			'date'                      => __( 'Published date', 'wp-content-pilot-pro' ),
			'regular_price'             => __( 'Regular Price', 'wp-content-pilot-pro' ),
			'sale_price'                => __( 'Sale Price', 'wp-content-pilot-pro' ),
			'affiliate_url'             => __( 'Affiliate URL', 'wp-content-pilot-pro' ),
			'add_to_cart_url'           => __( 'Add to cart url', 'wp-content-pilot-pro' ),
			'affiliate_add_to_cart_url' => __( 'Affiliate add to cart url', 'wp-content-pilot-pro' ),
			'review_count'              => __( 'Review count', 'wp-content-pilot-pro' ),
			'review_average'            => __( 'Review Average', 'wp-content-pilot-pro' ),
			'manufacturer'              => __( 'Manufacturer', 'wp-content-pilot-pro' ),
			'model_number'              => __( 'Model number', 'wp-content-pilot-pro' ),
			'features'                  => __( 'Features List', 'wp-content-pilot-pro' ),
			'details'                   => __( 'Details List', 'wp-content-pilot-pro' ),
		);
	}

	/**
	 * @return string
	 * @since 1.1.0
	 */
	public function get_default_template() {
		$template
			= <<<EOT
<img src="{image_url}"><br>
<a href="{affiliate_add_to_cart_url}">Add to cart</a><br>
<strong>Regular Price:</strong> {regular_price} <br>
<strong>Sale Price:</strong> {sale_price} <br>
<strong>Manufacturer:</strong> {manufacturer} <br>
<strong>Model number:</strong> {model_number} <br>
{content}<br>
<h3>Features</h3>
{features}<br>
<h3>Details</h3>
{details}<br>
<a href="{source_url}">Source</a>
EOT;

		return $template;
	}

	/**
	 * @param $post
	 */
	public function add_campaign_option_fields( $post ) {
		echo WPCP_HTML::select_input( array(
			'label'   => __( 'BestBuy Category', 'wp-content-pilot-pro' ),
			'name'    => '_category',
			'class'   => 'wpcp-select2',
			'options' => array(
				''                   => 'Select Category',
				'pcmcat209400050001' => 'All Cell Phones with Plans',
				'abcat0501000'       => 'Desktop &amp; All-in-One Computers',
				'abcat0401000'       => 'Digital Cameras',
				'pcmcat242800050021' => 'Health, Fitness &amp; Beauty',
				'abcat0204000'       => 'Headphones',
				'pcmcat241600050001' => 'Home Audio',
				'pcmcat254000050002' => 'Home Automation &amp; Security',
				'pcmcat209000050006' => 'iPad, Tablets &amp; E-Readers',
				'abcat0502000'       => 'Laptops',
				'pcmcat232900050000' => 'Nintendo 3DS',
				'pcmcat295700050012' => 'PlayStation 4',
				'pcmcat310200050004' => 'Portable &amp; Wireless Speakers',
				'pcmcat243400050029' => 'PS Vita',
				'abcat0904000'       => 'Ranges, Cooktops &amp; Ovens',
				'abcat0901000'       => 'Refrigerators',
				'abcat0912000'       => 'Small Kitchen Appliances',
				'abcat0101000'       => 'TVs',
				'abcat0910000'       => 'Washers &amp; Dryers',
				'pcmcat273800050036' => 'Wii U',
				'pcmcat300300050002' => 'Xbox One',
			),
			'tooltip' => __( 'Select BestBuy Category', 'wp-content-pilot-pro' ),
		) );
	}

	/**
	 * @param $campaign_id
	 * @param $posted
	 */
	public function save_campaign_meta( $campaign_id, $posted ) {
		update_post_meta( $campaign_id, '_category', empty( $posted['_category'] ) ? '' : sanitize_key( $posted['_category'] ) );
	}

	/**
	 * @param $section
	 *
	 * @return array
	 * @since 1.1.0
	 */
	public function get_setting_section( $sections ) {
		$sections[] = [
			'id'    => 'wpcp_settings_bestbuy',
			'title' => __( 'BestBuy Settings', 'wp-content-pilot-pro' )
		];

		return $sections;
	}

	/**
	 * @param $fields
	 *
	 * @return array
	 * @since 1.1.0
	 */
	public function get_setting_fields( $fields ) {
		$fields['wpcp_settings_bestbuy'] = array(
			array(
				'name'  => 'bestbuy_api',
				'label' => __( 'API Key', 'wp-content-pilot-pro' ),
				'type'  => 'password',
				'desc'  => sprintf( __( '<a href="%s" target="_blank">Here</a> is the guide to get your BestBuy API key.', 'wp-content-pilot-pro' ), 'https://www.pluginever.com/docs/wp-content-pilot/bestbuy-settings/' )
			),

			array(
				'name'  => 'bestbuy_lid',
				'label' => __( 'LinkShare Affiliate Tracking Code', 'wp-content-pilot-pro' ),
				'type'  => 'password',
				'desc'  => sprintf( __( 'Create your LinkShare Affiliate Tracking code following <a href="%s" target="_blank">this guide</a>.', 'wp-content-pilot-pro' ), 'https://www.pluginever.com/docs/wp-content-pilot/bestbuy-settings/' ),
			),
		);

		return $fields;
	}

	/**
	 *
	 * @param $campaign_id
	 *
	 * @return mixed|void
	 * @throws ErrorException
	 */
	public function get_post( $campaign_id ) {
		wpcp_logger()->info( __( 'Loaded Bestbuy Campaign', 'wp-content-pilot-pro' ), $campaign_id );

		$api_key = wpcp_get_settings( 'bestbuy_api', 'wpcp_settings_bestbuy' );
		$lid     = wpcp_get_settings( 'bestbuy_lid', 'wpcp_settings_bestbuy' );

		wpcp_logger()->info( __( 'Checking bestbuy api key for authentication', 'wp-content-pilot-pro' ), $campaign_id );
		if ( empty( $api_key ) ) {
			wpcp_disable_campaign( $campaign_id );

			$notice = __( 'BestBuy api key is not set.So, the campaign wont run, disabling campaign.', 'wp-content-pilot-pro' );
			wpcp_logger()->error( $notice, $campaign_id );

			return new WP_Error( 'missing-data', $notice );
		}

		$keywords = $this->get_campaign_meta( $campaign_id );
		if ( empty( $keywords ) ) {
			return new WP_Error( 'missing-data', __( 'Campaign do not have keyword to proceed, please set keyword', 'wp-content-pilot-pro' ) );
		}

		foreach ( $keywords as $keyword ) {

			wpcp_logger()->info( sprintf( __( 'Looping through keywords [ %s ]', 'wp-content-pilot-pro' ), $keyword ), $campaign_id );

			//get links from database

			wpcp_logger()->info( __( 'Checking if any cached links in store..', 'wp-content-pilot-pro' ), $campaign_id );
			$links = $this->get_links( $keyword, $campaign_id );
			if ( empty( $links ) ) {
				wpcp_logger()->info( __( 'No cached links in store. Generating new links..', 'wp-content-pilot-pro' ), $campaign_id );
				$this->discover_links( $campaign_id, $keyword );
				$links = $this->get_links( $keyword, $campaign_id );
			}

			wpcp_logger()->info( __( 'Looping through links for publishing article', 'wp-content-pilot-pro' ), $campaign_id );

			foreach ( $links as $key => $link ) {
				$this->update_link( $link->id, [ 'status' => 'failed', 'meta' => '' ] );

				$sku      = preg_replace( '/[^0-9]/', '', $link->url );
				$endpoint = 'https://api.bestbuy.com/v1/products(sku in (' . $sku . '))?apiKey=' . $api_key . '&LID=' . $lid . '&sort=bestSellingRank.asc&show=accessories.sku,bestSellingRank,categoryPath.name,condition,description,addToCartUrl,color,customerReviewCount,categoryPath.id,details.name,details.value,customerReviewAverage,features.feature,frequentlyPurchasedWith.sku,image,freeShipping,inStoreAvailability,inStoreAvailabilityText,dollarSavings,longDescription,manufacturer,modelNumber,name,percentSavings,url,type,thumbnailImage,sku,shortDescription,salePrice,upc,includedItemList.includedItem,mobileUrl,onlineAvailability,onlineAvailabilityText,onSale,preowned,regularPrice,relatedProducts.sku,shipping,shippingCost&facet=color&format=json';
				wpcp_logger()->info( sprintf( 'Processing link#[%s]', preg_replace( '/apiKey=([^&]+)/m', 'apiKey=X', $endpoint ) ), $campaign_id );

				$curl = $this->setup_curl();
				$curl->get( $endpoint );

				if ( $curl->isError() ) {
					wpcp_logger()->error( sprintf( "Failed processing link reason [%s]", $curl->response->errorMessage ) );
					continue;
				}

				wpcp_logger()->info( __( 'Getting response for publishing article', 'wp-content-pilot-pro' ), $campaign_id );
				$response = $curl->getResponse();

				$product = array_pop( $response->products );


				$features = [];
				if ( isset( $product->features ) ) {
					wpcp_logger()->info( __( 'Extracting product features', 'wp-content-pilot-pro' ), $campaign_id );
					$features = wp_list_pluck( $product->features, 'feature' );
				}

				$details = [];
				if ( isset( $product->details ) ) {
					wpcp_logger()->info( __( 'Extracting product details', 'wp-content-pilot-pro' ), $campaign_id );
					$details = wp_list_pluck( $product->details, 'value', 'name' );
				}

				//check clean title and perform title cleaning when checked
				$check_clean_title = wpcp_get_post_meta( $campaign_id, '_clean_title', 'off' );

				if ( 'on' == $check_clean_title ) {
					wpcp_logger()->info( __( 'Cleaning title', 'wp-content-pilot-pro' ), $campaign_id );
					$title = wpcp_clean_title( $product->name );
				} else {
					$title = html_entity_decode( $product->name, ENT_QUOTES );
				}

				wpcp_logger()->info( __( 'Combining all parts for article', 'wp-content-pilot-pro' ), $campaign_id );
				$article = array(
					'title'                     => $title,
					'sku'                       => $product->sku,
					'regular_price'             => wpcp_price( $product->regularPrice ),
					'sale_price'                => wpcp_price( $product->salePrice ),
					'affiliate_url'             => isset( $product->affiliateUrl ) ? $product->affiliateUrl : '',
					'add_to_cart_url'           => $product->addToCartUrl,
					'affiliate_add_to_cart_url' => isset( $product->affiliateAddToCartUrl ) ? $product->affiliateAddToCartUrl : '',
					'review_count'              => $product->customerReviewCount,
					'review_average'            => $product->customerReviewAverage,
					'content'                   => $product->longDescription,
					'excerpt'                   => $product->shortDescription,
					'manufacturer'              => $product->manufacturer,
					'model_number'              => $product->modelNumber,
					'image_url'                 => $product->image,
					'source_url'                => $product->url,
					'features'                  => wpcp_array_to_html( $features ),
					'details'                   => wpcp_array_to_html( $details ),
				);

				$this->update_link( $link->id, [ 'status' => 'success' ] );

				return $article;
			}
		}

		$log_url = admin_url( '/edit.php?post_type=wp_content_pilot&page=wpcp-logs' );

		return new WP_Error( 'campaign-error', __( sprintf( 'No article generated check <a href="%s">log</a> for details.', $log_url ), 'wp-content-pilot-pro' ) );
	}

	/**
	 * Discover new links
	 *
	 * @param $campaign_id
	 * @param $keyword
	 *
	 * @return bool
	 * @throws ErrorException
	 * @since 1.2.0
	 */
	protected function discover_links( $campaign_id, $keyword ) {
		$page_key    = sanitize_key( '_page_' . $campaign_id . '_' . md5( $keyword ) );
		$page_number = wpcp_get_post_meta( $campaign_id, $page_key, '1' );
		$category    = wpcp_get_post_meta( $campaign_id, '_category' );
		$api_key     = wpcp_get_settings( 'bestbuy_api', 'wpcp_settings_bestbuy' );
		$lid         = wpcp_get_settings( 'bestbuy_lid', 'wpcp_settings_bestbuy' );

		/* set keyword and category to the url */
		$api_url = sprintf( "https://api.bestbuy.com/v1/products((search=$keyword)%s)", ! empty( $category ) ? '&(categoryPath.id=' . $category . ')' : '' );
		/* Query args */
		$query_args = array(
			'apiKey'   => $api_key,
			'LID'      => $lid,
			'pageSize' => '10',
			'page'     => $page_number,
			'format'   => 'json'
		);

		$endpoint = add_query_arg( $query_args, $api_url );
		wpcp_logger()->info( sprintf( __( 'Requesting urls from bestbuy [%s]', 'wp-content-pilot-pro' ), preg_replace( '/apiKey=([^&]+)/m', 'apiKey=X', $endpoint ) ), $campaign_id );
		$curl = $this->setup_curl();

		$curl->get( $endpoint );
		if ( $curl->isError() ) {
			$message = sprintf( __( 'bestbuy api request failed response [%s]', 'wp-content-pilot-pro' ), $curl->response->errorMessage );
			wpcp_logger()->error( $message );

			return false;
		}

		wpcp_logger()->info( __( 'Getting response from request', 'wp-content-pilot-pro' ), $campaign_id );
		$response = $curl->getResponse();

		$products = $response->products;
		$links    = [];
		wpcp_logger()->info( __( 'Looping through links for storing...', 'wp-content-pilot-pro' ), $campaign_id );
		foreach ( $products as $item ) {

			if ( wpcp_is_duplicate_url( $item->url ) ) {
				continue;
			}
			//check duplicate title and don't publish the post with duplicate title
			$skip = apply_filters( 'wpcp_skip_duplicate_title', false, $item->name, $campaign_id );
			if ( $skip ) {
				continue;
			}

			$links[] = array(
				'url'     => esc_url( $item->url ),
				'title'   => $item->name,
				'for'     => $keyword,
				'camp_id' => $campaign_id,
			);
		}

		wpcp_logger()->info( __( 'Inserting links into store..', 'wp-content-pilot-pro' ), $campaign_id );
		$total_inserted = $this->inset_links( $links );

		wpcp_update_post_meta( $campaign_id, $page_key, $page_number + 1 );
		wpcp_logger()->info( sprintf( __( 'Total found links [%d] and accepted [%d] and rejected [%d]', 'wp-content-pilot-pro' ), count( $links ), $total_inserted, ( count( $links ) - $total_inserted ) ), $campaign_id );

		return true;
	}

	/**
	 * Main WPCP_Bestbuy Instance.
	 *
	 * Ensures only one instance of WPCP_Bestbuy is loaded or can be loaded.
	 *
	 * @return WPCP_Bestbuy Main instance
	 * @since 1.1.0
	 * @static
	 */
	public static function instance() {
		if ( is_null( self::$_instance ) ) {
			self::$_instance = new self();
		}

		return self::$_instance;
	}

}

WPCP_Bestbuy::instance();
