<?php

namespace Gigneo;

use WP_Query;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Class Jobs
 *
 * Plugin Jobs class for Gigneo.
 *
 * @since 0.0.1
 */
class Jobs {

	/**
	 * The single instance of the class.
	 *
	 * @var Jobs|null
	 * @since 0.0.1
	 */
	private static $instance = null;

	/**
	 * Constructor for the class.
	 *
	 * @since 0.0.1
	 */
	public function __construct() {

		//Save job via AJAX
		add_action( 'wp_ajax_gigneo_save_job', array( $this, 'save_job' ) );

		//Duplicate job via AJAX
		add_action( 'wp_ajax_gigneo_job_clone', array( $this, 'job_clone' ) );

		// Approve job
		add_action( 'wp_ajax_gigneo_approve_job', array( $this, 'approve_job' ) );

		// Reject job
		add_action( 'wp_ajax_gigneo_reject_job', array( $this, 'reject_job' ) );

		//Remove job
		add_action( 'wp_ajax_gigneo_remove_job', array( $this, 'remove_job' ) );

		//Featured job
		add_action( 'wp_ajax_gigneo_featured_job', array( $this, 'featured_job' ) );

		//Draft Job
		add_action( 'wp_ajax_gigneo_draft_job', array( $this, 'draft_job' ) );

		//Update job status
		add_action( 'wp_ajax_gigneo_pause_active_job', array( $this, 'pause_active_job' ) );

		//Publish Job
		add_action( 'wp_ajax_gigneo_publish_job', array( $this, 'publish_job' ) );

		//Job Approve Action
		add_action( 'gigneo_post_type_actions', array( $this, 'post_type_actions' ), 10, 3 );

		//Job Proposal overview
		add_action( 'gigneo_post_type_actions', array( $this, 'proposal_post_type_actions' ), 10, 3 );

		//Job Reject Markup
		add_action( 'admin_footer', array( $this, 'reject_job_markup' ) );

		//Menu Counter
		add_action( 'admin_menu', array( $this, 'menu_counter' ) );
	}

	/**
	 * Ensures only one instance of the class is loaded or can be loaded.
	 *
	 * @return Jobs
	 * @since 0.0.1
	 */
	public static function instance() {
		if ( is_null( self::$instance ) ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Menu counter.
	 *
	 * @since 0.0.1
	 */
	public function menu_counter() {

		global $submenu;
		$counts  = wp_count_posts( 'gigneo_job' );
		$pending = isset( $counts->{'pending'} ) ? (int) $counts->{'pending'} : 0;

		if ( $pending <= 0 || ! isset( $submenu['gigneo'] ) ) {
			return;
		}

		foreach ( $submenu['gigneo'] as $key => $item ) {
			if ( isset( $item[2] ) && 'edit.php?post_type=gigneo_job' === $item[2] ) {
				// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
				$submenu['gigneo'][ $key ][0] .= sprintf(
					' <span class="update-plugins count-%1$d"><span class="plugin-count">%1$d</span></span>',
					esc_html( $pending )
				);
				break;
			}
		}
	}

	/**
	 * Job clone.
	 *
	 * @since 0.0.1
	 */
	public function job_clone() {

		// Verify security nonce
		$security = isset( $_POST['security'] ) ? sanitize_text_field( wp_unslash( $_POST['security'] ) ) : '';
		if ( empty( $security ) || ! wp_verify_nonce( $security, 'gigneo_security' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security verification failed. Please reload and try again.', 'gigneo' ) ), 403 );
		}

		// Get current user and active profile
		$profile_id   = gigneo_active_profile_id();
		$current_user = wp_get_current_user();

		if ( empty( $current_user->ID ) || empty( $profile_id ) ) {
			wp_send_json_error(
				array( 'message' => esc_html__( 'You do not have permission to do that.', 'gigneo' ) ),
				403
			);
		}

		// Retrieve and sanitize the original job ID
		$original_id = isset( $_POST['id'] ) ? absint( wp_unslash( $_POST['id'] ) ) : 0;

		if ( empty( $original_id ) ) {
			wp_send_json_error(
				array( 'message' => esc_html__( 'Please select a job', 'gigneo' ) ),
				400
			);
		}

		// Verify the user owns the job
		if ( ! gigneo_validate_post_author( $original_id ) ) {
			wp_send_json_error(
				array( 'message' => esc_html__( 'You do not have permission to do that.', 'gigneo' ) ),
				403
			);
		}

		// Load the original post object
		$original_post = get_post( $original_id );

		if ( ! $original_post || 'gigneo_job' !== $original_post->post_type ) {
			wp_send_json_error(
				array( 'message' => esc_html__( 'Job not found.', 'gigneo' ) ),
				404
			);
		}

		// Enforce creation conditions (profile image, email, identity)
		$this->validate_job_creation_conditions( $profile_id, $current_user->ID );

		// Enforce creation limit (how many jobs the user may have)
		$this->validate_job_creation_limit( $current_user->ID );

		// Create the new draft post (duplicate core fields)
		$new_post_args = array(
			'post_type'    => 'gigneo_job',
			'post_title'   => $original_post->post_title . ' (Copy)',
			'post_content' => $original_post->post_content,
			'post_status'  => 'draft',
			'post_author'  => $current_user->ID,
		);

		$new_job_id = wp_insert_post( $new_post_args );

		if ( is_wp_error( $new_job_id ) || empty( $new_job_id ) ) {
			wp_send_json_error(
				array( 'message' => esc_html__( 'Failed to duplicate job.', 'gigneo' ) ),
				400
			);
		}

		// Duplicate taxonomies (facets & tags)
		$taxonomies = array( 'gigneo_facet', 'gigneo_skill' );

		foreach ( $taxonomies as $taxonomy ) {
			$terms = wp_get_object_terms( $original_id, $taxonomy, array( 'fields' => 'ids' ) );
			if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) {
				wp_set_object_terms( $new_job_id, $terms, $taxonomy );
			}
		}

		// Duplicate ALL meta fields automatically (no key list)
		global $wpdb;
		// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$all_meta = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id = %d", $original_id ), ARRAY_A );
		// phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching

		if ( $all_meta ) {
			foreach ( $all_meta as $meta ) {
				$key   = $meta['meta_key'];
				$value = maybe_unserialize( $meta['meta_value'] );

				// Skip metas
				if ( in_array(
						$key,
						array(
							'_edit_lock',
							'_edit_last',
							'_gigneo_pm_status',
							'_gigneo_pm_credit_invoice_id',
							'_gigneo_pm_manual_approval_info',
							'_gigneo_pm_featured',
						),
						true
					)
				) {
					continue;
				}

				// Copy every other meta field
				update_post_meta( $new_job_id, $key, $value );
			}
		}

		// Duplicate featured image
		$thumbnail_id = get_post_thumbnail_id( $original_id );
		if ( $thumbnail_id ) {
			set_post_thumbnail( $new_job_id, $thumbnail_id );
		}

		$response['message']      = esc_html__( 'Job cloned successfully.', 'gigneo' );
		$response['redirect_url'] = gigneo_dashboard_url( 'job', 'edit', array( 'p_id' => $new_job_id ) );

		// Send JSON success
		wp_send_json_success( $response, 200 );
	}

	/**
	 * Validate job creation conditions.
	 *
	 * @since 0.0.1
	 */
	public function validate_job_creation_conditions( $profile_id, $user_id ) {

		if ( empty( $profile_id ) || empty( $user_id ) ) {
			return;
		}

		$creation_conditions = gigneo_option( '_gigneo_ts_job_creation_conditions' );

		if ( empty( $creation_conditions ) && ! is_array( $creation_conditions ) ) {
			return;
		}

		//Profile Image
		if ( in_array( 'profile_image', $creation_conditions, true ) ) {
			if ( empty( get_post_thumbnail_id( $profile_id ) ) ) {
				wp_send_json_error(
					array( 'message' => esc_html__( 'To continue, please upload a profile image first', 'gigneo' ) ),
					403
				);
			}
		}

		//Email Verification
		if ( in_array( 'email_verified', $creation_conditions, true ) && in_array( 'email_verification', gigneo_active_modules(), true ) ) {
			$email_verified = get_user_meta( $user_id, '_gigneo_um_email_verified', true );

			if ( empty( $email_verified ) ) {
				wp_send_json_error(
					array( 'message' => esc_html__( 'Please verify your email address before creating a job', 'gigneo' ) ),
					403
				);
			}
		}

		//Identity Verification
		do_action( 'gigneo_validate_job_creation_conditions', $creation_conditions, $profile_id, $user_id );
	}

	/**
	 * Validate job creation limit.
	 *
	 * @since 0.0.1
	 */
	private function validate_job_creation_limit( $user_id ) {

		if ( empty( $user_id ) ) {
			return;
		}

		$limit = gigneo_option( '_gigneo_ts_job_creation_limit' );

		if ( empty( $limit ) ) {
			return;
		}

		$query = new WP_Query(
			array(
				'post_type'      => 'gigneo_job',
				'author'         => $user_id,
				'post_status'    => 'any',
				'posts_per_page' => -1,
				'fields'         => 'ids',
			)
		);

		// Check if limit exceeded.
		if ( $query->post_count >= $limit ) {
			wp_send_json_error(
				array(
					'message' => esc_html__( 'You have reached the maximum number of jobs allowed.', 'gigneo' ),
				),
				403
			);
		}
	}

	/**
	 * Approve job.
	 *
	 * @since 0.0.1
	 */
	public function approve_job() {

		// Check if nonce is valid
		$security = isset( $_POST['security'] ) ? sanitize_text_field( wp_unslash( $_POST['security'] ) ) : '';
		if ( empty( $security ) || ! wp_verify_nonce( $security, 'gigneo_security' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security verification failed. Please reload and try again.', 'gigneo' ) ), 403 );
		}

		// Check if the user has permission to edit settings (usually admin)
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to do that.', 'gigneo' ) ), 403 );
		}

		// Parse serialized data manually
		$id = isset( $_POST['id'] ) ? absint( wp_unslash( $_POST['id'] ) ) : 0;

		if ( empty( $id ) || 'gigneo_job' !== get_post_type( $id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Something went wrong.', 'gigneo' ) ), 409 );
		}

		update_post_meta( $id, '_gigneo_pm_status', 'publish' );

		$manual_approval_data           = gigneo_post_meta( $id, '_gigneo_pm_manual_approval_info' );
		$manual_approval_data['status'] = 'approved';

		update_post_meta( $id, '_gigneo_pm_manual_approval_info', $manual_approval_data );

		wp_update_post(
			array(
				'ID'          => $id,
				'post_status' => 'publish',
			)
		);

		$job_author = get_post_field( 'post_author', $id );
		$profile_id = gigneo_profile_id( $job_author, 'employer' );

		//Approved job Notification
		$approved_job_nf_title   = esc_html__( 'Job approved', 'gigneo' );
		$approved_job_nf_content = sprintf(
			// translators: 1: Job Title, 2: Profile Name
			esc_html__( 'Hey %1$s, Your job "%2$s" has been approved.', 'gigneo' ),
			gigneo_profile_name( $profile_id ),
			get_the_title( $id )
		);
		Notifications::trigger_notification( $approved_job_nf_title, $approved_job_nf_content, 'job', 'job_approved', $profile_id, $id );

		$wc_mailer = WC()->mailer();
		$wc_emails = $wc_mailer->get_emails();

		if ( ! empty( $wc_emails['Gigneo_Job_Approved'] ) ) {
			$wc_emails['Gigneo_Job_Approved']->trigger( $profile_id, $id );
		}

		$response            = array();
		$response['message'] = esc_html__( 'Job has been approved successfully.', 'gigneo' );

		wp_send_json_success( $response, 200 );
	}

	/**
	 * Reject job.
	 *
	 * @since 0.0.1
	 */
	public function reject_job() {

		// Check if nonce is valid
		$security = isset( $_POST['security'] ) ? sanitize_text_field( wp_unslash( $_POST['security'] ) ) : '';
		if ( empty( $security ) || ! wp_verify_nonce( $security, 'gigneo_security' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security verification failed. Please reload and try again.', 'gigneo' ) ), 403 );
		}

		// Check if the user has permission to edit settings (usually admin)
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to do that.', 'gigneo' ) ), 403 );
		}

		$id      = isset( $_POST['job_id'] ) ? absint( wp_unslash( $_POST['job_id'] ) ) : 0;
		$type    = isset( $_POST['rejection_type'] ) ? sanitize_text_field( wp_unslash( $_POST['rejection_type'] ) ) : '';
		$detail  = isset( $_POST['rejection_detail'] ) ? sanitize_textarea_field( wp_unslash( $_POST['rejection_detail'] ) ) : '';
		$changes = isset( $_POST['request_changes'] ) ? sanitize_textarea_field( wp_unslash( $_POST['request_changes'] ) ) : '';

		if ( empty( $id ) || empty( $type ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Something went wrong.', 'gigneo' ) ), 409 );
		}

		if ( 'soft' !== $type && 'hard' !== $type ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Rejection type required.', 'gigneo' ) ), 409 );
		}

		if ( 'soft' === $type && empty( $changes ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Required field could not be empty.', 'gigneo' ) ), 409 );
		}

		if ( 'hard' === $type && empty( $detail ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Required field could not be empty.', 'gigneo' ) ), 409 );
		}

		$pm_status = gigneo_post_meta( $id, '_gigneo_pm_status' );

		if ( 'pending' !== $pm_status ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to do this.', 'gigneo' ) ), 403 );
		}

		$post_author_id    = get_post_field( 'post_author', $id );
		$author_profile_id = gigneo_active_profile_id( $post_author_id );

		$manual_approval_data = gigneo_post_meta( $id, '_gigneo_pm_manual_approval_info' );

		$manual_approval_data['status']              = 'rejected';
		$manual_approval_data['rejection']['type']   = $type;
		$manual_approval_data['rejection']['detail'] = 'soft' === $type ? $changes : $detail;

		update_post_meta( $id, '_gigneo_pm_status', 'rejected' );
		update_post_meta( $id, '_gigneo_pm_manual_approval_info', $manual_approval_data );

		wp_update_post(
			array(
				'ID'          => $id,
				'post_status' => 'rejected',
			)
		);

		if ( 'hard' === $type ) {
			wp_trash_post( $id );
		}
		//Reject job Notification
		$reject_job_nf_title   = esc_html__( 'Job rejected', 'gigneo' );
		$reject_job_nf_content = sprintf(
			// translators: 1: Job Title, 2: Profile Name
			esc_html__( 'Hey %1$s, Your job "%2$s" has been hard rejected and no longer available.', 'gigneo' ),
			gigneo_profile_name( $author_profile_id ),
			get_the_title( $id )
		);

		if ( 'soft' === $type ) {
			//Reject job Notification
			$reject_job_nf_title   = esc_html__( 'Job rejected', 'gigneo' );
			$reject_job_nf_content = sprintf(
				// translators: 1: Job Title, 2: Profile Name
				esc_html__( 'Hey %1$s, Your job "%2$s" has been soft rejected. Please review and update the job details to resubmit for approval.', 'gigneo' ),
				gigneo_profile_name( $author_profile_id ),
				get_the_title( $id )
			);

		}
		Notifications::trigger_notification( $reject_job_nf_title, $reject_job_nf_content, 'job', 'job_rejected', $author_profile_id, $id );

		$wc_mailer = WC()->mailer();
		$wc_emails = $wc_mailer->get_emails();
		if ( isset( $wc_emails['Gigneo_Job_Rejected'] ) ) {
			$wc_emails['Gigneo_Job_Rejected']->trigger( $author_profile_id, $id, $type );
		}

		$response            = array();
		$response['message'] = esc_html__( 'Job has been rejected successfully.', 'gigneo' );

		wp_send_json_success( $response, 200 );
	}

	/**
	 * Remove job.
	 *
	 * @since 0.0.1
	 */
	public function remove_job() {

		// Check if nonce is valid
		$security = isset( $_POST['security'] ) ? sanitize_text_field( wp_unslash( $_POST['security'] ) ) : '';
		if ( empty( $security ) || ! wp_verify_nonce( $security, 'gigneo_security' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security verification failed. Please reload and try again.', 'gigneo' ) ), 403 );
		}

		$profile_id   = gigneo_active_profile_id();
		$current_user = wp_get_current_user();

		if ( empty( $current_user->ID ) || empty( $profile_id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to do that.', 'gigneo' ) ), 403 );
		}

		// Parse serialized data manually
		$id = isset( $_POST['id'] ) ? absint( wp_unslash( $_POST['id'] ) ) : 0;

		if ( empty( $id ) || ! gigneo_validate_post_author( $id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Please select a job', 'gigneo' ) ), 400 );
		}

		// Get the original job post
		$original_post = get_post( $id );
		if ( ! $original_post || 'gigneo_job' !== $original_post->post_type ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Job not found.', 'gigneo' ) ), 404 );
		}

		// Remove the job post
		$deleted = wp_delete_post( $id, true );

		if ( $deleted ) {
			wp_send_json_success( array( 'message' => esc_html__( 'Job removed successfully.', 'gigneo' ) ), 200 );
		}

		wp_send_json_error( array( 'message' => esc_html__( 'Failed to remove job.', 'gigneo' ) ), 400 );
	}

	/**
	 * Pause active job.
	 *
	 * @since 0.0.1
	 */
	public function pause_active_job() {

		// Check if nonce is valid
		$security = isset( $_POST['security'] ) ? sanitize_text_field( wp_unslash( $_POST['security'] ) ) : '';
		if ( empty( $security ) || ! wp_verify_nonce( $security, 'gigneo_security' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security verification failed. Please reload and try again.', 'gigneo' ) ), 403 );
		}

		$profile_id   = gigneo_active_profile_id();
		$current_user = wp_get_current_user();

		if ( empty( $current_user->ID ) || empty( $profile_id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to do that.', 'gigneo' ) ), 403 );
		}

		if ( empty( $_POST['id'] ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Something went wrong.', 'gigneo' ) ), 400 );
		}

		$id            = absint( wp_unslash( $_POST['id'] ) );
		$validate_post = gigneo_validate_post_author( $id );

		if ( empty( $validate_post ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to do that.', 'gigneo' ) ), 403 );
		}

		// Get the original job post
		$original_post = get_post( $id );

		if ( ! $original_post || 'gigneo_job' !== $original_post->post_type ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Something went wrong.', 'gigneo' ) ), 400 );
		}

		if ( 'publish' !== $original_post->post_status && 'paused' !== $original_post->post_status ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Something went wrong.', 'gigneo' ) ), 400 );
		}

		$status = isset( $_POST['status'] ) ? sanitize_text_field( wp_unslash( $_POST['status'] ) ) : 'paused';

		if ( 'publish' !== $status && 'paused' !== $status ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Something went wrong.', 'gigneo' ) ), 400 );
		}

		// Remove the job post
		$post_data = array(
			'ID'          => $id,
			'post_status' => $status,
		);

		$post_update = wp_update_post( $post_data );

		if ( is_wp_error( $post_update ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Something went wrong.', 'gigneo' ) ), 400 );
		}

		wp_send_json_success( array( 'message' => esc_html__( 'Job status has been updated successfully.', 'gigneo' ) ), 200 );
	}

	/**
	 * Featured job.
	 *
	 * @since 0.0.1
	 */
	public function featured_job() {

		// Check if nonce is valid
		$security = isset( $_POST['security'] ) ? sanitize_text_field( wp_unslash( $_POST['security'] ) ) : '';
		if ( empty( $security ) || ! wp_verify_nonce( $security, 'gigneo_security' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security verification failed. Please reload and try again.', 'gigneo' ) ), 403 );
		}

		$profile_id   = gigneo_active_profile_id();
		$current_user = wp_get_current_user();

		if ( empty( $current_user->ID ) || empty( $profile_id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to do that.', 'gigneo' ) ), 403 );
		}

		$id     = isset( $_POST['id'] ) ? absint( wp_unslash( $_POST['id'] ) ) : 0;
		$action = isset( $_POST['featured'] ) ? intval( $_POST['featured'] ) : 0;

		if ( empty( $id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Please select job', 'gigneo' ) ), 400 );
		}

		if ( ! gigneo_validate_post_author( $id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to do that.', 'gigneo' ) ), 403 );
		}

		if ( 'gigneo_job' !== get_post_type( $id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Job not found.', 'gigneo' ) ), 404 );
		}

        $job_status = get_post_status( $id );

        if ( ! in_array( $job_status, array( 'publish', 'paused' ) ) ) {
            wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to do that.', 'gigneo' ) ), 400 );
        }

		if ( ! $action ) {
			delete_post_meta( $id, '_gigneo_pm_featured' );
			wp_send_json_success( array( 'message' => esc_html__( 'Job featured removed successfully.', 'gigneo' ) ), 200 );
		}

		$featured_limit = gigneo_option( '_gigneo_ts_job_featured_limit', '0' );

		if ( absint( $featured_limit ) < 1 ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You are not allowed to feature jobs.', 'gigneo' ) ), 400 );
		}

        $author_id = get_post_field( 'post_author', $id );

		$featured_count = count(
			get_posts(
				array(
					'post_type'      => 'gigneo_job',
					'post_status'    => 'publish',
                    'author'         => $author_id,
					'posts_per_page' => -1,
					'fields'         => 'ids',
					// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
					'meta_key'       => '_gigneo_pm_featured',
					// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_value
					'meta_value'     => true,
				)
			)
		);

		if ( $featured_count >= $featured_limit ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You have reached the maximum number of featured jobs allowed.', 'gigneo' ) ), 400 );
		}

		update_post_meta( $id, '_gigneo_pm_featured', true );

		wp_send_json_success( array( 'message' => esc_html__( 'Job featured successfully.', 'gigneo' ) ), 200 );
	}

	/**
	 * Draft job.
	 *
	 * @since 0.0.1
	 */
	public function draft_job() {

		// Verify nonce
		$security = isset( $_POST['security'] ) ? sanitize_text_field( wp_unslash( $_POST['security'] ) ) : '';
		if ( empty( $security ) || ! wp_verify_nonce( $security, 'gigneo_security' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security verification failed. Please reload and try again.', 'gigneo' ) ), 403 );
		}

		$current_user = wp_get_current_user();
		$profile_id   = gigneo_active_profile_id();

		if ( empty( $current_user->ID ) || empty( $profile_id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to do that.', 'gigneo' ) ), 403 );
		}

		// Validate post ID
		$id = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : 0;

		if ( ! $id || ! gigneo_validate_post_author( $id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to do that.', 'gigneo' ) ), 400 );
		}

		$post = get_post( $id );

		if ( ! $post || 'gigneo_job' !== $post->post_type ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Job not found.', 'gigneo' ) ), 404 );
		}

		if ( 'draft' === $post->post_status ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Job is already in draft.', 'gigneo' ) ), 409 );
		}

		if ( 'publish' !== $post->post_status ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to do that.', 'gigneo' ) ), 409 );
		}

		$updated = wp_update_post(
			array(
				'ID'          => $id,
				'post_status' => 'draft',
			),
			true
		);

		if ( is_wp_error( $updated ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Failed to update job status.', 'gigneo' ) ), 500 );
		}

		wp_send_json_success( array( 'message' => esc_html__( 'Job moved to draft successfully.', 'gigneo' ) ), 200 );
	}

	/**
	 * Publish job.
	 *
	 * @since 0.0.1
	 */
	public function publish_job() {

		// Security / Nonce verification
		$security = isset( $_POST['security'] ) ? sanitize_text_field( wp_unslash( $_POST['security'] ) ) : '';
		if ( empty( $security ) || ! wp_verify_nonce( $security, 'gigneo_security' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security verification failed. Please reload and try again.', 'gigneo' ) ), 403 );
		}

		// Basic authorization checks
		$profile_id   = gigneo_active_profile_id();
		$current_user = wp_get_current_user();

		if ( empty( $current_user->ID ) || empty( $profile_id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to perform this action.', 'gigneo' ) ), 403 );
		}

		$id = isset( $_POST['id'] ) ? absint( wp_unslash( $_POST['id'] ) ) : 0;

		if ( empty( $id ) || ! gigneo_validate_post_author( $id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to publish this job.', 'gigneo' ) ), 403 );
		}

		$p_status  = get_post_status( $id );
		$pm_status = gigneo_post_meta( $id, '_gigneo_pm_status' );

		if ( 'draft' !== $p_status && 'publish' === $pm_status ) {
			wp_update_post(
				array(
					'ID'          => $id,
					'post_status' => 'publish',
				)
			);
			wp_send_json_error( array( 'message' => esc_html__( 'Job published successfully,', 'gigneo' ) ), 403 );
		}

		$steps_filled = gigneo_post_meta( $id, '_gigneo_pm_steps_filled' );
		$steps_filled = ! empty( $steps_filled ) && is_array( $steps_filled ) ? $steps_filled : array();

		$required_steps = array( 'basic', 'pricing', 'details', 'screening' );

		foreach ( $required_steps as $step ) {
			if ( ! in_array( $step, $steps_filled, true ) ) {
				wp_send_json_error( array( 'message' => esc_html__( 'Please complete all required steps before publishing this job.', 'gigneo' ) ), 403 );
			}
		}

		$creation_type     = gigneo_option( '_gigneo_ts_job_creation_type', 'paid' );
		$creation_credits  = gigneo_option( '_gigneo_ts_job_creation_credits', '10' );
		$manual_approval   = gigneo_option( '_gigneo_ts_job_manually_approve' );
		$available_credits = gigneo_available_credits( $profile_id );

		$mailer = WC()->mailer();
		$emails = $mailer->get_emails();

		$credit_invoice_id = gigneo_post_meta( $id, '_gigneo_pm_credit_invoice_id' );

		if ( 'paid' === $creation_type && empty( $credit_invoice_id ) ) {

			if ( $available_credits < $creation_credits ) {
				wp_send_json_error( array( 'message' => esc_html__( 'Insufficient credit balance.', 'gigneo' ) ), 403 );
			}

			$invoice_id = wp_insert_post(
				array(
					'post_type'   => 'gigneo_invoice',
					'post_status' => 'paid',
					'post_title'  => sprintf(
						// translators: %s is job ID
						esc_html__( 'Credits Spent — %s', 'gigneo' ),
						esc_html( gigneo_format_id( $id, 'job', false ) )
					),
					'post_author' => $current_user->ID,
				)
			);

			if ( is_wp_error( $invoice_id ) ) {
				wp_send_json_error( array( 'message' => esc_html__( 'Something went wrong.', 'gigneo' ) ), 403 );
			}

			update_post_meta( $invoice_id, '_gigneo_pm_profile_id', $profile_id );
			update_post_meta( $invoice_id, '_gigneo_pm_credit', -intval( $creation_credits ) );
			update_post_meta( $invoice_id, '_gigneo_pm_type', 'job_creation' );

			update_post_meta( $id, '_gigneo_pm_credit_invoice_id', $invoice_id );
		}

		wp_update_post(
			array(
				'ID'          => $id,
				'post_status' => $manual_approval ? 'pending' : 'publish',
			)
		);

		if ( empty( $pm_status ) || 'rejected' === $pm_status ) {
			if ( $manual_approval ) {
				//Start Date&Time
				$manual_approval_data = array(
					'status'        => 'pending',
					'submit_at'     => current_time( 'mysql' ),
					'submit_at_gmt' => current_time( 'mysql', 1 ),
				);
				update_post_meta( $id, '_gigneo_pm_manual_approval_info', $manual_approval_data );
			}
			if ( $manual_approval && isset( $emails['Gigneo_Job_Requested'] ) ) {
				$emails['Gigneo_Job_Requested']->trigger( $profile_id, $id );
			} elseif ( isset( $emails['Gigneo_Job_Published'] ) ) {
				$emails['Gigneo_Job_Published']->trigger( $profile_id, $id );
			}
		}
		update_post_meta( $id, '_gigneo_pm_status', $manual_approval ? 'pending' : 'publish' );

		$response['message'] = esc_html__( 'Job published successfully.', 'gigneo' );

		if ( $manual_approval ) {
			$response['message'] = esc_html__( 'Job has been successfully submitted for review.', 'gigneo' );
		}

		wp_send_json_success( $response, 200 );
	}

	/**
	 * Save job.
	 *
	 * @since 0.0.1
	 */
	public function save_job() {

		// Security / Nonce verification
		$security = isset( $_POST['security'] ) ? sanitize_text_field( wp_unslash( $_POST['security'] ) ) : '';
		if ( empty( $security ) || ! wp_verify_nonce( $security, 'gigneo_security' ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Security verification failed. Please reload and try again.', 'gigneo' ) ), 403 );
		}

		// Basic authorization checks
		$profile_id   = gigneo_active_profile_id();
		$current_user = wp_get_current_user();
		$user_id      = $current_user->ID;

		if ( empty( $user_id ) || empty( $profile_id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to perform this action.', 'gigneo' ) ), 403 );
		}

		// Get and sanitize request parameters
		$step = isset( $_POST['step'] ) ? sanitize_text_field( wp_unslash( $_POST['step'] ) ) : '';
		$type = isset( $_POST['type'] ) ? sanitize_text_field( wp_unslash( $_POST['type'] ) ) : '';
		$id   = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : 0;

		// Basic validation
		if ( empty( $type ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Something went wrong.', 'gigneo' ) ), 400 );
		}

		// Permission check when editing existing job
		if ( $id > 0 && ! gigneo_validate_post_author( $id ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to edit this job.', 'gigneo' ) ), 403 );
		}

		// New job → apply creation limits & conditions
		if ( empty( $id ) ) {
			$this->validate_job_creation_limit( $user_id );
			$this->validate_job_creation_conditions( $profile_id, $user_id );
		}

		$steps_filled = gigneo_post_meta( $id, '_gigneo_pm_steps_filled' );
		$steps_filled = ! empty( $steps_filled ) && is_array( $steps_filled ) ? $steps_filled : array();

		//Steps
		if ( 'basic' === $step ) {
			$response = $this->edit_basic_step( $id, $current_user->ID, $steps_filled );
			wp_send_json_success( $response, 200 );
		} elseif ( 'pricing' === $step ) {
			$response = $this->edit_pricing_step( $id, $steps_filled );
			wp_send_json_success( $response, 200 );
		} elseif ( 'details' === $step ) {
			$response = $this->edit_details_step( $id, $steps_filled );
			wp_send_json_success( $response, 200 );
		} elseif ( 'screening' === $step ) {
			$response = $this->edit_screening_step( $id, $steps_filled );
			do_action( 'gigneo_ajax_after_job_screening_save', $_POST, $id );
			wp_send_json_success( $response, 200 );
		}

		//Save as draft
		if ( 'draft' === $type ) {

			if ( 'pending' === get_post_status( $id ) ) {
				wp_send_json_error( array( 'message' => esc_html__( 'You cannot save the job as a draft while it is pending review.', 'gigneo' ) ), 403 );
			}

			wp_update_post(
				array(
					'ID'          => $id,
					'post_status' => 'draft',
				)
			);
		}
	}

	/**
	 * Edit basic step.
	 *
	 * @since 0.0.1
	 */
	public function edit_basic_step( $post_id, $user_id, $steps_filled ) {
		// Define required fields + error messages
		$required_fields = array(
			'job_title'       => esc_html__( 'Title is required.', 'gigneo' ),
			'job_category'    => esc_html__( 'Category is required.', 'gigneo' ),
			'job_subcategory' => esc_html__( 'Subcategory is required.', 'gigneo' ),
			'job_skills'      => esc_html__( 'Skills are required.', 'gigneo' ),
		);

		// job type is required only when platform setting allows both
		if ( gigneo_option( '_gigneo_ts_job_type', 'both' ) === 'both' ) {
			$required_fields['job_type'] = esc_html__( 'Type is required', 'gigneo' );
		}

		// Validate required fields
		foreach ( $required_fields as $required_field => $error_message ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
			if ( empty( $_POST[ $required_field ] ) ) {
				wp_send_json_error( array( 'message' => $error_message ), 422 );
			}
		}

		// Prepare clean title
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
		$title      = isset( $_POST['job_title'] ) ? sanitize_text_field( wp_unslash( $_POST['job_title'] ) ) : '';
		$prefix     = trim( gigneo_option( '_gigneo_ts_job_title_prefix' ) );
		$title      = ! empty( $prefix ) ? $prefix . ' ' . $title : $title;
		$user_id    = ! empty( $user_id ) ? $user_id : get_current_user_id();
		$profile_id = gigneo_active_profile_id( $user_id );

		$post_data = array(
			'post_type'  => 'gigneo_job',
			'post_title' => $title,
			'post_name'  => sanitize_title( $title ),
		);

		if ( $post_id > 0 ) {
			// Update existing job
			$post_data['ID'] = $post_id;
			$result          = wp_update_post( $post_data );

			if ( is_wp_error( $result ) || 0 === $result ) {
				wp_send_json_error( array( 'message' => esc_html__( 'Failed to update job.', 'gigneo' ) ), 500 );
			}
		} else {
			// Create new job
			$post_data['post_status'] = 'draft';
			$post_data['post_author'] = $user_id;

			$post_id = wp_insert_post( $post_data );

			if ( is_wp_error( $post_id ) || 0 === $post_id ) {
				wp_send_json_error( array( 'message' => esc_html__( 'Failed to create job.', 'gigneo' ) ), 500 );
			}

			// update the _gigneo_pm_open_positions for open positions
			update_post_meta( $post_id, '_gigneo_pm_open_positions', '1' );
		}

		// Taxonomy / Facets — sanitize and allowlist against gigneo_facet hierarchy.
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
		$category = isset( $_POST['job_category'] ) ? sanitize_text_field( wp_unslash( $_POST['job_category'] ) ) : '';
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
		$subcategory   = isset( $_POST['job_subcategory'] ) ? sanitize_text_field( wp_unslash( $_POST['job_subcategory'] ) ) : '';
		$category_list = gigneo_term_list(
			array(
				'taxonomy' => 'gigneo_facet',
				'parent'   => 0,
			),
			false
		);

		if ( empty( $category ) || ! array_key_exists( $category, $category_list ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Category is required.', 'gigneo' ) ), 422 );
		}

		$category_term = get_term_by( 'slug', $category, 'gigneo_facet' );
		if ( ! $category_term || is_wp_error( $category_term ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Category is required.', 'gigneo' ) ), 422 );
		}

		$subcategory_list = gigneo_term_list(
			array(
				'taxonomy' => 'gigneo_facet',
				'parent'   => $category_term->term_id,
			),
			false
		);

		if ( empty( $subcategory ) || ! array_key_exists( $subcategory, $subcategory_list ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Subcategory is required.', 'gigneo' ) ), 422 );
		}

		$subcategory_term = get_term_by( 'slug', $subcategory, 'gigneo_facet' );
		$facets           = array( $category, $subcategory );

		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
		$job_specific_types = isset( $_POST['job_specific_types'] ) && is_array( $_POST['job_specific_types'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['job_specific_types'] ) ) : array();

		if ( ! empty( $job_specific_types ) ) {
			$max_specific_types = gigneo_option( '_gigneo_ts_job_max_specific_types', '5' );
			$specific_types     = gigneo_filter_term_slugs(
				$job_specific_types,
				gigneo_term_list(
					array(
						'taxonomy' => 'gigneo_facet',
						'parent'   => $subcategory_term->term_id,
					),
					false
				)
			);

			if ( count( $specific_types ) > intval( $max_specific_types ) ) {
				wp_send_json_error(
					array(
						'message' => sprintf(
						// translators: %d: maximum number of specific types allowed
							esc_html__( 'You can select up to %d specialities only.', 'gigneo' ),
							$max_specific_types
						),
					),
					422
				);
			}

			$facets = array_merge( $facets, $specific_types );
		}

		wp_set_object_terms( $post_id, $facets, 'gigneo_facet' );

		// Taxonomy Skills — sanitize and allowlist against gigneo_skill.
		$max_skills = gigneo_option( '_gigneo_ts_job_max_skills', '5' );
		$skill_list = gigneo_term_list( array( 'taxonomy' => 'gigneo_skill' ), false );
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
		$job_skills = isset( $_POST['job_skills'] ) && is_array( $_POST['job_skills'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['job_skills'] ) ) : array();
		$skills     = gigneo_filter_term_slugs( $job_skills, $skill_list );

		if ( empty( $skills ) ) {
			wp_send_json_error( array( 'message' => esc_html__( 'Skills are required.', 'gigneo' ) ), 422 );
		}

		if ( count( $skills ) > intval( $max_skills ) ) {
			wp_send_json_error(
				array(
					'message' => sprintf(
					// translators: %d: maximum number of skills allowed
						esc_html__( 'You can select up to %d skills only.', 'gigneo' ),
						$max_skills
					),
					'field'   => 'job_skills', // optional - for frontend focus
				),
				422
			);
		}

		wp_set_object_terms( $post_id, $skills, 'gigneo_skill' );

		// job Type Meta
		$default_type = gigneo_option( '_gigneo_ts_default_job_type', 'remote' );
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
		$job_type = isset( $_POST['job_type'] ) ? sanitize_text_field( wp_unslash( $_POST['job_type'] ) ) : $default_type;

		update_post_meta( $post_id, '_gigneo_pm_type', $job_type );
		update_post_meta( $post_id, '_gigneo_pm_profile_id', $profile_id );
		update_post_meta( $post_id, '_gigneo_pm_job_type', 'fixed' );

		//Update Steps
		$steps_filled[] = 'basic';
		update_post_meta( $post_id, '_gigneo_pm_steps_filled', array_unique( $steps_filled ) );

		return array(
			'id' => $post_id,
		);
	}
	/**
	 * Edit pricing step.
	 *
	 * @since 0.0.1
	 */
	public function edit_pricing_step( $post_id, $steps_filled ) {

		// Define required fields + error messages
		$required_fields = array(
			'duration_length' => esc_html__( 'Duration Length is required.', 'gigneo' ),
			'duration'        => esc_html__( 'Duration Unit is required.', 'gigneo' ),
			'budget'          => esc_html__( 'Budget is required.', 'gigneo' ),
		);

		// Validate required fields
		foreach ( $required_fields as $required_field => $error_message ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
			if ( empty( $_POST[ $required_field ] ) ) {
				wp_send_json_error( array( 'message' => $error_message ), 422 );
			}
		}

		//budget
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
		$budget = isset( $_POST['budget'] ) ? sanitize_text_field( wp_unslash( $_POST['budget'] ) ) : '';
		update_post_meta( $post_id, '_gigneo_pm_price', $budget );

		//duration
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
		$duration_length = isset( $_POST['duration_length'] ) ? absint( wp_unslash( $_POST['duration_length'] ) ) : 0;
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
		$duration_unit = isset( $_POST['duration'] ) ? sanitize_text_field( wp_unslash( $_POST['duration'] ) ) : 'days';

		update_post_meta( $post_id, '_gigneo_pm_duration_type', $duration_unit );
		update_post_meta( $post_id, '_gigneo_pm_duration', $duration_length );

		//Update Steps
		$steps_filled[] = 'pricing';
		update_post_meta( $post_id, '_gigneo_pm_steps_filled', array_unique( $steps_filled ) );

		return array(
			'id' => $post_id,
		);
	}
	/**
	 * Edit details step.
	 *
	 * @since 0.0.1
	 */
	public function edit_details_step( $post_id, $steps_filled ) {

		// Define required fields + error messages
		$required_fields = array(
			'description'      => esc_html__( 'Description is required.', 'gigneo' ),
			'country_state'    => esc_html__( 'Country/State is required.', 'gigneo' ),
			'zip_code'         => esc_html__( 'Zip code is required.', 'gigneo' ),
			'area'             => esc_html__( 'Area is required.', 'gigneo' ),
			'friendly_address' => esc_html__( 'Friendly address is required.', 'gigneo' ),
		);

		if ( gigneo_post_meta( $post_id, '_gigneo_pm_type' ) === 'remote' ) {
			// For remote jobs, location fields are not required
			unset( $required_fields['country_state'] );
			unset( $required_fields['zip_code'] );
			unset( $required_fields['area'] );
			unset( $required_fields['friendly_address'] );
		}

		// Validate required fields
		foreach ( $required_fields as $required_field => $error_message ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
			if ( empty( $_POST[ $required_field ] ) ) {
				wp_send_json_error( array( 'message' => $error_message ), 403 );
			}
		}

		//Description
		// phpcs:disabled WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce verified upstream in save_job().

		$description = isset( $_POST['description'] ) ? wp_kses( wp_unslash( $_POST['description'] ), gigneo_allowed_html_tags() ) : '';
		update_post_meta( $post_id, '_gigneo_pm_description', $description );
		//location
		$country_state = isset( $_POST['country_state'] ) ? sanitize_text_field( wp_unslash( $_POST['country_state'] ) ) : '';
		update_post_meta( $post_id, '_gigneo_pm_country_state', $country_state );

		$city = isset( $_POST['city'] ) ? sanitize_text_field( wp_unslash( $_POST['city'] ) ) : '';
		update_post_meta( $post_id, '_gigneo_pm_city', $city );

		$zip_code = isset( $_POST['zip_code'] ) ? sanitize_text_field( wp_unslash( $_POST['zip_code'] ) ) : '';
		update_post_meta( $post_id, '_gigneo_pm_zip_code', $zip_code );

		$area = isset( $_POST['area'] ) ? sanitize_text_field( wp_unslash( $_POST['area'] ) ) : '';
		update_post_meta( $post_id, '_gigneo_pm_area', $area );

		$friendly_address = isset( $_POST['friendly_address'] ) ? sanitize_text_field( wp_unslash( $_POST['friendly_address'] ) ) : '';
		update_post_meta( $post_id, '_gigneo_pm_friendly_address', $friendly_address );

		// Extract and decode map location JSON safely.
		$map_location_raw = isset( $_POST['map_location'] ) ? wp_unslash( $_POST['map_location'] ) : '';
		$map_location     = json_decode( $map_location_raw, true );
		// phpcs:enable WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

		// Ensure we have an array to prevent potential Fatal Errors during property access.
		if ( ! is_array( $map_location ) ) {
			$map_location = array();
		}

		// Determine the address using a hierarchy of fallbacks: JSON value -> form map_address -> friendly_address.
		$map_address = ! empty( $map_location['address'] ) ? sanitize_text_field( $map_location['address'] ) : '';
		if ( empty( $map_address ) ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
			$map_address = isset( $_POST['map_address'] ) ? sanitize_text_field( wp_unslash( $_POST['map_address'] ) ) : $friendly_address;
		}

		$map_location_data = array(
			'address' => $map_address,
		);
		$map_location_data = apply_filters( 'gigneo_edit_details_step_before', $map_location_data, $map_location, $map_address );

		update_post_meta( $post_id, '_gigneo_pm_location', $map_location_data );

		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
		$attachments_raw = isset( $_POST['attachments'] ) && is_array( $_POST['attachments'] ) ? array_map( 'absint', wp_unslash( $_POST['attachments'] ) ) : array();
		$attachments     = ! empty( $attachments_raw ) ? array_values( array_filter( $attachments_raw ) ) : array();

		// Attachments
		$attachment_list = array();
		foreach ( $attachments as $attachment ) {
			$attachment_list[] = absint( $attachment );
		}

		update_post_meta( $post_id, '_gigneo_pm_attachments', $attachment_list );

		//Update Steps
		$steps_filled[] = 'details';
		update_post_meta( $post_id, '_gigneo_pm_steps_filled', array_unique( $steps_filled ) );

		return array(
			'id' => $post_id,
		);
	}

	/**
	 * Edit screening step.
	 *
	 * @since 0.0.1
	 */
	public function edit_screening_step( $post_id, $steps_filled ) {

		// Define required fields + error messages
		$required_fields = array(
			'experience_level' => esc_html__( 'Experience level is required.', 'gigneo' ),
		);

		// Validate required fields
		foreach ( $required_fields as $required_field => $error_message ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().
			if ( empty( $_POST[ $required_field ] ) ) {
				wp_send_json_error( array( 'message' => $error_message ), 422 );
			}
		}

		//Required licenses
		// phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce verified upstream; elements sanitized below.
		$required_licence = isset( $_POST['job_licenses'] ) ? wp_unslash( $_POST['job_licenses'] ) : array();

		if ( ! is_array( $required_licence ) ) {
			$required_licence = array( $required_licence );
		}

		$required_licence = array_map( 'sanitize_text_field', $required_licence );
		update_post_meta( $post_id, '_gigneo_pm_job_licenses', $required_licence );

		// Experience Level
		$experience_level = isset( $_POST['experience_level'] ) ? sanitize_text_field( wp_unslash( $_POST['experience_level'] ) ) : '';
		update_post_meta( $post_id, '_gigneo_pm_experience_level', $experience_level );

		// Preferred Location
		$preferred_location = isset( $_POST['preferred_location'] ) ? wp_unslash( $_POST['preferred_location'] ) : array();

		if ( ! is_array( $preferred_location ) ) {
			$preferred_location = array( $preferred_location );
		}

		$preferred_location = array_map( 'sanitize_text_field', $preferred_location );
		update_post_meta( $post_id, '_gigneo_pm_preferred_location', $preferred_location );

		// Preferred Timezone
		$preferred_timezone = isset( $_POST['preferred_timezone'] ) ? sanitize_text_field( wp_unslash( $_POST['preferred_timezone'] ) ) : '';
		update_post_meta( $post_id, '_gigneo_pm_preferred_timezone', $preferred_timezone );

		// Preferred Language
		$preferred_language = isset( $_POST['preferred_language'] ) ? sanitize_text_field( wp_unslash( $_POST['preferred_language'] ) ) : '';
		update_post_meta( $post_id, '_gigneo_pm_preferred_language', $preferred_language );

		// Language Proficiency
		$language_proficiency = isset( $_POST['language_proficiency'] ) ? sanitize_text_field( wp_unslash( $_POST['language_proficiency'] ) ) : '';
		update_post_meta( $post_id, '_gigneo_pm_language_proficiency', $language_proficiency );

		// Application Deadline
		$application_deadline = isset( $_POST['application_deadline'] ) ? sanitize_text_field( wp_unslash( $_POST['application_deadline'] ) ) : '';
		$application_deadline = gigneo_prepare_datetime( $application_deadline );
		update_post_meta( $post_id, '_gigneo_pm_application_deadline', $application_deadline['local'] ?? '' );
		update_post_meta( $post_id, '_gigneo_pm_application_deadline_gmt', $application_deadline['gmt'] ?? '' );
		// phpcs:enable WordPress.Security.NonceVerification.Missing -- Nonce verified upstream in save_job().

		//Update Steps
		$steps_filled[] = 'screening';
		update_post_meta( $post_id, '_gigneo_pm_steps_filled', array_unique( $steps_filled ) );

		$average_rating = gigneo_post_meta( $post_id, '_gigneo_pm_average_rating' );
		if ( empty( $average_rating ) ) {
			update_post_meta( $post_id, '_gigneo_pm_average_rating', '0' );
		}

		return array( 'id' => $post_id );
	}

	/**
	 * Post type actions.
	 *
	 * @since 0.0.1
	 */
	public function post_type_actions( $post_id, $author_id, $post_type ) {

		if ( 'gigneo_job' !== $post_type ) {
			return;
		}

		$job_manual_approval_option = gigneo_option( '_gigneo_ts_job_manually_approve', false );
		$job_manual_approval_info   = gigneo_post_meta( $post_id, '_gigneo_pm_manual_approval_info' );
		$job_manual_approval_status = $job_manual_approval_info['status'] ?? '';

		if ( ! $job_manual_approval_option || ! in_array( $job_manual_approval_status, array( 'pending', 'approved', 'rejected' ), true ) ) {
			return;
		}
		$job_icon = GIGNEO_DIR_URL . "assets/img/icon/job-$job_manual_approval_status.png";
		?>
		<div class="gn-post-type-action gn-action-job">
			<button type="button" data-gn-modal-toggle="gn-job-review-modal-<?php echo esc_attr( $post_id ); ?>">
				<img src="<?php echo esc_url( $job_icon ); ?>" alt="<?php echo esc_html__( 'Job Approval', 'gigneo' ); ?>">
			</button>
		</div>
		<?php
		gigneo_load_template( 'admin/parts/job/pending-review', false, array( 'p_id' => $post_id ) );
	}
	/**
	 * Reject job markup.
	 *
	 * @since 0.0.1
	 */
	public function reject_job_markup() {
		$manual_approval_option = gigneo_option( '_gigneo_ts_job_manually_approve', false );
		if ( $manual_approval_option ) {
			gigneo_load_template( 'admin/parts/job/reject-review' );
		}
	}

	/**
	 * Proposal post type actions.
	 *
	 * @since 0.0.1
	 */
	public function proposal_post_type_actions( $post_id, $author_id, $post_type ) {

		if ( 'gigneo_proposal' !== $post_type ) {
			return;
		}
		$post_status = get_post_status( $post_id );
		$job_icon    = GIGNEO_DIR_URL . 'assets/img/icon/proposal-' . $post_status . '.png';
		?>
		<div class="gn-post-type-action gn-action-job">
			<button type="button" data-gn-modal-toggle="gn-proposal-overview-modal-<?php echo esc_attr( $post_id ); ?>">
				<img src="<?php echo esc_url( $job_icon ); ?>" alt="<?php echo esc_html__( 'Job proposal', 'gigneo' ); ?>">
			</button>
		</div>
		<?php
		gigneo_load_template( 'admin/parts/proposal/overview', false, array( 'p_id' => $post_id ) );
	}
}
