<?php

namespace GemBoards\Collections;

use GemBoards\Classes\AbstractCollection;
use GemBoards\Classes\Exception\GemboardsInvalidArgumentException;
use GemBoards\Entities\Card;
use GemBoards\entities\CardAssignee;

class CardCollection extends AbstractCollection {

	protected string $table = 'gemboards_cards';

	protected string $object_type = 'card';

	protected string $primary_key = 'id';

	protected string $order_by = 'id'; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.PropertyNotSnakeCase

	protected string $order       = 'ASC';
	protected string $return_type = Card::class; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.PropertyNotSnakeCase

	/**
	 * @throws GemboardsInvalidArgumentException
	 */
	public static function get_cards_by_assignee( array $user_ids = [], array $conditions = [] ): array {
		$card_assignees = new CardAssigneeCollection( [
			'per_page' => - 1,
			'where'    => [
				[
					'key'     => 'user_id',
					'value'   => $user_ids,
					'compare' => 'IN',
				],
			],
		] );
		$card_ids       = array_map(
		/**
		 * @param CardAssignee $card_assignee
		 *
		 * @return int
		 */ fn( CardAssignee $card_assignee ) => $card_assignee->get_card_id(), $card_assignees->get_results()
		);

		if ( empty( $card_ids ) ) {
			return [];
		}

		return ( ( new self( [
			'per_page' => - 1,
			'where'    => array_merge( [
				[
					'key'     => 'id',
					'value'   => $card_ids,
					'compare' => 'IN',
				],
				[
					'key'   => 'archived',
					'value' => 0,
				],
			], $conditions ),
		] ) )->get_results() ?? [] );
	}

	/**
	 * @throws GemboardsInvalidArgumentException
	 */
	public static function get_cards_no_assignee( int $board_id, int $column_id ): array {
		$cache_key   = "get_cards_no_assignee_{$board_id}_$column_id";
		$cache_group = 'gemboards_card_assignees';
		$card_ids    = wp_cache_get( $cache_key, $cache_group );

		if ( false === $card_ids ) {
			global $wpdb;
			// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
			$results = $wpdb->get_results(
				$wpdb->prepare(
					"SELECT
							c.id
						FROM
							{$wpdb->prefix}gemboards_cards AS c
							LEFT JOIN {$wpdb->prefix}gemboards_card_assignees AS ca ON ca.card_id = c.id
						WHERE
							ca.card_id IS NULL AND c.column_id = %d AND c.board_id = %d AND c.archived = 0", $column_id, $board_id
				)
			);
			// phpcs:enable

			$card_ids = array_map( fn( $result ) => $result->id, $results );
			wp_cache_set( $cache_key, $card_ids, $cache_group );
		}

		if ( empty( $card_ids ) ) {
			return [];
		}

		return ( ( new self( [
			'per_page' => - 1,
			'where'    => [
				[
					'key'     => 'id',
					'value'   => $card_ids,
					'compare' => 'IN',
				],
			],
		] ) )->get_results() ?? [] );
	}

	/**
	 * @param int $board_id
	 * @param string $search
	 *
	 * @return Int[]
	 */
	public static function get_card_ids_for_board( int $board_id, string $search = '' ): array {
		if ( ! $board_id ) {
			return [];
		}

		$cache_key   = 'gemboards_card_ids_for_board_' . $board_id . '_' . $search;
		$cache_group = 'gemboards_cards';
		$has_cache   = wp_cache_get( $cache_key, $cache_group );

		$card_ids = [];
		if ( is_array( $has_cache ) ) {
			$card_ids = $has_cache;
		}

		if ( ! empty( $search ) ) {
			$search = '%' . $search . '%';
		}

		if ( empty( $card_ids ) ) {
			global $wpdb;
			// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
			$results = $wpdb->get_results(
				$wpdb->prepare(
					'SELECT
							card.id
						FROM
							wp_posts AS post
							INNER JOIN wp_gemboards_cards card ON post.ID = card.task_id AND card.board_id = %d AND card.archived = 0
						WHERE
							post.post_title LIKE %s
							OR post.post_content LIKE %s',
					$board_id,
					$search,
					$search,
				)
			);
			// phpcs:enable
			$card_ids = array_map( fn( $result ) => absint( $result->id ), $results );
			wp_cache_set( $cache_key, $card_ids, $cache_group );
		}

		return $card_ids;
	}
}
