<?php
/**
 * Kanban task buckets + drag-and-drop moves (Dashboard → Alerts).
 */
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

if ( ! function_exists( 'newsai_task_resolve_due_ts' ) ) {
	/**
	 * @param object $row Alert row.
	 * @return int Unix timestamp (site TZ semantics, same as legacy kanban).
	 */
	function newsai_task_resolve_due_ts( $row, $now_time = null ) {
		if ( $now_time === null ) {
			$now_time = (int) strtotime( gmdate( 'Y-m-d' ) );
		} else {
			$now_time = (int) $now_time;
		}
		$t_year  = (int) $row->year > 0 ? (int) $row->year : (int) gmdate( 'Y' );
		$t_month = (int) $row->month > 0 ? (int) $row->month : (int) gmdate( 'm' );
		$t_day   = max( 1, (int) $row->day );
		$task_time = strtotime( sprintf( '%04d-%02d-%02d', $t_year, $t_month, $t_day ) );
		if ( ! $task_time ) {
			return (int) strtotime( gmdate( 'Y-m-d' ) );
		}
		if ( (int) $row->year === 0 && (int) $row->month > 0 ) {
			if ( ( $now_time - $task_time ) > ( 15 * DAY_IN_SECONDS ) ) {
				$t_year++;
				$task_time = strtotime( sprintf( '%04d-%02d-%02d', $t_year, $t_month, $t_day ) );
			}
		} elseif ( (int) $row->year === 0 && (int) $row->month === 0 ) {
			if ( ( $now_time - $task_time ) > ( 5 * DAY_IN_SECONDS ) ) {
				$t_month++;
				if ( $t_month > 12 ) {
					$t_month = 1;
					$t_year++;
				}
				$task_time = strtotime( sprintf( '%04d-%02d-%02d', $t_year, $t_month, $t_day ) );
			}
		}
		return (int) $task_time;
	}
}

if ( ! function_exists( 'newsai_task_kanban_bucket' ) ) {
	/**
	 * @param object $row        Alert row.
	 * @param bool   $has_status Whether status column exists.
	 * @param int    $now_time   Today midnight timestamp.
	 * @return string overdue|due-soon|scheduled|done
	 */
	function newsai_task_kanban_bucket( $row, $has_status, $now_time ) {
		if ( $has_status && isset( $row->status ) && $row->status === 'done' ) {
			return 'done';
		}
		$task_time = newsai_task_resolve_due_ts( $row, $now_time );
		$diff_days = ( $task_time - (int) $now_time ) / 86400;
		$lead      = max( 1, (int) ( $row->lead_days ?? 7 ) );
		if ( $diff_days < 0 ) {
			return 'overdue';
		}
		if ( $diff_days <= $lead ) {
			return 'due-soon';
		}
		return 'scheduled';
	}
}

if ( ! function_exists( 'newsai_task_kanban_move' ) ) {
	/**
	 * Move task to a kanban column by adjusting due date / status.
	 *
	 * @param int    $task_id Task ID.
	 * @param string $column  overdue|due-soon|scheduled|done
	 * @return true|WP_Error
	 */
	function newsai_task_kanban_move( $task_id, $column ) {
		global $wpdb;

		$task_id = (int) $task_id;
		$column  = sanitize_key( (string) $column );
		$allowed = [ 'overdue', 'due-soon', 'scheduled', 'done' ];
		if ( ! in_array( $column, $allowed, true ) ) {
			return new WP_Error( 'invalid_column', 'invalid_column' );
		}

		$table = $wpdb->prefix . 'newsai_alerts';
		$row   = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$table} WHERE id = %d", $task_id ) );
		if ( ! $row ) {
			return new WP_Error( 'not_found', 'not_found' );
		}

		if ( ! function_exists( 'newsai_task_can_access' ) || ! newsai_task_can_access( $task_id ) ) {
			return new WP_Error( 'forbidden', 'forbidden' );
		}

		$cols = $wpdb->get_col( "DESC {$table}", 0 );
		$has_status = is_array( $cols ) && in_array( 'status', $cols, true );

		$now_ts = (int) strtotime( gmdate( 'Y-m-d' ) );
		$data   = [];

		if ( 'done' === $column ) {
			if ( $has_status ) {
				$data['status'] = 'done';
			}
		} else {
			if ( $has_status ) {
				$data['status'] = 'pending';
			}
			$lead = max( 1, (int) ( $row->lead_days ?? 7 ) );
			if ( 'overdue' === $column ) {
				$due_ts = $now_ts - DAY_IN_SECONDS;
			} elseif ( 'due-soon' === $column ) {
				$due_ts = $now_ts + ( 2 * DAY_IN_SECONDS );
				$lead   = max( $lead, 7 );
				$data['lead_days'] = $lead;
			} else {
				$due_ts = $now_ts + ( 14 * DAY_IN_SECONDS );
			}
			$data['day']   = (int) gmdate( 'd', $due_ts );
			$data['month'] = (int) gmdate( 'm', $due_ts );
			$data['year']  = (int) gmdate( 'Y', $due_ts );
		}

		if ( empty( $data ) ) {
			return new WP_Error( 'noop', 'noop' );
		}

		$updated = $wpdb->update( $table, $data, [ 'id' => $task_id ] );
		if ( false === $updated ) {
			return new WP_Error( 'db_error', 'db_error' );
		}

		if ( function_exists( 'nros_clear_task_transients' ) ) {
			nros_clear_task_transients();
		}
		if ( function_exists( 'newsai_invalidate_task_due_metrics_cache' ) ) {
			newsai_invalidate_task_due_metrics_cache();
		}
		if ( function_exists( 'newsai_pro_invalidate_author_performance' ) ) {
			newsai_pro_invalidate_author_performance();
		}

		if ( 'done' === $column ) {
			do_action( 'newsai_task_completed', $task_id, (int) get_current_user_id() );
		} else {
			do_action( 'newsai_task_assigned', $task_id, false, (int) $row->author_id );
		}

		return true;
	}
}

if ( ! function_exists( 'newsai_ajax_kanban_move_task' ) ) {
	function newsai_ajax_kanban_move_task() {
		check_ajax_referer( 'newsai_ajax_nonce', 'nonce' );
		if ( ! current_user_can( 'edit_posts' ) ) {
			wp_send_json_error( [ 'message' => 'forbidden' ], 403 );
		}
		$task_id = isset( $_POST['task_id'] ) ? (int) $_POST['task_id'] : 0;
		$column  = isset( $_POST['column'] ) ? sanitize_key( (string) wp_unslash( $_POST['column'] ) ) : '';
		if ( $task_id < 1 || $column === '' ) {
			wp_send_json_error( [ 'message' => 'invalid_request' ], 400 );
		}
		$res = newsai_task_kanban_move( $task_id, $column );
		if ( is_wp_error( $res ) ) {
			wp_send_json_error( [ 'message' => $res->get_error_code() ], 400 );
		}
		wp_send_json_success( [ 'task_id' => $task_id, 'column' => $column ] );
	}
}
add_action( 'wp_ajax_newsai_kanban_move_task', 'newsai_ajax_kanban_move_task' );

if ( ! function_exists( 'newsai_ajax_kanban_bulk_move' ) ) {
	/**
	 * Move several tasks to one column in a single request (Kanban bulk actions).
	 * Per-task access is still enforced inside newsai_task_kanban_move().
	 */
	function newsai_ajax_kanban_bulk_move() {
		check_ajax_referer( 'newsai_ajax_nonce', 'nonce' );
		if ( ! current_user_can( 'edit_posts' ) ) {
			wp_send_json_error( [ 'message' => 'forbidden' ], 403 );
		}
		$column   = isset( $_POST['column'] ) ? sanitize_key( (string) wp_unslash( $_POST['column'] ) ) : '';
		$ids_raw  = isset( $_POST['task_ids'] ) ? (array) wp_unslash( $_POST['task_ids'] ) : [];
		$task_ids = array_values( array_unique( array_filter( array_map( 'intval', $ids_raw ) ) ) );
		if ( $column === '' || empty( $task_ids ) ) {
			wp_send_json_error( [ 'message' => 'invalid_request' ], 400 );
		}
		// Cap batch size to keep a single request bounded.
		$task_ids = array_slice( $task_ids, 0, 100 );
		$moved    = [];
		$failed   = [];
		foreach ( $task_ids as $tid ) {
			$res = newsai_task_kanban_move( $tid, $column );
			if ( is_wp_error( $res ) ) {
				$failed[] = $tid;
			} else {
				$moved[] = $tid;
			}
		}
		wp_send_json_success(
			[
				'moved'  => $moved,
				'failed' => $failed,
				'column' => $column,
			]
		);
	}
}
add_action( 'wp_ajax_newsai_kanban_bulk_move', 'newsai_ajax_kanban_bulk_move' );

if ( ! function_exists( 'newsai_task_kanban_card_html' ) ) {
	/**
	 * @param object $row           Alert row.
	 * @param string $column        Kanban column key.
	 * @param string $all_users_lbl Fallback author label.
	 * @return string
	 */
	function newsai_task_kanban_card_html( $row, $column, $all_users_lbl, $has_status = false, $now_time = null ) {
		$author = get_the_author_meta( 'display_name', (int) $row->author_id );
		if ( $author === '' ) {
			$author = $all_users_lbl;
		}
		$initials = function_exists( 'newsai_dashboard_registry_initials' )
			? newsai_dashboard_registry_initials( $author )
			: '?';
		$status_val = ( $has_status && isset( $row->status ) ) ? (string) $row->status : 'pending';
		$task_time  = newsai_task_resolve_due_ts( $row, $now_time );
		$now_ts     = $now_time !== null ? (int) $now_time : (int) strtotime( gmdate( 'Y-m-d' ) );
		$diff_days  = ( $task_time - $now_ts ) / 86400;
		$keyword    = isset( $row->target_keyword ) ? trim( (string) $row->target_keyword ) : '';
		$seo_tag    = $keyword !== ''
			? '<span class="nros-kanban-card__tag">' . esc_html( $keyword ) . '</span>'
			: '';

		return sprintf(
			'<div class="nros-kanban-card" draggable="true" data-task-id="%1$d" data-kanban-col="%2$s" data-status="%6$s" data-overdue="%7$s" data-today="%8$s" data-unassigned="%9$s">'
			. '<label class="nros-kanban-card__select"><input type="checkbox" class="nros-kanban-check" data-task-id="%1$d" aria-label="%10$s" /></label>'
			. '<strong class="nros-kanban-card__title">%3$s</strong>'
			. '%11$s'
			. '<div class="nros-kanban-meta"><span class="nros-kanban-meta__date">%4$s</span>'
			. '<span class="nros-kanban-meta__author"><span class="nros-kanban-card__avatar" aria-hidden="true">%12$s</span> %5$s</span></div></div>',
			(int) $row->id,
			esc_attr( (string) $column ),
			esc_html( (string) $row->title ),
			esc_html( sprintf( '%02d/%02d', (int) $row->day, (int) $row->month ) ),
			esc_html( (string) $author ),
			esc_attr( $status_val ),
			( $diff_days < 0 ) ? '1' : '0',
			( (int) round( $diff_days ) === 0 ) ? '1' : '0',
			( (int) $row->author_id === 0 ) ? '1' : '0',
			esc_attr__( 'Select task', 'newsroom-ai-assistant' ),
			$seo_tag,
			esc_html( $initials )
		);
	}
}

if ( ! function_exists( 'newsai_render_kanban_board' ) ) {
	/**
	 * Render four-column kanban board with drag handles.
	 *
	 * @param array|null $rows       Task rows.
	 * @param bool       $has_status Status column present.
	 * @param int        $now_time   Today midnight timestamp.
	 * @param array      $i18n       Dashboard i18n slice.
	 */
	function newsai_render_kanban_board( $rows, $has_status, $now_time, $i18n ) {
		$columns = [
			'overdue'   => (string) ( $i18n['chip_overdue'] ?? __( 'Overdue', 'newsroom-ai-assistant' ) ),
			'due-soon'  => __( 'Due Soon', 'newsroom-ai-assistant' ),
			'scheduled' => __( 'Scheduled', 'newsroom-ai-assistant' ),
			'done'      => (string) ( $i18n['chip_done'] ?? __( 'Done', 'newsroom-ai-assistant' ) ),
		];
		$buckets = array_fill_keys( array_keys( $columns ), [] );
		foreach ( (array) $rows as $row ) {
			$bucket = newsai_task_kanban_bucket( $row, $has_status, $now_time );
			if ( isset( $buckets[ $bucket ] ) ) {
				$buckets[ $bucket ][] = $row;
			}
		}
		$all_users = (string) ( $i18n['all_users'] ?? __( 'All users', 'newsroom-ai-assistant' ) );
		?>
		<div id="nros-kanban-view" class="nros-kanban-panel is-visible">
			<div class="nros-kanban-bulkbar" id="nros-kanban-bulkbar" hidden
				data-selected-template="<?php echo esc_attr__( '%d selected', 'newsroom-ai-assistant' ); ?>">
				<span class="nros-kanban-bulkbar__count" id="nros-kanban-bulk-count" aria-live="polite">0</span>
				<label class="nros-kanban-bulkbar__move">
					<span><?php echo esc_html__( 'Move to', 'newsroom-ai-assistant' ); ?></span>
					<select id="nros-kanban-bulk-col">
						<?php foreach ( $columns as $col_key => $col_label ) : ?>
							<option value="<?php echo esc_attr( $col_key ); ?>"><?php echo esc_html( $col_label ); ?></option>
						<?php endforeach; ?>
					</select>
				</label>
				<button type="button" class="button button-primary" id="nros-kanban-bulk-apply"><?php echo esc_html__( 'Apply', 'newsroom-ai-assistant' ); ?></button>
				<button type="button" class="button-link" id="nros-kanban-bulk-clear"><?php echo esc_html__( 'Clear', 'newsroom-ai-assistant' ); ?></button>
			</div>
			<div class="nros-kanban">
				<?php foreach ( $columns as $col_key => $col_label ) : ?>
					<div class="nros-kanban-col" data-kanban-col="<?php echo esc_attr( $col_key ); ?>">
						<div class="nros-kanban-head nros-kanban-head--<?php echo esc_attr( $col_key ); ?>">
							<span class="nros-kanban-head__dot" aria-hidden="true"></span>
							<span class="nros-kanban-head__label"><?php echo esc_html( $col_label ); ?></span>
							<span class="nros-kanban-head__count"><?php echo (int) count( $buckets[ $col_key ] ); ?></span>
						</div>
						<div class="nros-kanban-body" data-kanban-drop="<?php echo esc_attr( $col_key ); ?>">
							<?php
							if ( empty( $buckets[ $col_key ] ) ) {
								echo '<p class="nros-kanban-empty">' . esc_html__( 'No tasks', 'newsroom-ai-assistant' ) . '</p>';
							}
							foreach ( $buckets[ $col_key ] as $row ) {
								echo newsai_task_kanban_card_html( $row, $col_key, $all_users, $has_status, $now_time ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
							}
							?>
						</div>
					</div>
				<?php endforeach; ?>
			</div>
		</div>
		<?php
	}
}
