<?php
declare( strict_types=1 );


namespace Inavii\Instagram\Includes\Legacy\Wp;

use Inavii\Instagram\Wp\QueryResult;

class Query {

	private $query = [];

	public function __construct( string $postTypeSlug ) {
		$this->query['post_type']   = $postTypeSlug;
		$this->query['post_status'] = 'publish';
	}

	public function withPostTitle( string $postTitle ): self {
		$this->query['post_title'] = $postTitle;

		return $this;
	}

	public function withMetaInput( string $key, $value ): self {
		$this->query['meta_input'][ $key ] = $value;

		return $this;
	}

	public function withMetaQuery( string $key, $value, string $compare = '=' ): self {
		if ( is_array( $value ) ) {
			return $this->withMetaQueryRelation( $key, $value );
		}

		$this->query['meta_query'][] = [
			'key'     => $key,
			'value'   => $value,
			'compare' => $compare,
		];

		return $this;
	}

	public function withMetaQueryRelation( string $key, array $values, string $compare = '=', string $relation = 'OR' ): self {
		if ( empty( $values ) ) {
			return $this;
		}

		$metaQuery = [ 'relation' => $relation ];

		foreach ( $values as $value ) {
			$metaQuery[] = [
				'key'     => $key,
				'value'   => $value,
				'compare' => $compare,
			];
		}

		$this->query['meta_query'][] = $metaQuery;

		return $this;
	}

	public function withExcludePosts( array $postsID ): self {
		if ( empty( $postsID ) ) {
			return $this;
		}

		$this->query['post__not_in'] = $postsID;

		return $this;
	}

	public function withSpecificPosts( array $postsID ): self {
		if ( empty( $postsID ) ) {
			return $this;
		}

		$this->query['post__in'] = $postsID;
		$this->query['orderby']  = 'post__in';

		return $this;
	}

	public function withOffset( int $offset = 0 ): self {
		if ( $offset < 0 || $offset === 0 ) {
			return $this;
		}

		$this->query['offset'] = $offset;

		return $this;
	}

	public function orderByMetaValue( string $metaKey, string $valueType = 'CHAR', string $order = 'ASC', bool $random = false ): self {
		if ( $random ) {
			$this->query['orderby'] = 'rand';
			return $this;
		}

		$this->query['meta_key'] = $metaKey;
		$this->query['orderby']  = $valueType === 'NUMERIC' ? 'meta_value_num' : 'meta_value';
		$this->query['order']    = strtoupper( $order ) === 'ASC' ? 'ASC' : 'DESC';

		return $this;
	}

	public function numberOfPosts( int $number = -1 ): self {
		$this->query['posts_per_page'] = $number;

		return $this;
	}

	public function order( $order ): self {
		$this->query['order'] = $order;

		return $this;
	}

	public function findPostByTitle(): \WP_Query {
		$args = [
			'post_type'      => $this->query['post_type'],
			'post_status'    => 'publish',
			'title'          => $this->query['post_title'],
			'posts_per_page' => 1,
		];

		return new \WP_Query( $args );
	}

	public function save() {
		$postExists = $this->findPostByTitle();

		if ( $postExists->have_posts() ) {
			$data = array_merge( $this->query, [ 'ID' => $postExists->posts[0]->ID ] );

			return wp_update_post( $data );
		}

		$id = wp_insert_post( $this->query );

		$this->query = [];

		return $id;
	}

	public function saveMedia( string $immutableInput = '' ) {
		$postExists = $this->findPostByTitle();

		if ( $postExists->have_posts() ) {
			$id = $postExists->posts[0]->ID;

			$existing_meta = get_post_meta( $id, $immutableInput );

			if ( ! in_array( $this->query['meta_input'][ $immutableInput ], $existing_meta ) ) {
				add_post_meta( $id, $immutableInput, $this->query['meta_input'][ $immutableInput ] );
				unset( $this->query['meta_input'][ $immutableInput ] );
				return wp_update_post( array_merge( $this->query, [ 'ID' => $id ] ) );
			}

			unset( $this->query['meta_input'][ $immutableInput ] );

			return wp_update_post( array_merge( $this->query, [ 'ID' => $id ] ) );
		}

		$id = wp_insert_post( $this->query );

		$this->query = [];

		return $id;
	}

	public function withFields( $param ): self {
		$this->query['fields'] = $param;

		return $this;
	}

	public function posts(): QueryResult {
		$query = new \WP_Query( $this->query );

		return new QueryResult( $query->posts, $query->found_posts );
	}

	public function post( $postID ) {
		return get_post( $postID );
	}

	public function countPosts(): int {
		try {
			$args                   = $this->query;
			$args['fields']         = 'ids';
			$args['posts_per_page'] = -1;

			$posts = get_posts( $args );

			return is_array( $posts ) ? count( $posts ) : 0;
		} catch ( \Exception $e ) {
			return 0;
		}
	}
}
