<?php
declare( strict_types=1 );


namespace Inavii\Instagram\Includes\Legacy\PostTypes\Media;

use Inavii\Instagram\Includes\Legacy\Utils\FeedAdvancedFilters;
use Inavii\Instagram\Includes\Legacy\Utils\FeedOrder;
use Inavii\Instagram\Includes\Legacy\Wp\Query;
use Inavii\Instagram\Wp\PostType;
use Inavii\Instagram\Wp\QueryResult;
use WP_Post;

class MediaPostType extends PostType {

	const MEDIA_ID           = '_inavii_media_id';
	const MEDIA_TYPE         = '_inavii_media_type';
	const MEDIA_URL          = '_inavii_media_url';
	const URL                = '_inavii_url';
	const PERMALINK          = '_inavii_permalink';
	const USERNAME           = '_inavii_username';
	const VIDEO_URL          = '_inavii_video_url';
	const DATE               = '_inavii_date';
	const COMMENTS_COUNT     = '_inavii_comments_count';
	const LIKES_COUNT        = '_inavii_likes_count';
	const CAPTION            = '_inavii_caption';
	const CHILDREN           = '_inavii_children';
	const MEDIA_PRODUCT_TYPE = '_inavii_media_product_type';
	const LAST_REQUESTED     = '_inavii_last_requested';
	const SOURCE             = '_inavii_source';

	public function slug(): string {
		return 'inavii_ig_media';
	}

	public function get( int $postID ) {
		// TODO: Implement get() method.
	}

	public function insert( string $title, array $data ) {
		return ( new Query( $this->slug() ) )->withPostTitle( $title )
			->withMetaInput( self::MEDIA_ID, $data['id'] )
			->withMetaInput( self::MEDIA_TYPE, $data['mediaType'] )
			->withMetaInput( self::MEDIA_URL, $data['mediaUrl'] )
			->withMetaInput( self::URL, $data['url'] ?? '' )
			->withMetaInput( self::PERMALINK, $data['permalink'] )
			->withMetaInput( self::USERNAME, $data['username'] )
			->withMetaInput( self::VIDEO_URL, $data['videoUrl'] )
			->withMetaInput( self::DATE, $data['date'] )
			->withMetaInput( self::COMMENTS_COUNT, $data['commentsCount'] )
			->withMetaInput( self::LIKES_COUNT, $data['likeCount'] )
			->withMetaInput( self::CAPTION, wp_encode_emoji( $data['caption'] ?? '' ) )
			->withMetaInput( self::CHILDREN, $data['children'] )
			->withMetaInput( self::MEDIA_PRODUCT_TYPE, $data['media_product_type'] ?? '' )
			->withMetaInput( self::LAST_REQUESTED, gmdate( 'c' ) )
			->withMetaInput( self::SOURCE, $data['source'] )
			->saveMedia( self::SOURCE );
	}

	public function getMostRecentPostDate( $source ) {
		$order = FeedOrder::create( 'lastRequested' );

		$query = ( new Query( $this->slug() ) )->withMetaQuery( self::SOURCE, $source )
			->numberOfPosts( 1 )
			->orderByMetaValue( $order->key, $order->valueType, $order->order, $order->isRandom )
			->posts();

		if ( ! $query->getPosts() ) {
			return null;
		}

		return $query->getPosts()[0]->{self::LAST_REQUESTED};
	}

	public function getMediaBySource( $source ): QueryResult {
		$order = FeedOrder::create( 'mostRecentFirst' );

		$query = ( new Query( $this->slug() ) )->withMetaQuery( self::SOURCE, $source )
			->numberOfPosts()
			->orderByMetaValue( $order->key, $order->valueType, $order->order, $order->isRandom )
			->posts();

		return $this->processQuery( $query );
	}

	public function getMedia( $source, array $settings, int $postsCount = 30, $offset = 0 ): QueryResult {
		$order = FeedOrder::create( $settings['postOrder'] ?? 'mostRecentFirst' );

		$query = ( new Query( $this->slug() ) )->withMetaQuery( self::SOURCE, $source )
			->withMetaQueryRelation( self::MEDIA_TYPE, $settings['typesOfPosts'] ?? [] )
			->withMetaQueryRelation( self::CAPTION, $settings['hashTagFilter']['include'] ?? [], 'LIKE' )
			->withMetaQueryRelation( self::CAPTION, $settings['hashTagFilter']['exclude'] ?? [], 'NOT LIKE', 'AND' )
			->withMetaQueryRelation( self::CAPTION, $settings['captionFilter']['include'] ?? [], 'LIKE' )
			->withMetaQueryRelation( self::CAPTION, $settings['captionFilter']['exclude'] ?? [], 'NOT LIKE', 'AND' )
			->orderByMetaValue( $order->key, $order->valueType, $order->order, $order->isRandom )
			->withSpecificPosts( FeedAdvancedFilters::customOrderPostIds( $settings ) )
			->withSpecificPosts( FeedAdvancedFilters::moderateWhiteList( $settings ) )
			->withExcludePosts( FeedAdvancedFilters::moderateBlackList( $settings ) )
			->numberOfPosts( $postsCount )
			->withOffset( $offset )
			->posts();

		return $this->processQuery( $query );
	}

	public function getMediaForApi( $source, array $settings, int $postsCount = -1 ): QueryResult {
		$order = FeedOrder::create( $settings['postOrder'] );

		$query = ( new Query( $this->slug() ) )->withMetaQuery( self::SOURCE, $source )
			->orderByMetaValue( $order->key, $order->valueType, $order->order, $order->isRandom )
			->numberOfPosts( $postsCount )
			->withSpecificPosts( FeedAdvancedFilters::customOrderPostIdsForApi( $settings ) )
			->posts();

		return $this->processQuery( $query );
	}

	private function processQuery( QueryResult $query ): QueryResult {
		if ( ! $query ) {
			return new QueryResult( [], 0 );
		}

		$data = array_map(
			function ( $post ) {
				return $this->buildMediaAlbum( $post );
			},
			$query->getPosts()
		);

		return new QueryResult( $data, $query->getTotal() );
	}

	private function buildMediaAlbum( WP_Post $post ): array {
		return [
			'id'               => $post->ID,
			'mediaId'          => $post->{self::MEDIA_ID},
			'mediaType'        => $post->{self::MEDIA_TYPE},
			'mediaUrl'         => $post->{self::MEDIA_URL},
			'url'              => $post->{self::URL},
			'permalink'        => $post->{self::PERMALINK},
			'username'         => $post->{self::USERNAME},
			'videoUrl'         => $post->{self::VIDEO_URL},
			'date'             => $post->{self::DATE},
			'commentsCount'    => $post->{self::COMMENTS_COUNT},
			'likeCount'        => $post->{self::LIKES_COUNT},
			'caption'          => html_entity_decode( $post->{self::CAPTION}, ENT_QUOTES, 'UTF-8' ),
			'children'         => $post->{self::CHILDREN},
			'mediaProductType' => $post->{self::MEDIA_PRODUCT_TYPE},
			'lastRequested'    => $post->{self::LAST_REQUESTED},
			'source'           => $post->{self::SOURCE},
		];
	}

	public function posts(): array {
		return [];
	}

	protected function args(): array {
		return array_merge(
			parent::args(),
			[
				'labels' => [
					'menu_name' => __( 'Inavii Ig Media', 'inavii-social-feed' ),
				],
			]
		);
	}
}
