<?php

namespace GemBoards\Ajax;

use GemBoards\Classes\AbstractAjaxHandler;
use GemBoards\Classes\Exception\GemboardsInvalidArgumentException;
use GemBoards\Collections\CardCollection;
use GemBoards\entities\CardAssignee;
use GemBoards\Utils\Helper;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class BulkCard extends AbstractAjaxHandler {

	public function __construct() {
		$this->actions = [
			'move_bulk_cards' => [
				'callback' => [ $this, 'move_bulk_cards' ],
				'fields'   => [
					'cards' => [

						[
							'card_id'   => 'integer',
							'column_id' => 'integer',
							'sprint_id' => 'integer',
						],
					],
				],
			],
			'bulk_assign_cards' => [
				'callback' => [ $this, 'bulk_assign_cards' ],
				'fields'   => [
					'cards' => [
						[
							'card_id'   => 'integer',
							'user_ids' => 'string',
						],
					],
				],
			],
			'bulk_tasks_label' => [
				'callback' => [ $this, 'bulk_tasks_label' ],
				'fields'   => [
					'cards' => [
						[
							'task_id'   => 'integer',
							'labels'    => 'string',
						],
					],
				],
			],
		];
	}

	public function move_bulk_cards( array $payload ) {
		if ( ! isset( $payload['cards'] ) ) {
			wp_send_json_error( [
				'message' => __('Card array is required.', 'gemboards'),
			] );
		}

		foreach ( $payload['cards'] as $card ) {
			if ( empty($card['card_id']) ) {
				wp_send_json_error( [
					'message' => __('Card ID is required.', 'gemboards'),
				]);
			}

			if ( empty($card['column_id']) && empty($card['sprint_id']) ) {
				wp_send_json_error( [
					'message' => __('Column ID or Sprint ID is required.', 'gemboards'),
				] );
			}
		}

		$card_ids = [];
		try {
			$card_ids = ( new CardCollection( [
				'per_page' => - 1,
				'fields'   => 'ids',
				'where'    => [
					[
						'key'     => 'id',
						'value'   => array_map( fn( $card ) => absint( $card['card_id'] ), $payload['cards'] ),
						'compare' => 'IN',
					],
				],
			] ) )->get_results();
		} catch ( GemboardsInvalidArgumentException $e ) {
			wp_send_json_error( [
				'message' => $e->getMessage(),
			]);
			Helper::error_log( $e->getMessage() );
		}

		foreach ( $payload['cards'] as $card_data ) {
			if ( ! in_array( absint($card_data['card_id']), $card_ids, true ) ) {
				wp_send_json_error( [
					'message' => __('Invalid card id.', 'gemboards'),
				]);
			}
		}

		global $wpdb;

		$column_case = "column_id = CASE id ";
		$sprint_case = "sprint_id = CASE id ";
		foreach ( $payload['cards'] as $card_data ) {
			$column_case .= $wpdb->prepare( "WHEN %d THEN %d ", absint( $card_data['card_id'] ), absint( $card_data[ 'column_id' ] ) );
			$sprint_case  .= $wpdb->prepare( "WHEN %d THEN %d ", absint( $card_data['card_id'] ), absint( $card_data[ 'sprint_id' ] ) );
		}
		$column_case .= "END";
		$sprint_case  .= "END";

		$id_placeholders = implode( ',', array_fill( 0, count( $payload['cards'] ), '%d' ) );

		$query = $wpdb->prepare(
			"UPDATE {$wpdb->prefix}gemboards_cards
		     SET $column_case, {$sprint_case}
		     WHERE id IN ($id_placeholders)",
			...array_map( fn( $card ) => absint($card['card_id']), $payload['cards'] )
		);
		$wpdb->query( $query );

		if ( $wpdb->last_error ) {
			wp_send_json_error( [
				'message' => $wpdb->last_error,
			] );
		}

		do_action( 'gemboards/bulk_cards/moved', $payload['cards'] );

		wp_send_json_success();
	}

	public function bulk_assign_cards( array $payload ) {
		if ( ! isset( $payload['cards'] ) ) {
			wp_send_json_error( [
				'message' => __('Card array is required.', 'gemboards'),
			] );
		}

		$card_data = [];
		foreach ( $payload['cards'] as $card ) {
			if ( empty($card['card_id']) ) {
				wp_send_json_error( [
					'message' => __('Card ID is required.', 'gemboards'),
				]);
			}

			$card_id = absint($card['card_id']);
			if ( ! Helper::get_card( $card_id ) ) {
				wp_send_json_error( [
					'message' => __('Invalid card id.', 'gemboards'),
				]);
			}

			$user_ids = explode(',', $card['user_ids']);
			if ( empty($user_ids) ) {
				wp_send_json_error( [
					'message' => __('User IDs are required.', 'gemboards'),
				]);
			}
			$user_ids = array_map( 'trim', $user_ids );
			$user_ids = array_map('absint', $user_ids);
			$card_data[] = [
				'card_id' => $card_id,
				'user_ids' => $user_ids,
			];
		}

		global $wpdb;
		$card_ids_placeholders = implode( ',', array_fill( 0, count( $card_data ), '%d' ) );
		$wpdb->query(
			$wpdb->prepare("DELETE FROM {$wpdb->prefix}gemboards_card_assignees WHERE card_id IN ($card_ids_placeholders)", ...array_map( fn( $card ) => $card['card_id'], $card_data ))
		);
		if ( $wpdb->last_error ) {
			wp_send_json_error( [
				'message' => $wpdb->last_error,
			] );
		}

		foreach ( $card_data as $card_datum ) {
			foreach ( $card_datum['user_ids'] as $user_id ) {
				$card_assignee = new CardAssignee();
				$card_assignee->set_card_id( $card_datum['card_id'] );
				$card_assignee->set_user_id( $user_id );
				$card_assignee->save();
			}
		}

		wp_send_json_success();
	}

	public function bulk_tasks_label( array $payload ) {
		if ( ! isset( $payload['cards'] ) ) {
			wp_send_json_error( [
				'message' => __('Card array is required.', 'gemboards'),
			] );
		}

		$card_data = [];
		foreach ( $payload['cards'] as $card ) {
			if ( empty($card['task_id']) ) {
				wp_send_json_error( [
					'message' => __('Task ID is required.', 'gemboards'),
				]);
			}

			$task_id = absint($card['task_id']);
			if ( ! Helper::get_card_by_task_id( $task_id ) ) {
				wp_send_json_error( [
					'message' => __('Invalid Task id.', 'gemboards'),
				]);
			}

			$labels = array_map('trim', explode(',', $card['labels']));
			$card_data[] = [
				'task_id' => $task_id,
				'labels'  => $labels,
			];
		}

		foreach ( $card_data  as $card ) {
			if ( ! empty( $card['labels'] ) ) {
				wp_set_object_terms( $card['task_id'], $card['labels'], 'gemboards_label' );
			} else {
				wp_set_object_terms( $card['task_id'], [], 'gemboards_label' );
			}
		}

		wp_send_json_success();
	}

}
