<?php

namespace Pixalia\ImageAssistant\Repository;

use Pixalia\ImageAssistant\Admin\View\PostListStatusTabs;
use Pixalia\ImageAssistant\Base\Const\MetaKeyConst;
use Pixalia\ImageAssistant\Base\Const\PixaliaConst;
use Pixalia\ImageAssistant\Base\Enum\ImageCheck\ImageCheckResultStatusEnum;
use Pixalia\ImageAssistant\Base\Enum\ImageCheck\ImageSetFromEnum;
use Pixalia\ImageAssistant\Service\Container\ImageCheckResult;
use WP_Query;

class PostRepository {

	/**
	 * ステータスの優先度マップ
	 */
	private const STATUS_PRIORITY = [
		'ok'      => 1,
		'warning' => 2,
		'ng'      => 3,
	];

	/**
	 * 指定された投稿の画像ステータスを取得します。
	 *
	 * @param int $postId
	 *
	 * @return ImageCheckResultStatusEnum メタデータがない場合は NG を返す
	 */
	public function getImageStatus( int $postId ): ImageCheckResultStatusEnum {
		$statusValue = get_post_meta( $postId, MetaKeyConst::ImageStatus, true );
		$statusEnum  = ImageCheckResultStatusEnum::tryFrom( (string) $statusValue );

		return $statusEnum ?: ImageCheckResultStatusEnum::NG;
	}

	/**
	 * 指定された投稿の画像ソースを取得します。
	 *
	 * @param int $postId
	 *
	 * @return ImageSetFromEnum メタデータがない場合は None を返す
	 */
	public function getImageSource( int $postId ): ImageSetFromEnum {
		$sourceValue = get_post_meta( $postId, MetaKeyConst::ImageSource, true );
		$sourceEnum  = ImageSetFromEnum::tryFrom( (string) $sourceValue );

		return $sourceEnum ?: ImageSetFromEnum::None;
	}


	/**
	 * チェック結果を一括保存（優先度・バージョンも含む）
	 *
	 * このメソッドで以下をすべて保存します:
	 * - 画像ステータス
	 * - 画像ソース
	 * - ソート用優先度
	 * - ロジックバージョン
	 *
	 * @param int $postId 投稿ID
	 * @param ImageCheckResult $result チェック結果
	 * @param int $logicVersion ロジックバージョン
	 *
	 * @return void
	 */
	public function saveImageCheckResult( int $postId, ImageCheckResult $result, int $logicVersion ): void {
		// ステータスを保存
		update_post_meta( $postId, MetaKeyConst::ImageStatus, $result->status->value );

		// ソースを保存
		update_post_meta( $postId, MetaKeyConst::ImageSource, $result->setFromEnum->value );

		// ソート用の優先度を保存
		$priority = self::STATUS_PRIORITY[ $result->status->value ] ?? 999;
		update_post_meta( $postId, MetaKeyConst::ImageStatusPriority, $priority );

		// ロジックバージョンを保存
		update_post_meta( $postId, MetaKeyConst::LogicVersion, $logicVersion );

		// ★ キャッシュをクリア（一度だけ）
		$post = get_post( $postId );
		if ( $post ) {
			PostListStatusTabs::clear_cache( $post->post_type );
		}
	}

	/**
	 * 指定された投稿の画像ステータスを保存（更新）します。
	 *
	 * @param int $postId
	 * @param ImageCheckResultStatusEnum $status
	 *
	 * @return bool|int 更新された場合はメタID、失敗した場合はfalse、変更がなければtrue
	 */
	public function updateImageStatus( int $postId, ImageCheckResultStatusEnum $status ): bool|int {
		$result = update_post_meta( $postId, MetaKeyConst::ImageStatus, $status->value );

		// 更新成功時、キャッシュをクリア
		if ( $result ) {
			$post = get_post( $postId );
			if ( $post ) {
				PostListStatusTabs::clear_cache( $post->post_type );
			}
		}

		return $result;
	}

	/**
	 * 指定された投稿の画像ソースを保存（更新）します。
	 *
	 * @param int $postId
	 * @param ImageSetFromEnum $source
	 *
	 * @return bool|int
	 */
	public function updateImageSource( int $postId, ImageSetFromEnum $source ): bool|int {
		$result = update_post_meta( $postId, MetaKeyConst::ImageSource, $source->value );

		// 更新成功時、キャッシュをクリア
		if ( $result ) {
			$post = get_post( $postId );
			if ( $post ) {
				PostListStatusTabs::clear_cache( $post->post_type );
			}
		}

		return $result;
	}

	/**
	 * 未チェックの投稿数を高速に取得します。
	 *
	 * @return int
	 */
	public function getUncheckedCount(): int {
		$query = $this->getUncheckedPostsQuery( [
			'posts_per_page' => 1,
			'fields'         => 'ids',
			'no_found_rows'  => false,
		] );

		return (int) $query->found_posts;
	}

	/**
	 * 未チェックの投稿をバッチで取得します。
	 *
	 * @param int $limit
	 *
	 * @return \WP_Post[]
	 */
	public function getUncheckedPosts( int $limit = 50 ): array {
		$query = $this->getUncheckedPostsQuery( [
			'posts_per_page' => $limit,
			'fields'         => 'all',
			'no_found_rows'  => true,
		] );

		return $query->posts;
	}

	/**
	 * 未チェックの投稿を取得する共通WP_Queryを生成します。
	 *
	 * @param array $extra_args
	 *
	 * @return \WP_Query
	 */
	private function getUncheckedPostsQuery( array $extra_args = [] ): \WP_Query {
		$allowedPostTypes = get_option( PixaliaConst::OPTION_POST_TYPES, [ 'post' ] );
		if ( empty( $allowedPostTypes ) ) {
			$allowedPostTypes = [ 'post' ];
		}

		$default_args = [
			'post_type'     => $allowedPostTypes,
			'post_status'   => 'any',
			'no_found_rows' => true,
			'cache_results' => false,
			// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- ステータスによる絞り込み機能に必須のため
			'meta_query'    => [
				'relation' => 'OR',
				[
					'key'     => MetaKeyConst::LogicVersion,
					'compare' => 'NOT EXISTS',
				],
				[
					'key'     => MetaKeyConst::LogicVersion,
					'value'   => PixaliaConst::LOGIC_VERSION,
					'compare' => '<',
					'type'    => 'NUMERIC',
				],
			],
		];

		$args = wp_parse_args( $extra_args, $default_args );

		return new \WP_Query( $args );
	}
}
