<?php

namespace GemBoards\Ajax;

use GemBoards\Classes\AbstractAjaxHandler;
use GemBoards\Classes\Exception\GemboardsException;
use GemBoards\Classes\Exception\GemboardsInvalidArgumentException;
use GemBoards\Collections\CardAssigneeCollection;
use GemBoards\Collections\CardCollection;
use GemBoards\Collections\TaskAttachmentCollection;
use GemBoards\entities\CardAssignee;
use GemBoards\Entities\TaskAttachment;
use GemBoards\Utils\Helper;
use GemBoardsPro\Collections\TaskChecklistCollection;
use GemBoardsPro\Collections\TaskChecklistGroupCollection;
use GemBoardsPro\Entities\TaskChecklistGroup;
use WP_Error;

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

class Card extends AbstractAjaxHandler {

	public function __construct() {
		$this->actions = [
			'create_card'        => [
				'callback'   => [ $this, 'create_card' ],
				'permission' => 'manage_tasks',
				'fields'     => [
					'id'             => 'integer',
					'parent_task_id' => 'integer',
					'title'          => 'string',
					'column_id'      => 'integer',
					'board_id'       => 'integer',
					'sprint_id'      => 'integer',
					'description'    => 'post',
					'labels'         => 'string',
					'sort_order'     => 'integer',
					'story_point'    => 'integer',
					'due_date'       => 'string',
					'priority'       => 'string',
					'assignees'      => 'string',
					'custom_fields' => [
						[
							'field_id' => 'integer',
							'value'    => 'string',
						],
					],
				],
			],
			'move_card'          => [
				'callback'   => [ $this, 'move_card' ],
				'permission' => 'manage_tasks',
				'fields'     => [
					'card_id'   => 'integer',
					'column_id' => 'integer',
					'sprint_id' => 'integer',
				],
			],
			'move_card_to_board' => [
				'callback'   => [ $this, 'move_card_to_board' ],
				'permission' => 'manage_tasks',
				'fields'     => [
					'card_id'    => 'integer',
					'column_id'  => 'integer',
					'sprint_id'  => 'integer',
					'board_id'   => 'integer',
					'sort_order' => 'integer',
				],
			],
			'sort_cards'         => [
				'callback' => [ $this, 'sort_cards' ],
				'fields'   => [
					'cards' => [
						[
							'card_id'    => 'integer',
							'sort_order' => 'integer',
						],
					],
				],
			],
			'get_card'           => [
				'callback' => [ $this, 'get_card' ],
				'fields'   => [
					'id' => 'integer',
				],
			],
			'duplicate_card'     => [
				'callback'   => [ $this, 'duplicate_card' ],
				'permission' => 'manage_tasks',
				'fields'     => [
					'title'     => 'string',
					'card_id'   => 'integer',
					'column_id' => 'integer',
					'fields'    => 'string',
				],
			],
			'archive_card'       => [
				'callback'   => [ $this, 'archive_card' ],
				'permission' => 'manage_tasks',
				'fields'     => [
					'card_id' => 'integer',
				],
			],
			'restore_card'       => [
				'callback'   => [ $this, 'restore_card' ],
				'permission' => 'manage_tasks',
				'fields'     => [
					'card_id' => 'integer',
				],
			],
			'bulk_restore_cards' => [
				'callback'   => [ $this, 'bulk_restore_cards' ],
				'permission' => 'manage_tasks',
				'fields'     => [
					'board_id' => 'integer',
					'card_ids' => 'string',
				],
			],
			'assign_card_users'  => [
				'callback'   => [ $this, 'assign_card_users' ],
				'permission' => 'manage_tasks',
				'fields'     => [
					'card_id' => 'integer',
					'user_id' => 'integer',
				],
			],
			'remove_card_users'  => [
				'callback'   => [ $this, 'remove_card_users' ],
				'permission' => 'manage_tasks',
				'fields'     => [
					'card_id' => 'integer',
					'user_id' => 'integer',
				],
			],
			'get_card_assignees' => [
				'callback'   => [ $this, 'get_card_assignees' ],
				'permission' => 'manage_tasks',
				'fields'     => [
					'card_id' => 'integer',
				],
			],
			'delete_card'        => [
				'callback'   => [ $this, 'delete_card' ],
				'permission' => 'manage_tasks',
				'fields'     => [
					'card_id' => 'integer',
				],
			],
			'bulk_delete_cards'  => [
				'callback'   => [ $this, 'bulk_delete_cards' ],
				'permission' => 'manage_tasks',
				'fields'     => [
					'board_id' => 'integer',
					'card_ids' => 'string',
				],
			],
		];
	}

	public function create_card( $request ) {
		$id            = $request['id'] ?? 0;
		$column_id     = $request['column_id'] ?? 0;
		$title         = $request['title'] ?? '';
		$board_id      = $request['board_id'] ?? 0;
		$sort_order    = $request['sort_order'] ?? 1;
		$sprint_id     = $request['sprint_id'] ?? 0; // Optional sprint ID
		$story_point   = $request['story_point'] ?? 0; // Optional sprint ID
		$due_date      = empty( $request['due_date'] ) || 'null' === $request['due_date'] ? null : $request['due_date'];
		$description   = wp_kses_post( $request['description'] ?? '' );
		$custom_fields = $request['custom_fields'] ?? [];

		if ( empty( $title ) || empty( $board_id ) ) {
			wp_send_json_error( [
				'message' => __( 'Title and Board Id fields are required.', 'gemboards' ),
			] );
		}

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

			$task_title       = $card->get_task()->post_title;
			$task_description = $card->get_task()->post_content;

			wp_update_post( [
				'ID'           => $card->get_task_id(),
				'post_title'   => $title,
				'post_content' => $description,
				'post_parent'  => $request['parent_task_id'] ?? 0,
			] );

			if ( $task_title !== $title ) {
				do_action( 'gemboards/card/title_updated', $card->get_id(), $title );
			}

			if ( $task_description !== $description ) {
				do_action( 'gemboards/card/description_updated', $card->get_id(), $description );
			}
		} else {
			$card    = new \GemBoards\Entities\Card();
			$task_id = wp_insert_post( [
				'post_title'   => $title,
				'post_content' => $description,
				'post_type'    => Helper::BOARD_TASK_POST_TYPE,
				'post_status'  => 'publish',
				'post_author'  => get_current_user_id(),
				'post_parent'  => $request['parent_task_id'] ?? 0,
			] );
			if ( is_wp_error( $task_id ) ) {
				wp_send_json_error( [
					'message' => $task_id->get_error_message(),
				] );
			}
			$card->set_task_id( $task_id );
		}
		$card->set_column_id( $column_id );
		$card->set_board_id( $board_id );
		$card->set_sprint_id( $sprint_id );
		$card->set_story_point( $story_point );
		$card->set_sort_order( $sort_order );
		$card->set_due_date( $due_date );
		$result = $card->save();
		if ( is_wp_error( $result ) ) {
			wp_send_json_error( [
				'message' => $result->get_error_message(),
			] );
		}

		if ( ! empty( $request['priority'] ) ) {
			wp_set_object_terms( $card->get_task_id(), $request['priority'], 'gemboards_priority' );
		} else {
			wp_set_object_terms( $card->get_task_id(), [], 'gemboards_priority' );
		}

		if ( ! empty( $request['labels'] ) ) {
			$labels = explode( ',', $request['labels'] );
			wp_set_object_terms( $card->get_task_id(), $labels, 'gemboards_label' );
		} else {
			wp_set_object_terms( $card->get_task_id(), [], 'gemboards_label' );
		}

		if ( ! empty( $custom_fields ) && Helper::has_pro() ) {
			foreach ( $custom_fields as $custom_field ) {
				if ( empty( $custom_field['field_id'] ) ) {
					continue;
				}
				update_post_meta( $card->get_task_id(), "_gemboards_pro_custom_field_{$custom_field['field_id']}", $custom_field['value'] );
			}
		}

		$assignees = explode( ',', $request['assignees'] ?? '' );
		if ( ! empty( $assignees ) ) {
			$assignees = array_map( 'trim', $assignees );
			$assignees = array_map( 'absint', $assignees );

			if ( ! empty( $request['id'] ) ) {
				$delete_assignee_ids = [];
				foreach ( $card->get_assignees() as $card_assignee ) {
					if ( ! in_array( $card_assignee->get_user_id(), $assignees, true ) ) {
						$delete_assignee_ids[] = $card_assignee->get_id();
					}
				}

				if ( ! empty( $delete_assignee_ids ) ) {
					try {
						$card_assignees = new CardAssigneeCollection( [
							'per_page' => - 1,
							'where'    => [
								[
									'key'     => 'id',
									'value'   => $delete_assignee_ids,
									'compare' => 'IN',
								],
							],
						] );
						foreach ( $card_assignees->get_results() as $card_assignee ) {
							try {
								$card_assignee->delete();
							} catch ( GemboardsException $e ) {
								Helper::error_log( $e->getMessage() );
							}
						}
					} catch ( GemboardsInvalidArgumentException $e ) {
						Helper::error_log( $e->getMessage() );
					}
				}
			}

			if ( ! empty( $assignees ) ) {
				foreach ( $assignees as $assignee ) {
					$this->assign_user_in_card( absint( $assignee ), $card->get_id() );
				}
			}
		} else {
			if ( ! empty( $request['id'] ) ) {
				foreach ( $card->get_assignees() as $assignee ) {
					try {
						$assignee->delete();
					} catch ( GemboardsException $e ) {
						Helper::error_log( $e->getMessage() );
					}
				}
			}
		}

		$assignee_list = array_map( function ( $assignee ) {
			return [
				'id'     => $assignee->get_user_id(),
				'name'   => get_the_author_meta( 'display_name', $assignee->get_user_id() ),
				'avatar' => get_avatar_url( $assignee->get_user_id(), [ 'size' => 96 ] ),
			];
		}, $card->get_assignees( true ) );
		$activity      = array_map( function ( $comment ) {
			return [
				'id'        => (int) $comment->comment_ID,
				'content'   => $comment->comment_content,
				'date_time' => get_comment_date( 'Y-m-d H:i', $comment ),
				'author'    => $comment->comment_author,
				'avatar'    => get_avatar_url( $comment->user_id, [ 'size' => 96 ] ),
			];
		}, Helper::get_card_activities( $card->get_task_id() ) );
		wp_send_json_success( array_merge( $this->get_card_data( $card ), [
			'assignees' => $assignee_list,
			'activity'  => $activity,
		] ) );
	}

	public function move_card( array $payload ) {
		if ( ! isset( $payload['card_id'] ) ) {
			wp_send_json_error( [
				'message' => 'Card ID is required.',
			] );
		}
		$card_id = $payload['card_id'];
		$card    = Helper::get_card( $card_id );
		if ( ! $card ) {
			wp_send_json_error( [
				'message' => __( 'Invalid card id.', 'gemboards' ),
			] );
		}

		$column_id = $payload['column_id'] ?? 0;
		if ( 0 !== $column_id ) {
			$column = Helper::get_column( $column_id );
			if ( ! $column ) {
				wp_send_json_error( [
					'message' => __( 'Invalid column id.', 'gemboards' ),
				] );
			}

			if ( $card->get_board_id() !== $column->get_board_id() ) {
				wp_send_json_error( [
					'message' => __( 'Invalid column id.', 'gemboards' ),
				] );
			}
		}

		$sprint_id = $payload['sprint_id'] ?? 0;

		$board = $card->get_board();
		if ( ! $board ) {
			wp_send_json_error( [
				'message' => __( 'Invalid card board.', 'gemboards' ),
			] );
		}

		if ( $sprint_id && ! $column_id ) {
			$board_columns = $board->get_columns();
			if ( ! empty( $board_columns ) ) {
				$first_column = reset( $board_columns );
				$column_id    = $first_column->get_id();
			}
		}

		$completed_column_id = $board->get_completed_column_id();
		if ( $completed_column_id && $completed_column_id === $column_id ) {
			$card->set_is_completed( true );
		}

		if ( $column_id ) {
			$card->set_column_id( $column_id );
		}

		$card->set_sprint_id( $sprint_id );

		$result = $card->save();
		if ( is_wp_error( $result ) ) {
			wp_send_json_error( [
				'message' => $result->get_error_message(),
			] );
		}

		do_action( 'gemboards/card/moved', $card_id, $column_id );
		wp_send_json_success( $this->get_card_data( $card ) );
	}

	public function move_card_to_board( array $payload ) {
		if ( empty( $payload['card_id'] ) ) {
			wp_send_json_error( [
				'message' => __( 'Card ID is required.', 'gemboards' ),
			] );
		}

		if ( empty( $payload['board_id'] ) ) {
			wp_send_json_error( [
				'message' => __( 'Board ID is required.', 'gemboards' ),
			] );
		}

		$card_id    = $payload['card_id'];
		$column_id  = empty( $payload['column_id'] ) ? 0 : $payload['column_id'];
		$board_id   = $payload['board_id'];
		$sprint_id  = empty( $payload['sprint_id'] ) ? 0 : $payload['sprint_id'];
		$sort_order = empty( $payload['sort_order'] ) ? 1 : $payload['sort_order'];

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

		$board = Helper::get_board( $board_id );
		if ( ! $board ) {
			wp_send_json_error( [
				'message' => __( 'Invalid Board ID.', 'gemboards' ),
			] );
		}

		if ( 'kanban' === $board->get_board_type() && empty( $column_id ) ) {
			wp_send_json_error( [
				'message' => __( 'Column ID is required.', 'gemboards' ),
			] );
		}

		if ( ! empty( $column_id ) ) {
			$column = Helper::get_column( $column_id );
			if ( ! $column ) {
				wp_send_json_error( [
					'message' => __( 'Invalid Column ID.', 'gemboards' ),
				] );
			}

			if ( $column->get_board_id() !== $board_id ) {
				wp_send_json_error( [
					'message' => __( 'Column does not belong to the selected board.', 'gemboards' ),
				] );
			}
		}

		global $wpdb;

		// Reorder sort_order of other cards if the newly moved card isn't inserted at the last order of a column.
		// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$max_sort_order = (int) $wpdb->get_var(
			$wpdb->prepare(
				"SELECT MAX(sort_order) FROM {$wpdb->prefix}gemboards_cards WHERE column_id = %d AND board_id = %d",
				$column_id,
				$board_id
			)
		);

		if ( $sort_order <= $max_sort_order ) {
			$wpdb->query(
				$wpdb->prepare(
					"UPDATE {$wpdb->prefix}gemboards_cards SET sort_order = sort_order + 1 WHERE column_id = %d AND board_id = %d AND sort_order >= %d",
					$column_id,
					$board_id,
					$sort_order
				)
			);
		} else {
			// If sort_order is greater than max, set it to max + 1
			$sort_order = $max_sort_order + 1;
		}
		// phpcs:enable

		$card->set_board_id( $board_id );
		$card->set_column_id( $column_id );
		$card->set_sort_order( $sort_order );
		$card->set_sprint_id( $sprint_id );

		$result = $card->save();
		if ( is_wp_error( $result ) ) {
			wp_send_json_error( [
				'message' => $result->get_error_message(),
			] );
		}

		wp_send_json_success( $this->get_card_data( $card ) );
	}

	public function sort_cards( $request ) {
		$cards = $request['cards'] ?? [];

		if ( empty( $cards ) || ! is_array( $cards ) ) {
			wp_send_json_error( [ 'message' => __( 'Invalid card data.', 'gemboards' ) ] );
		}

		foreach ( $cards as $card ) {
			if ( ! isset( $card['card_id'], $card['sort_order'] ) ) {
				wp_send_json_error( [ 'message' => __( 'Invalid card data.', 'gemboards' ) ] );
			}

			if ( ! current_user_can( 'manage_tasks', [
				'card_id' => $card['card_id'],
			] ) ) {
				wp_send_json_error( [ 'message' => __( 'You do not have permission to sort cards.', 'gemboards' ) ] );
			}
		}

		$card_ids   = [];
		$conditions = '';

		global $wpdb;
		foreach ( $cards as $card ) {
			$card_id     = absint( $card['card_id'] );
			$sort_order  = absint( $card['sort_order'] );
			$conditions .= $wpdb->prepare(
				"WHEN %d THEN %d \n", $card_id, $sort_order
			);
			$card_ids[]  = $card_id;
		}

		$card_ids_formatter = implode( ',', array_fill( 0, count( $card_ids ), '%d' ) );

		// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- Clearing cache by calling clear_cache method of entity class.
		$wpdb->query(
			$wpdb->prepare(
				"UPDATE {$wpdb->prefix}gemboards_cards
						SET sort_order = CASE id
						   $conditions
						END
						WHERE id IN ($card_ids_formatter)", ...$card_ids
			)
		);
		// phpcs:enable

		( new \GemBoards\Entities\Card() )->clear_cache();
		do_action( 'gemboards/card/sorted', $cards );
		wp_send_json_success( [ 'message' => 'Cards sorted successfully.' ] );
	}

	public function get_card( $request ) {
		$card_id = $request['id'] ?? 0;
		if ( empty( $card_id ) ) {
			wp_send_json_error( [
				'message' => __( 'Card ID is required.', 'gemboards' ),
			] );
		}
		if ( ! current_user_can( 'manage_tasks', [ 'card_id' => $card_id ] ) ) {
			wp_send_json_error( [
				'message' => __( 'You do not have permission to view this card.', 'gemboards' ),
			] );
		}

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

		wp_send_json_success( $this->get_card_data( $card ) );
	}

	public function duplicate_card( array $payload ) {
		if ( empty( $payload['title'] ) ) {
			wp_send_json_error( [
				'message' => __( 'Title is required.', 'gemboards' ),
			] );
		}
		if ( empty( $payload['card_id'] ) ) {
			wp_send_json_error( [
				'message' => __( 'Card ID is required.', 'gemboards' ),
			] );
		}
		if ( empty( $payload['column_id'] ) ) {
			wp_send_json_error( [
				'message' => __( 'Column ID is required.', 'gemboards' ),
			] );
		}
		if ( empty( $payload['fields'] ) ) {
			wp_send_json_error( [
				'message' => __( 'Fields is required.', 'gemboards' ),
			] );
		}

		$card_id = $payload['card_id'];
		$card    = Helper::get_card( $card_id );
		if ( ! $card ) {
			wp_send_json_error( [
				'message' => __( 'Invalid card id.', 'gemboards' ),
			] );
		}
		$column_id = $payload['column_id'];
		$column    = Helper::get_column( $column_id );
		if ( ! $column || $column->get_board_id() !== $card->get_board_id() ) {
			wp_send_json_error( [
				'message' => __( 'Invalid column id.', 'gemboards' ),
			] );
		}

		$task    = $card->get_task();
		$task_id = wp_insert_post( [
			'post_title'   => $payload['title'],
			'post_content' => $task->post_content,
			'post_type'    => Helper::BOARD_TASK_POST_TYPE,
			'post_status'  => 'publish',
			'post_author'  => get_current_user_id(),
		] );
		if ( is_wp_error( $task_id ) ) {
			wp_send_json_error( [
				'message' => $task_id->get_error_message(),
			] );
		}

		$old_card_id = $card->get_id();
		$old_task_id = $card->get_task_id();

		$card->set_task_id( $task_id );
		$card->set_column_id( $column_id );
		$card->set_id( 0 );
		$card->save();

		$fields = explode( ',', $payload['fields'] );
		$fields = array_map( 'trim', $fields );

		if ( in_array( 'labels', $fields, true ) ) {
			$labels = wp_get_object_terms(
				$old_task_id,
				'gemboards_label',
				[
					'fields' => 'ids',
				]
			);
			if ( ! empty( $labels ) && ! is_wp_error( $labels ) ) {
				wp_set_object_terms( $task_id, $labels, 'gemboards_label' );
			}
		}

		if ( in_array( 'priority', $fields, true ) ) {
			$priorities = wp_get_object_terms(
				$old_task_id,
				'gemboards_priority',
				[
					'fields' => 'ids',
				]
			);
			if ( ! empty( $priorities ) ) {
				wp_set_object_terms( $task_id, $priorities, 'gemboards_priority' );
			}
		}

		if ( in_array( 'assignees', $fields, true ) ) {
			/** @var CardAssignee[] $card_assignees */
			try {
				$card_assignees = ( new CardAssigneeCollection( [
					'per_page' => - 1,
					'where'    => [
						[
							'key'   => 'card_id',
							'value' => $old_card_id,
						],
					],
				] ) )->get_results();
				foreach ( $card_assignees as $card_assignee ) {
					$card_assignee->set_card_id( $card->get_id() );
					$card_assignee->set_id( 0 );
					$card_assignee->save();
				}
			} catch ( GemboardsInvalidArgumentException $e ) {
				Helper::error_log( $e->getMessage() );
			}
		}

		if ( in_array( 'comments', $fields, true ) ) {
			$old_comments = get_comments( [
				'post_id' => $old_task_id,
				'status'  => 'all',
				'type'    => 'task_comment',
				'orderby' => 'comment_date_gmt',
				'order'   => 'ASC',
			] );
			foreach ( $old_comments as $old_comment ) {
				$new_comment_id = wp_insert_comment( [
					'comment_post_ID'      => $task_id,
					'comment_author'       => $old_comment->comment_author,
					'comment_author_email' => $old_comment->comment_author_email,
					'comment_author_url'   => $old_comment->comment_author_url,
					'comment_author_IP'    => $old_comment->comment_author_IP,
					'comment_date'         => $old_comment->comment_date,
					'comment_date_gmt'     => $old_comment->comment_date_gmt,
					'comment_content'      => $old_comment->comment_content,
					'comment_karma'        => $old_comment->comment_karma,
					'comment_approved'     => $old_comment->comment_approved,
					'comment_agent'        => $old_comment->comment_agent,
					'comment_type'         => $old_comment->comment_type,
					'comment_parent'       => 0,
					'user_id'              => $old_comment->user_id,
				] );

				if ( ! $new_comment_id ) {
					continue;
				}

				$meta = get_comment_meta( $old_comment->comment_ID );
				foreach ( $meta as $meta_key => $values ) {
					foreach ( $values as $value ) {
						add_comment_meta(
							$new_comment_id,
							$meta_key,
							maybe_unserialize( $value )
						);
					}
				}
			}
		}

		if ( in_array( 'attachments', $fields, true ) ) {
			/** @var TaskAttachment[] $attachments */
			$attachments = ( new TaskAttachmentCollection( [
				'per_page' => - 1,
				'where'    => [
					[
						'key'   => 'task_id',
						'value' => $old_task_id,
					],
				],
			] ) )->get_results();
			foreach ( $attachments as $attachment ) {
				$attachment->set_task_id( $task_id );
				$attachment->set_id( 0 );
				$attachment->save();
			}
		}

		if ( in_array( 'checklists', $fields, true ) ) {
			/** @var TaskChecklistGroup[] $checklist_groups */
			$checklist_groups = ( new TaskChecklistGroupCollection( [
				'per_page' => - 1,
				'where'    => [
					[
						'key'   => 'card_id',
						'value' => $old_card_id,
					],
				],
			] ) )->get_results();

			$checklist_groups_map = [];
			foreach ( $checklist_groups as $checklist_group ) {
				$old_checklist_group_id = $checklist_group->get_id();
				$checklist_group->set_card_id( $card->get_id() );
				$checklist_group->set_id( 0 );
				$checklist_group->save();
				$checklist_groups_map[ $old_checklist_group_id ] = $checklist_group->get_id();
			}

			$checklists = ( new TaskChecklistCollection( [
				'per_page' => - 1,
				'where'    => [
					[
						'key'   => 'card_id',
						'value' => $old_card_id,
					],
				],
			] ) )->get_results();
			foreach ( $checklists as $checklist ) {
				$checklist->set_card_id( $card->get_id() );
				$checklist->set_checklist_group_id( $checklist_groups_map[ $checklist->get_checklist_group_id() ] ?? 0 );
				$checklist->set_id( 0 );
				$checklist->save();
			}
		}

		wp_send_json_success( $this->get_card_data( $card ) );
	}

	public function archive_card( $request ) {
		$card_id = $request['card_id'] ?? 0;

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

		$card = Helper::get_card( $card_id );
		if ( ! $card ) {
			wp_send_json_error( [
				'message' => __( 'Invalid card id.', 'gemboards' ),
			] );
		}
		$card->set_archived( true );
		$result = $card->save();
		if ( is_wp_error( $result ) ) {
			wp_send_json_error( [
				'message' => $result->get_error_message(),
			] );
		}
		do_action( 'gemboards/card/archived', $card );
		wp_send_json_success( $this->get_card_data( $card ) );
	}

	public function restore_card( array $payload ) {
		$card_id = $payload['card_id'] ?? 0;

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

		$card = Helper::get_card( $card_id );
		if ( ! $card ) {
			wp_send_json_error( [
				'message' => __( 'Invalid card id.', 'gemboards' ),
			] );
		}
		$card->set_archived( false );
		$result = $card->save();
		if ( is_wp_error( $result ) ) {
			wp_send_json_error( [
				'message' => $result->get_error_message(),
			] );
		}
		do_action( 'gemboards/card/restored', $card );
		wp_send_json_success( $this->get_card_data( $card ) );
	}

	public function bulk_restore_cards( array $payload ) {
		if ( empty( $payload['board_id'] ) ) {
			wp_send_json_error( [
				'message' => __( 'Board ID is required.', 'gemboards' ),
			] );
		}

		if ( empty( $payload['card_ids'] ) ) {
			wp_send_json_error( [
				'message' => __( 'Card IDs are required.', 'gemboards' ),
			] );
		}

		$card_ids = explode( ',', $payload['card_ids'] );
		$card_ids = array_map( 'trim', $card_ids );
		$card_ids = array_filter( $card_ids );
		if ( empty( $card_ids ) ) {
			wp_send_json_error( [
				'message' => __( 'Invalid card ids.', 'gemboards' ),
			] );
		}

		try {
			/** @var \GemBoards\Entities\Card[] $cards */
			$cards     = ( new Cardcollection( [
				'per_page' => - 1,
				'where'    => [
					[
						'key'     => 'id',
						'value'   => $card_ids,
						'compare' => 'IN',
					],
					[
						'key'   => 'board_id',
						'value' => $payload['board_id'],
					],
					[
						'key'   => 'archived',
						'value' => 1,
					],
				],
			] ) )->get_results();
			$card_data = [];
			foreach ( $cards as $card ) {
				$card->set_archived( false );
				$result = $card->save();
				if ( is_wp_error( $result ) ) {
					wp_send_json_error( [
						'message' => $result->get_error_message(),
					] );
				}
				do_action( 'gemboards/card/restored', $card );
				$card_data[] = $this->get_card_data( $card );
			}
			wp_send_json_success( $card_data );
		} catch ( GemboardsInvalidArgumentException $e ) {
			Helper::error_log( $e->getMessage() );
			wp_send_json_error( [
				'message' => $e->getMessage(),
			] );
		}
	}

	public function assign_card_users( $request ) {
		$card_id = (int) $request['card_id'] ?? 0;
		$user_id = (int) $request['user_id'] ?? 0;

		$result = $this->assign_user_in_card( $user_id, $card_id );
		if ( is_wp_error( $result ) ) {
			wp_send_json_error( [
				'message' => $result->get_error_message(),
			] );
		}

		$user = get_user( $user_id );
		wp_send_json_success( [
			'id'     => $user->ID,
			'name'   => $user->display_name,
			'avatar' => get_avatar_url( $user->ID ),
		] );
	}

	private function assign_user_in_card( int $user_id, int $card_id ) {
		if ( empty( $card_id ) || empty( $user_id ) ) {
			return new WP_Error( 'invalid_request', __( 'Card ID and user_id integer are required.', 'gemboards' ) );
		}

		$has_assigned = Helper::get_user_assignee( $card_id, $user_id );
		if ( $has_assigned ) {
			return true;
		}

		$card = Helper::get_card( $card_id );
		if ( ! $card ) {
			return new WP_Error( 'invalid_card_id', __( 'Invalid card id', 'gemboards' ) );
		}

		$card_assignee = new CardAssignee();
		$card_assignee->set_card_id( $card_id );
		$card_assignee->set_user_id( $user_id );
		$result = $card_assignee->save();
		if ( is_wp_error( $result ) ) {
			/** @var WP_Error $result */
			return $result;
		}

		return true;
	}

	public function remove_card_users( $request ) {
		$card_id = (int) $request['card_id'] ?? 0;
		$user_id = (int) $request['user_id'] ?? 0;

		if ( empty( $card_id ) || empty( $user_id ) ) {
			wp_send_json_error( [ 'message' => __( 'Card ID and user_id integer are required.', 'gemboards' ) ] );
		}

		$assignee = Helper::get_user_assignee( $card_id, $user_id );
		if ( ! $assignee ) {
			wp_send_json_error( [
				'message' => __( "User didn't assigned with selected card.", 'gemboards' ),
			] );
		}

		try {
			$assignee->delete();
			wp_send_json_success( [
				'message' => __( 'Users removed successfully.', 'gemboards' ),
				'user_id' => $user_id,
			] );
		} catch ( GemboardsException $e ) {
			wp_send_json_error( [
				'message' => __( 'Failed to delete card assignee!', 'gemboards' ),
			] );
		}
	}

	public function get_card_assignees( $request ) {
		$card_id = $request['card_id'] ?? 0;

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

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

		$user_ids = array_map( fn( $assignee ) => $assignee->get_user_id(), $card->get_assignees() );
		wp_send_json_success( [ 'user_ids' => $user_ids ] );
	}

	public function delete_card( $request ) {
		$card_id = $request['card_id'] ?? 0;

		if ( empty( $card_id ) ) {
			wp_send_json_error( [
				'message' => 'Card ID is required.',
			] );
		}

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

		try {
			$card->delete();
			wp_send_json_success( [ 'message' => __( 'Card deleted successfully.', 'gemboards' ) ] );
		} catch ( GemboardsException $e ) {
			wp_send_json_error( [ 'message' => __( 'Failed to delete card.', 'gemboards' ) ] );
		}
	}

	public function bulk_delete_cards( array $payload ) {
		if ( empty( $payload['board_id'] ) ) {
			wp_send_json_error( [
				'message' => __( 'Board ID is required.', 'gemboards' ),
			] );
		}
		if ( empty( $payload['card_ids'] ) ) {
			wp_send_json_error( [
				'message' => __( 'Card IDs are required.', 'gemboards' ),
			] );
		}

		$card_ids = explode( ',', $payload['card_ids'] );
		$card_ids = array_map( 'trim', $card_ids );
		$card_ids = array_filter( $card_ids );
		if ( empty( $card_ids ) ) {
			wp_send_json_error( [
				'message' => __( 'Invalid card ids.', 'gemboards' ),
			] );
		}

		try {
			/** @var \GemBoards\Entities\Card[] $cards */
			$cards = ( new Cardcollection( [
				'per_page' => - 1,
				'where'    => [
					[
						'key'     => 'id',
						'value'   => $card_ids,
						'compare' => 'IN',
					],
					[
						'key'   => 'board_id',
						'value' => $payload['board_id'],
					],
					[
						'key'   => 'archived',
						'value' => 1,
					],
				],
			] ) )->get_results();
			foreach ( $cards as $card ) {
				try {
					$card->delete();
					do_action( 'gemboards/card/deleted', $card->get_id() );
				} catch ( GemboardsException $e ) {
					Helper::error_log( $e->getMessage() );
				}
			}
			wp_send_json_success( [ 'message' => __( 'Card deleted successfully.', 'gemboards' ) ] );
		} catch ( GemboardsInvalidArgumentException $e ) {
			Helper::error_log( $e->getMessage() );
			wp_send_json_error( [
				'message' => $e->getMessage(),
			] );
		}
	}

	private function get_card_data( \GemBoards\Entities\Card $card ): array {
		$attachments = array_map( function ( $attachment ) {
			return [
				'id'        => $attachment->get_id(),
				'file_url'  => $attachment->get_file_url(),
				'file_name' => $attachment->get_file_name(),
				'file_type' => $attachment->get_file_type(),
				'file_size' => $attachment->get_file_size(),
				'date'      => $attachment->get_date_created_at(),
			];
		}, $card->get_attachments() );

		$labels      = get_the_terms( $card->get_task_id(), GEMBOARDS_PLUGIN_SLUG . '_label' ) ?: [];
		$labels_data = array_map( function ( $term ) {
			return [
				'id'         => (int) $term->term_id,
				'name'       => $term->name,
				'slug'       => $term->slug,
				'bg_color'   => get_term_meta( $term->term_id, 'bg_color', true ) ?: '#cccccc',
				'text_color' => get_term_meta( $term->term_id, 'text_color', true ) ?: '#000000',
			];
		}, $labels );
		$task        = $card->get_task();

		$card_author = get_user( $card->get_task()->post_author );

		return array_merge( $card->get_data(), [
			'id'          => $card->get_id(),
			'title'       => $task->post_title,
			'description' => $task->post_content,
			'attachments' => $attachments,
			'labels'      => $labels_data,
			'due_date'    => $card->get_due_date() ? $card->get_due_date()->format( 'Y-m-d' ) : null,
			'updated_at'  => $card->get_date_updated() ? $card->get_date_updated()->format( 'Y-m-d H:i:s' ) : null,
			'created_by'  => [
				'display_name' => $card_author->display_name,
				'username'     => $card_author->user_login,
				'avatar'       => get_avatar_url( $card_author->ID ),
				'id'           => $card_author->ID,
			],
		] );
	}
}
