<?php
/**
 * Instagram 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_Instagram extends WPCP_Module {
    /**
     * The single instance of the class
     *
     * @var $this ;
     */
    protected static $_instance = null;

    /**
     * WPCP_Instagram constructor.
     */
    public function __construct() {
        //fields
        add_action( 'wpcp_instagram_campaign_options_meta_fields', 'wpcp_keyword_suggestion_field' );
        add_action( 'wpcp_instagram_campaign_options_meta_fields', 'wpcp_keyword_field' );
        parent::__construct( 'instagram' );
    }

    /**
     * @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' ),
            'content'    => __( 'Content', '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' ),
            'comments'   => __( 'Comments Count', 'wp-content-pilot-pro' ),
            'likes'      => __( 'Likes Count', 'wp-content-pilot-pro' ),
            'user_id'    => __( 'User ID', 'wp-content-pilot-pro' ),
        );
    }

    /**
     * @return string
     * @since 1.1.0
     */
    public function get_default_template() {
        $template
            = <<<EOT
<img src="{image_url}" alt=""><br>
{content}<br>
<a href="{source_url}" target="_blank">Source</a>
EOT;

        return $template;
    }

    /**
     * @param $post
     */
    public function add_campaign_option_fields( $post ) {

        echo WPCP_HTML::start_double_columns();

        echo WPCP_HTML::select_input( array(
            'label'    => __( 'Select Source Type', 'wp-content-pilot-pro' ),
            'name'     => '_instagram_src',
            'options'  => array(
                'keyword' => __( 'Keyword', 'wp-content-pilot-pro' ),
                'user'    => __( 'User', 'wp-content-pilot-pro' ),
            ),
            'required' => true,
            'tooltip'  => __( 'Select source type', 'wp-content-pilot-pro' ),
            'default'  => 'keyword',
        ) );

        echo WPCP_HTML::text_input( array(
            'name'        => '_instagram_user_id',
            'placeholder' => __( 'Example: add "cnn" for "https://instagram.com/cnn/"', 'wp-content-pilot-pro' ),
            'label'       => __( 'Instagram user ID', 'wp-content-pilot-pro' ),
            'tooltip'     => __( 'eg. Instagram user ID (appear after instagram.com at the user page link)', 'wp-content-pilot-pro' ),
        ) );


        echo WPCP_HTML::end_double_columns();
        echo WPCP_HTML::checkbox_input( array(
            'label'   => __( 'Only publish latest Post', 'wp-content-pilot-pro' ),
            'name'    => '_instagram_publish_latest_posts',
            'default' => 'no',
            'tooltip' => __( 'Enable this checkbox if you only want to just publish articles which published on current date. Other posts will not be pubslished', 'wp-content-pilot-pro' )
        ) );
    }

    /**
     * @param $campaign_id
     * @param $posted
     */
    public function save_campaign_meta( $campaign_id, $posted ) {
        update_post_meta( $campaign_id, '_instagram_src', empty( $posted['_instagram_src'] ) ? 'keyword' : sanitize_key( $posted['_instagram_src'] ) );
        update_post_meta( $campaign_id, '_instagram_user_id', empty( $posted['_instagram_user_id'] ) ? '' : sanitize_key( $posted['_instagram_user_id'] ) );
        update_post_meta( $campaign_id, '_instagram_publish_latest_posts', isset( $posted['_instagram_publish_latest_posts'] ) && ! empty( $posted['_instagram_publish_latest_posts'] ) ? $posted['_instagram_publish_latest_posts'] : 'no' );
    }

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

        return $sections;
    }

    /**
     * @param $fields
     *
     * @return array
     * @since 1.1.0
     */
    public function get_setting_fields( $fields ) {
        $fields['wpcp_settings_instagram'] = array(
            array(
                'name'              => 'sessionid',
                'label'             => __( 'Session ID', 'wp-content-pilot-pro' ),
                'desc'              => sprintf( __( 'Create your Instagram Session ID following <a href="%s" target="_blank">this guide</a>.', 'wp-content-pilot-pro' ), 'https://www.pluginever.com/docs/wp-content-pilot/instagram-campaign-settings/' ),
                'type'              => 'password',
                'sanitize_callback' => 'esc_html',
                'default'           => ''
            ),
        );

        return $fields;
    }

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

        $sessionid = wpcp_get_settings( 'sessionid', 'wpcp_settings_instagram' );
        wpcp_logger()->info( __( 'Checking instagram session id for authentication', 'wp-content-pilot-pro' ), $campaign_id );
        if ( empty( $sessionid ) ) {
            $notice = __( 'Instagram \'Session ID\' is not set, so no campaign wont work.', 'wp-content-pilot-pro' );
            wpcp_logger()->warning( $notice, $campaign_id );
            wpcp_disable_campaign( $campaign_id );

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

        $source_type = wpcp_get_post_meta( $campaign_id, '_instagram_src', 'keyword' );

        wpcp_logger()->info( __( 'Finding instagram source type', 'wp-content-pilot-pro' ), $campaign_id );

        if ( $source_type == "user" ) {
            $user_id = wpcp_get_post_meta( $campaign_id, '_instagram_user_id', '' );

            if ( empty( $user_id ) ) {
                return new WP_Error( 'missing-data', __( 'Campaign type is set from user but user id is not set', 'wp-content-pilot-pro' ) );
            }

            $numeric_user_id = wpcp_get_post_meta( $campaign_id, '_instagram_user_numeric_id_' . md5( $user_id ), '' );

            if ( empty( $numeric_user_id ) ) {
                wpcp_logger()->info( __( 'Finding instagram user id', 'wp-content-pilot-pro' ), $campaign_id );
                $numeric_user_id = $this->find_user_id( $user_id, $campaign_id );
                if ( is_wp_error( $numeric_user_id ) ) {
                    wpcp_disable_campaign( $campaign_id );

                    return $numeric_user_id;
                }
            }
            update_post_meta( $campaign_id, '_instagram_user_numeric_id_' . md5( $user_id ), $numeric_user_id );
            $sources = [ $numeric_user_id ];
        } else {
            $sources = $this->get_campaign_meta( $campaign_id );
        }

        if ( empty( $sources ) ) {
            return new WP_Error( 'missing-data', __( 'Campaign do not have anything to proceed, please set campaign correctly', 'wp-content-pilot-pro' ) );
        }

        //loop through keywords
        foreach ( $sources as $source ) {

            if ( $this->is_deactivated_key( $campaign_id, $source ) ) {
                wpcp_logger()->error( sprintf( __( 'Campaign is deactivated for 1 hr because last time could not find any article for [%s]', 'wp-content-pilot-pro' ), $source ), $campaign_id );
                continue;
            }

            $page_key    = sanitize_key( '_page_' . $campaign_id . '_' . md5( $source ) );
            $page_number = wpcp_get_post_meta( $campaign_id, $page_key, '' );
            $api_url     = "https://www.instagram.com/graphql/query/";
            $keyword     = str_replace( ' ', '', $source );
            $keyword     = str_replace( '#', '', $source );
            $query_args  = array(
                'query_id' => $source_type === 'user' ? '17880160963012870' : '17882293912014529',
                'tag_name' => strtolower( $keyword ),
                'first'    => '1',
            );

            if ( $source_type === 'user' ) {
                unset( $query_args['tag_name'] );
                $query_args['id'] = $source;
            }

            if ( $page_number !== '' ) {
                $query_args['after'] = urlencode( trim( $page_number ) );
            }
            $endpoint = add_query_arg( $query_args, $api_url );

            $curl = $this->setup_curl();
            $curl->setOpt( CURLOPT_COOKIE, 'sessionid=' . $sessionid . '; csrftoken=eqYUPd3nV0gDSWw43IYZjydziMndrn4l;' );
            $curl->setOpt( CURLOPT_MAXREDIRS, 3 );
            wpcp_logger()->info( sprintf( 'Grabbing links from instagram url [%s]', $endpoint ), $campaign_id );
            $curl->get( $endpoint );

            if ( $curl->isError() ) {
                wpcp_logger()->error( $curl->errorMessage, $campaign_id );
                $this->deactivate_key( $campaign_id, $keyword );
                continue;
            }

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

            $end_cursor = $this->get_end_cursor( $response, $source_type );
            $items      = [];
            if ( $source_type === 'user' && isset( $response->data->user->edge_owner_to_timeline_media->edges ) && is_array( $response->data->user->edge_owner_to_timeline_media->edges ) && count( $response->data->user->edge_owner_to_timeline_media->edges ) ) {
                $items = $response->data->user->edge_owner_to_timeline_media->edges;
            } else if ( isset( $response->data->hashtag->edge_hashtag_to_media->edges ) && is_array( $response->data->hashtag->edge_hashtag_to_media->edges ) && count( $response->data->hashtag->edge_hashtag_to_media->edges ) ) {
                $items = $response->data->hashtag->edge_hashtag_to_media->edges;
            } else {
                $items = $response->data->hashtag->edge_hashtag_to_top_posts->edges;
            }

            $item = false;
            if ( ! empty( $items ) ) {
                $item = reset( $items );
                $item = isset( $item->node ) ? $item->node : false;
            }

            if ( ! $item ) {
                wpcp_logger()->error( __( 'Failed retrieving item from instagram response ', 'wp-content-pilot-pro' ), $campaign_id );
                if ( ! $end_cursor ) {
                    wpcp_logger()->error( __( 'No more items from instagram. Now deactivating for 10 hours', 'wp-content-pilot-pro' ), $campaign_id );
                    $this->deactivate_key( $campaign_id, $keyword, 10 );
                }
                continue;
            }

            wpcp_logger()->info( __( 'Valid response returned from instagram. Now extracting content.', 'wp-content-pilot-pro' ), $campaign_id );
            $id = $item->shortcode;

            $content = $item->edge_media_to_caption->edges[0]->node->text;

            $title = wpcp_generate_title_from_content( $content );


            $comments = $item->edge_media_to_comment->count;

            $likes = $item->edge_liked_by->count;

            $image = $item->display_url;

            $url                  = 'http://instagram.com/p/' . $item->shortcode;
            $publish_latest_posts = wpcp_get_post_meta( $campaign_id, '_instagram_publish_latest_posts', 'no' );

            $user_id              = $item->owner->id;
            $created_at_timestamp = @$item->taken_at_timestamp;
            $created_date         = date( 'Y-m-d H:i:s', (int) $created_at_timestamp );

            if ( $publish_latest_posts == 'on' ) {
                wpcp_logger()->info( __( 'Checking if the post is posted in current date', 'wp-content-pilot-pro' ), $campaign_id );
                $current_date = date( 'Y-m-d H:i:s' );
                if ( $created_date < $current_date ) {
                    wpcp_logger()->error( __( 'No such post on current date', 'wp-content-pilot-pro' ), $campaign_id );

                    return new WP_Error( 'no-data', __( 'No Such post on current date', 'wp-content-pilot-pro' ), $campaign_id );
                }
            }


            //check duplicate title and don't publish the post with duplicate title
            $skip = apply_filters( 'wpcp_skip_duplicate_title', true, $title, $campaign_id );
            if ( $skip ) {
                wpcp_update_post_meta( $campaign_id, $page_key, $end_cursor );
                continue;
            }

            if ( wpcp_is_duplicate_url( $url ) ) {
                wpcp_logger()->info( __( 'Checking duplicate url and skipping it', 'wp-content-pilot-pro' ), $campaign_id );
                wpcp_update_post_meta( $campaign_id, $page_key, $end_cursor );
                continue;
            }

            //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( $title );
            } else {
                $title = html_entity_decode( $title, ENT_QUOTES );
            }

            wpcp_logger()->info( __( 'Combining all parts for article', 'wp-content-pilot-pro' ), $campaign_id );
            $article = array(
                'id'         => $id,
                'title'      => $title,
                'content'    => $content,
                'image_url'  => $image,
                'source_url' => $url,
                'date'       => $created_date,
                'comments'   => $comments,
                'likes'      => $likes,
                'user_id'    => $user_id
            );

            wpcp_logger()->info( __( 'Inserting links in store...', 'wp-content-pilot-pro' ), $campaign_id );
            $this->insert_link( array(
                'status'  => 'success',
                'url'     => $url,
                'title'   => $title,
                'for'     => $keyword,
                'camp_id' => $campaign_id,
            ) );
            wpcp_update_post_meta( $campaign_id, $page_key, $end_cursor );


            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' ) );
    }

    /**
     * @param $response
     * @param $type
     *
     * @return bool|string
     * @since 1.0.0
     */
    protected function get_end_cursor( $response, $type ) {
        if ( $type === 'user' ) {
            return $response->data->user->edge_owner_to_timeline_media->page_info->end_cursor;
        } else if ( isset( $response->data->hashtag->edge_hashtag_to_media->page_info->end_cursor ) ) {
            return $response->data->hashtag->edge_hashtag_to_media->page_info->end_cursor;
        } else {
            return $response->data->hashtag->edge_hashtag_to_top_posts->page_info->end_cursor;
        }

        return false;
    }

    /**
     * @param $user_name
     * @param $campaign_id
     *
     * @return mixed|WP_Error
     * @throws ErrorException
     * @since 1.1.0
     */
    protected function find_user_id( $user_name, $campaign_id ) {
        $sessionid = wpcp_get_settings( 'sessionid', 'wpcp_settings_instagram' );
        $curl      = $this->setup_curl();
        $curl->setCookie( 'sessionid', $sessionid );
        $curl->setCookie( 'csrftoken', 'eqYUPd3nV0gDSWw43IYZjydziMndrn4l' );
        $curl->get( 'https://www.instagram.com/' . trim( $user_name ) );
        $response = $curl->getResponse();

        if ( $curl->isError() ) {
            $message = __( 'Could not reach Instagram', 'wp-content-pilot-pro' );
            wpcp_logger()->warning( $message, $campaign_id );

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

        preg_match( '{profilePage_(.*?)"}', $response, $matches );
        if ( empty( $matches[1] ) ) {
            $message = __( 'Could not find user id, disabling campaign', 'wp-content-pilot-pro' );
            wpcp_logger()->warning( $message, $campaign_id );

            return new WP_Error( 'missing-data', $message );
        }
        wpcp_logger()->info( __( 'Valid user id returned from instagram', 'wp-content-pilot-pro' ), $campaign_id );

        return $matches[1];
    }


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

        return self::$_instance;
    }

}

WPCP_Instagram::instance();
