<?php

namespace Gigneo;

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

/**
 * Class Post Types
 *
 * Plugin post types class for Gigneo.
 *
 * @since 0.0.1
 */
class Post_Types {
	/**
	 * The single instance of the class.
	 *
	 * @var Post_Types|null
	 * @since 0.0.1
	 */
	private static $instance = null;

	/**
	 * Constructor for the class.
	 *
	 * @since 0.0.1
	 */
	public function __construct() {
		//Register post types
		add_action( 'init', array( $this, 'register_post_types' ) );

		//Register post statuses
		add_action( 'init', array( $this, 'register_post_statuses' ) );

		//Custom Column
		add_filter( 'manage_gigneo_freelancer_posts_columns', array( $this, 'custom_columns' ) );
		add_filter( 'manage_gigneo_employer_posts_columns', array( $this, 'custom_columns' ) );
		add_filter( 'manage_gigneo_service_posts_columns', array( $this, 'service_columns' ) );
		add_filter( 'manage_gigneo_job_posts_columns', array( $this, 'job_columns' ) );
		add_filter( 'manage_gigneo_proposal_posts_columns', array( $this, 'proposal_columns' ) );

		//Custom Column Content
		add_action( 'manage_gigneo_freelancer_posts_custom_column', array( $this, 'custom_column_content' ), 10, 2 );
		add_action( 'manage_gigneo_service_posts_custom_column', array( $this, 'custom_column_content' ), 10, 2 );
		add_action( 'manage_gigneo_employer_posts_custom_column', array( $this, 'custom_column_content' ), 10, 2 );
		add_action( 'manage_gigneo_job_posts_custom_column', array( $this, 'custom_column_content' ), 10, 2 );
		add_action( 'manage_gigneo_proposal_posts_custom_column', array( $this, 'custom_column_content' ), 10, 2 );

		//Show post-statuses in dropdown
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );

		//Update admin post-type urls when slugs change
		add_action( 'admin_init', array( $this, 'update_admin_post_type_urls' ) );

		//Update admin button urls when slugs change
		add_filter( 'admin_url', array( $this, 'modify_admin_post_type_button_urls' ) );

		//Update post filter url
		add_action( 'admin_head', array( $this, 'modify_post_filter_views_dynamic' ) );

		add_filter( 'wp_unique_post_slug', array( $this, 'post_unique_slug' ), 10, 4 );
	}

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

		return self::$instance;
	}

	/**
	 * Register post types.
	 *
	 * @since 0.0.1
	 */
	public function register_post_types() {

		//Register freelancer post type
		$this->register_freelancer_post_type();

		//Register service post type
		$this->register_service_post_type();

		//Register employer post type
		$this->register_employer_post_type();

		//Register job post type
		$this->register_job_post_type();

		//Register proposal post type
		$this->register_proposal_post_type();

		//Register order post type
		$this->register_order_post_type();

		//Register invoice post type
		$this->register_invoice_post_type();

		//Register withdraw post type
		$this->register_withdraw_post_type();
	}

	/**
	 * Registers the 'freelancer' post-type.
	 *
	 * This function defines and registers the 'freelancer' post-type in WordPress.
	 * It applies filters for labels and post-type arguments to allow customization.
	 *
	 * @since 0.0.1
	 *
	 * @return void
	 */
	public function register_freelancer_post_type() {

		$post_type_slug = self::post_type_slug( 'gigneo_freelancer' );

		$post_type_labels = array(
			'name'           => gigneo_freelancer_plural(),
			'singular_name'  => gigneo_freelancer_singular(),
			'menu_name'      => gigneo_freelancer_plural(),
			'name_admin_bar' => gigneo_freelancer_plural(),
			'all_items'      => esc_html__( 'All', 'gigneo' ),
			'edit_item'      => esc_html__( 'Edit', 'gigneo' ),
			'view_item'      => esc_html__( 'View', 'gigneo' ),
			'update_item'    => esc_html__( 'Update', 'gigneo' ),
			'add_new_item'   => esc_html__( 'Add new', 'gigneo' ),
			'new_item_name'  => esc_html__( 'New', 'gigneo' ),
			'search_items'   => esc_html__( 'Search', 'gigneo' ),
			'not_found'      => esc_html__( 'Not found', 'gigneo' ),
		);

		// Post type args
		$post_type_args = apply_filters(
			'gigneo_post_type_freelancer_args',
			array(
				'labels'        => $post_type_labels,
				'public'        => true,
				'has_archive'   => false,
				'rewrite'       => array( 'slug' => $post_type_slug ),
				'supports'      => array( 'title', 'thumbnail', 'author' ),
				'show_in_rest'  => false,
				'show_ui'       => true,
				'show_in_menu'  => false,
				'menu_position' => 31,
				'menu_icon'     => 'dashicons-admin-users',
				'capabilities'  => array( 'create_posts' => 'do_not_allow' ),
				'map_meta_cap'  => true,
			)
		);

		register_post_type( 'gigneo_freelancer', $post_type_args );
	}

	/**
	 * Retrieves the slug for a given post type.
	 *
	 * This function allows filtering of post type slugs through the
	 * 'gigneo_post_type_slugs' and "gigneo_post_type_{$post_type}_slug" filters.
	 *
	 * @since 0.0.1
	 *
	 * @param string $post_type The post type key.
	 * @return string|array The slug of the post type.
	 */
	public static function post_type_slug( $post_type = '' ) {

		$freelancer_slug = apply_filters( 'gigneo_freelancer_slug', 'freelancer' );
		$freelancer_slug = gigneo_option( '_gigneo_ts_post_type_freelancer_slug', $freelancer_slug );

		$service_slug = apply_filters( 'gigneo_service_slug', 'service' );
		$service_slug = gigneo_option( '_gigneo_ts_post_type_service_slug', $service_slug );

		$employer_slug = apply_filters( 'gigneo_employer_slug', 'employer' );
		$employer_slug = gigneo_option( '_gigneo_ts_post_type_employer_slug', $employer_slug );

		$job_slug = apply_filters( 'gigneo_job_slug', 'job' );
		$job_slug = gigneo_option( '_gigneo_ts_post_type_job_slug', $job_slug );

		$proposal_slug = apply_filters( 'gigneo_proposal_slug', 'proposal' );
		$proposal_slug = gigneo_option( '_gigneo_ts_post_type_proposal_slug', $proposal_slug );

		$invoice_slug = apply_filters( 'gigneo_invoice_slug', 'invoice' );
		$invoice_slug = gigneo_option( '_gigneo_ts_post_type_invoice_slug', $invoice_slug );

		$order_slug = apply_filters( 'gigneo_order_slug', 'order' );
		$order_slug = gigneo_option( '_gigneo_ts_post_type_order_slug', $order_slug );

		$withdraw_slug = apply_filters( 'gigneo_withdraw_slug', 'withdrawal' );
		$withdraw_slug = gigneo_option( '_gigneo_ts_post_type_withdraw_slug', $withdraw_slug );

		$slugs = array(
			'gigneo_freelancer' => $freelancer_slug,
			'gigneo_service'    => $service_slug,
			'gigneo_employer'   => $employer_slug,
			'gigneo_job'        => $job_slug,
			'gigneo_proposal'   => $proposal_slug,
			'gigneo_invoice'    => $invoice_slug,
			'gigneo_order'      => $order_slug,
			'gigneo_withdrawal' => $withdraw_slug,
		);

		$slugs = apply_filters( 'gigneo_post_type_slugs', $slugs );

		if ( ! empty( $post_type ) ) {
			return $slugs[ $post_type ] ?? '';
		}

		return $slugs;
	}

	/**
	 * Registers the 'service' post-type.
	 *
	 * This function defines and registers the 'service' post-type in WordPress.
	 * It applies filters for labels and post-type arguments to allow customization.
	 *
	 * @since 0.0.1
	 *
	 * @return void
	 */
	public function register_service_post_type() {

		$platform_type = gigneo_platform_type();

		if ( 'jobs' === $platform_type ) {
			return;
		}

		$post_type_slug = self::post_type_slug( 'gigneo_service' );

		$post_type_labels = array(
			'name'           => esc_html__( 'Services', 'gigneo' ),
			'singular_name'  => esc_html__( 'Service', 'gigneo' ),
			'menu_name'      => esc_html__( 'Services', 'gigneo' ),
			'name_admin_bar' => esc_html__( 'Services', 'gigneo' ),
			'all_items'      => esc_html__( 'All', 'gigneo' ),
			'edit_item'      => esc_html__( 'Edit', 'gigneo' ),
			'view_item'      => esc_html__( 'View', 'gigneo' ),
			'update_item'    => esc_html__( 'Update', 'gigneo' ),
			'add_new_item'   => esc_html__( 'Add new', 'gigneo' ),
			'new_item_name'  => esc_html__( 'New', 'gigneo' ),
			'search_items'   => esc_html__( 'Search', 'gigneo' ),
			'not_found'      => esc_html__( 'Not found', 'gigneo' ),
		);

		// Post type args
		$post_type_args = apply_filters(
			'gigneo_post_type_service_args',
			array(
				'labels'        => $post_type_labels,
				'public'        => true,
				'has_archive'   => false,
				'rewrite'       => array( 'slug' => "$post_type_slug" ),
				'supports'      => array( 'title', 'thumbnail', 'author' ),
				'show_in_rest'  => false,
				'show_ui'       => true,
				'show_in_menu'  => false,
				'menu_position' => 31,
				'query_var'     => true,
				'menu_icon'     => 'dashicons-admin-page',
			)
		);

		// Register the post type
		register_post_type( 'gigneo_service', $post_type_args );
	}

	/**
	 * Registers the 'employer' post type.
	 *
	 * This function defines and registers the 'employer' post type in WordPress.
	 * It applies filters for labels and post type arguments to allow customization.
	 *
	 * @since 0.0.1
	 *
	 * @return void
	 */
	public function register_employer_post_type() {

		$post_type_slug          = self::post_type_slug( 'gigneo_employer' );
		$employer_profile_access = gigneo_employer_profile_access();

		$post_type_labels = array(
			'name'           => gigneo_employer_plural(),
			'singular_name'  => gigneo_employer_singular(),
			'menu_name'      => gigneo_employer_plural(),
			'name_admin_bar' => gigneo_employer_plural(),
			'all_items'      => esc_html__( 'All', 'gigneo' ),
			'edit_item'      => esc_html__( 'Edit', 'gigneo' ),
			'view_item'      => esc_html__( 'View', 'gigneo' ),
			'update_item'    => esc_html__( 'Update', 'gigneo' ),
			'add_new_item'   => esc_html__( 'Add new', 'gigneo' ),
			'new_item_name'  => esc_html__( 'New', 'gigneo' ),
			'search_items'   => esc_html__( 'Search', 'gigneo' ),
			'not_found'      => esc_html__( 'Not found', 'gigneo' ),
		);

		// Post type args
		$post_type_args = apply_filters(
			'gigneo_post_type_employer_args',
			array(
				'labels'        => $post_type_labels,
				'public'        => 'public' === $employer_profile_access,
				'has_archive'   => false,
				'rewrite'       => array( 'slug' => $post_type_slug ),
				'supports'      => array( 'title', 'thumbnail', 'author' ),
				'show_in_rest'  => false,
				'show_ui'       => true,
				'show_in_menu'  => false,
				'menu_position' => 31,
				'menu_icon'     => 'dashicons-businessman',
				'capabilities'  => array( 'create_posts' => 'do_not_allow' ),
				'map_meta_cap'  => true,
			)
		);

		// Register the post type
		register_post_type( 'gigneo_employer', $post_type_args );
	}

	/**
	 * Registers the 'job' post type.
	 *
	 * This function defines and registers the 'job' post type in WordPress.
	 * It applies filters for labels and post type arguments to allow customization.
	 *
	 * @since 0.0.1
	 *
	 * @return void
	 */
	public function register_job_post_type() {

		$platform_type = gigneo_platform_type();

		if ( 'services' === $platform_type ) {
			return;
		}

		$post_type_slug = self::post_type_slug( 'gigneo_job' );

		$post_type_labels = array(
			'name'           => esc_html__( 'Jobs', 'gigneo' ),
			'singular_name'  => esc_html__( 'Job', 'gigneo' ),
			'menu_name'      => esc_html__( 'Jobs', 'gigneo' ),
			'name_admin_bar' => esc_html__( 'Jobs', 'gigneo' ),
			'all_items'      => esc_html__( 'All', 'gigneo' ),
			'edit_item'      => esc_html__( 'Edit', 'gigneo' ),
			'view_item'      => esc_html__( 'View', 'gigneo' ),
			'update_item'    => esc_html__( 'Update', 'gigneo' ),
			'add_new_item'   => esc_html__( 'Add new', 'gigneo' ),
			'new_item_name'  => esc_html__( 'New', 'gigneo' ),
			'search_items'   => esc_html__( 'Search', 'gigneo' ),
			'not_found'      => esc_html__( 'Not found', 'gigneo' ),
		);

		// Post type args
		$post_type_args = apply_filters(
			'gigneo_post_type_job_args',
			array(
				'labels'        => $post_type_labels,
				'public'        => true,
				'has_archive'   => false,
				'rewrite'       => array( 'slug' => $post_type_slug ),
				'supports'      => array( 'title', 'thumbnail', 'author' ),
				'show_in_rest'  => false,
				'show_ui'       => true,
				'show_in_menu'  => false,
				'menu_position' => 31,
				'menu_icon'     => 'dashicons-portfolio',
			)
		);

		// Register the post type
		register_post_type( 'gigneo_job', $post_type_args );
	}

	/**
	 * Registers the 'proposal' post type.
	 *
	 * This function defines and registers the 'proposal' post type in WordPress.
	 * It applies filters for labels and post type arguments to allow customization.
	 *
	 * @since 0.0.1
	 *
	 * @return void
	 */
	public function register_proposal_post_type() {

		$platform_type = gigneo_platform_type();

		if ( 'services' === $platform_type ) {
			return;
		}

		$post_type_slug = self::post_type_slug( 'gigneo_proposal' );

		$post_type_labels = array(
			'name'           => esc_html__( 'Proposals', 'gigneo' ),
			'singular_name'  => esc_html__( 'Proposal', 'gigneo' ),
			'menu_name'      => esc_html__( 'Proposals', 'gigneo' ),
			'name_admin_bar' => esc_html__( 'Proposals', 'gigneo' ),
			'all_items'      => esc_html__( 'All', 'gigneo' ),
			'edit_item'      => esc_html__( 'Edit', 'gigneo' ),
			'view_item'      => esc_html__( 'View', 'gigneo' ),
			'update_item'    => esc_html__( 'Update', 'gigneo' ),
			'add_new_item'   => esc_html__( 'Add new', 'gigneo' ),
			'new_item_name'  => esc_html__( 'New', 'gigneo' ),
			'search_items'   => esc_html__( 'Search', 'gigneo' ),
			'not_found'      => esc_html__( 'Not found', 'gigneo' ),
		);

		// Post type args
		$post_type_args = apply_filters(
			'gigneo_post_type_proposal_args',
			array(
				'labels'        => $post_type_labels,
				'public'        => false,
				'has_archive'   => false,
				'rewrite'       => array( 'slug' => $post_type_slug ),
				'supports'      => array( 'title' ),
				'show_in_rest'  => false,
				'show_ui'       => true,
				'show_in_menu'  => false,
				'menu_position' => 31,
				'menu_icon'     => 'dashicons-portfolio',
			)
		);

		// Register the post type
		register_post_type( 'gigneo_proposal', $post_type_args );
	}

	/**
	 * Registers the 'order' post type.
	 *
	 * This function defines and registers the 'order' post type in WordPress.
	 * It applies filters for labels and post type arguments to allow customization.
	 *
	 * @since 0.0.1
	 *
	 * @return void
	 */
	public function register_order_post_type() {

		$post_type_slug = self::post_type_slug( 'gigneo_order' );

		$post_type_labels = array(
			'name'           => esc_html__( 'Orders', 'gigneo' ),
			'singular_name'  => esc_html__( 'Order', 'gigneo' ),
			'menu_name'      => esc_html__( 'Orders', 'gigneo' ),
			'name_admin_bar' => esc_html__( 'Orders', 'gigneo' ),
			'all_items'      => esc_html__( 'All', 'gigneo' ),
			'edit_item'      => esc_html__( '&nbsp;', 'gigneo' ),
			'view_item'      => esc_html__( 'View', 'gigneo' ),
			'update_item'    => esc_html__( 'Update', 'gigneo' ),
			'add_new_item'   => esc_html__( 'Add new', 'gigneo' ),
			'new_item_name'  => esc_html__( 'New', 'gigneo' ),
			'search_items'   => esc_html__( 'Search', 'gigneo' ),
			'not_found'      => esc_html__( 'Not found', 'gigneo' ),
		);

		// Post type args
		$post_type_args = apply_filters(
			'gigneo_post_type_order_args',
			array(
				'labels'        => $post_type_labels,
				'public'        => false,
				'has_archive'   => false,
				'rewrite'       => array( 'slug' => $post_type_slug ),
				'supports'      => array( 'title', 'author' ),
				'show_in_rest'  => false,
				'show_ui'       => true,
				'show_in_menu'  => false,
				'menu_position' => 31,
				'menu_icon'     => 'dashicons-schedule',
				'capabilities'  => array( 'create_posts' => 'do_not_allow' ),
				'map_meta_cap'  => true,
			)
		);

		register_post_type( 'gigneo_order', $post_type_args );
	}

	/**
	 * Registers the 'invoice' post type.
	 *
	 * This function defines and registers the 'invoice' post type in WordPress.
	 * It applies filters for labels and post type arguments to allow customization.
	 *
	 * @since 0.0.1
	 *
	 * @return void
	 */
	public function register_invoice_post_type() {

		$post_type_slug = self::post_type_slug( 'gigneo_invoice' );

		$post_type_labels = array(
			'name'           => esc_html__( 'Invoices', 'gigneo' ),
			'singular_name'  => esc_html__( 'Invoice', 'gigneo' ),
			'menu_name'      => esc_html__( 'Invoices', 'gigneo' ),
			'name_admin_bar' => esc_html__( 'Invoices', 'gigneo' ),
			'all_items'      => esc_html__( 'All', 'gigneo' ),
			'edit_item'      => esc_html__( 'Edit', 'gigneo' ),
			'view_item'      => esc_html__( 'View', 'gigneo' ),
			'update_item'    => esc_html__( 'Update', 'gigneo' ),
			'add_new_item'   => esc_html__( 'Add new', 'gigneo' ),
			'new_item_name'  => esc_html__( 'New', 'gigneo' ),
			'search_items'   => esc_html__( 'Search', 'gigneo' ),
			'not_found'      => esc_html__( 'Not found', 'gigneo' ),
		);

		// Post type args
		$post_type_args = apply_filters(
			'gigneo_post_type_invoice_args',
			array(
				'labels'        => $post_type_labels,
				'public'        => false,
				'has_archive'   => false,
				'rewrite'       => array( 'slug' => $post_type_slug ),
				'supports'      => array( 'title' ),
				'show_in_rest'  => false,
				'show_ui'       => true,
				'show_in_menu'  => false,
				'menu_position' => 31,
				'menu_icon'     => 'dashicons-schedule',
				'capabilities'  => array(
					'create_posts' => 'do_not_allow',
				),
				'map_meta_cap'  => true,
			)
		);

		// Register the post type
		register_post_type( 'gigneo_invoice', $post_type_args );
	}

	/**
	 * Registers the 'withdraw' post type.
	 *
	 * This function defines and registers the 'withdraw' post type in WordPress.
	 * It applies filters for labels and post type arguments to allow customization.
	 *
	 * @since 0.0.1
	 *
	 * @return void
	 */
	public function register_withdraw_post_type() {

		$post_type_slug = self::post_type_slug( 'gigneo_withdrawal' );

		$post_type_labels = array(
			'name'           => esc_html__( 'Withdrawals', 'gigneo' ),
			'singular_name'  => esc_html__( 'Withdrawal', 'gigneo' ),
			'menu_name'      => esc_html__( 'Withdrawals', 'gigneo' ),
			'name_admin_bar' => esc_html__( 'Withdrawals', 'gigneo' ),
			'all_items'      => esc_html__( 'All', 'gigneo' ),
			'edit_item'      => esc_html__( 'Edit', 'gigneo' ),
			'view_item'      => esc_html__( 'View', 'gigneo' ),
			'update_item'    => esc_html__( 'Update', 'gigneo' ),
			'add_new_item'   => esc_html__( 'Add new', 'gigneo' ),
			'new_item_name'  => esc_html__( 'New', 'gigneo' ),
			'search_items'   => esc_html__( 'Search', 'gigneo' ),
			'not_found'      => esc_html__( 'Not found', 'gigneo' ),
		);

		// Post type args
		$post_type_args = apply_filters(
			'gigneo_post_type_withdraw_args',
			array(
				'labels'        => $post_type_labels,
				'public'        => false,
				'has_archive'   => false,
				'rewrite'       => array( 'slug' => $post_type_slug ),
				'supports'      => array( 'title' ),
				'show_in_rest'  => false,
				'show_ui'       => true,
				'show_in_menu'  => false,
				'menu_position' => 31,
				'menu_icon'     => 'dashicons-cart',
			)
		);

		// Register the post type
		register_post_type( 'gigneo_withdrawal', $post_type_args );
	}

	/**
	 * Update admin post type URLs.
	 *
	 * This function updates the admin post type URLs when the slugs change.
	 *
	 * @since 0.0.1
	 */
	public function update_admin_post_type_urls() {
		global $pagenow;

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only parameters no nonce required.
		$post_type = isset( $_GET['post_type'] ) ? sanitize_key( wp_unslash( $_GET['post_type'] ) ) : '';

		$post_type = ! empty( $post_type ) ? str_replace( 'gigneo_', '', $post_type ) : '';

		if ( is_admin() && ( 'edit.php' === $pagenow || 'post-new.php' === $pagenow ) && ! empty( $post_type ) ) {

			$post_types_slug = self::post_type_slug();
			$pt              = array_search( $post_type, $post_types_slug, true );
			if ( ! empty( $pt ) ) {
				$_GET['post_type']     = $pt;
				$_REQUEST['post_type'] = $pt;
			}
		}
	}

	/**
	 * Modify admin post type button URLs.
	 *
	 * This function modifies the URLs of admin post type buttons when the slugs change.
	 *
	 * @param string $url The original URL.
	 * @return string The modified URL.
	 * @since 0.0.1
	 */
	public function modify_admin_post_type_button_urls( $url ) {

		if ( ! is_admin() ) {
			return $url;
		}

		global $current_screen;

		if ( ! isset( $current_screen ) || empty( $current_screen->post_type ) || 'edit' !== $current_screen->base ) {
			return $url;
		}

		$post_type = $current_screen->post_type;

		$post_types_slugs = self::post_type_slug( $post_type );
		$post_types_slugs = ! empty( $post_types_slugs ) ? 'gigneo_' . $post_types_slugs : '';

		if ( empty( $post_types_slugs ) || $post_types_slugs === $post_type ) {
			return $url;
		}

		return str_replace( "post_type=$post_type", "post_type=$post_types_slugs", $url );
	}

	/**
	 * Modify post filter views dynamically.
	 *
	 * This function modifies the post filter views dynamically based on the current post type.
	 *
	 * @since 0.0.1
	 */
	public function modify_post_filter_views_dynamic() {

		if ( ! is_admin() ) {
			return;
		}

		$screen = get_current_screen();

		if ( ! $screen || ! isset( $screen->post_type ) || 'edit' !== $screen->base ) {
			return;
		}

		$current_post_type  = $screen->post_type;
		$new_post_type_slug = self::post_type_slug( $current_post_type );
		$new_post_type_slug = ! empty( $new_post_type_slug ) ? 'gigneo_' . $new_post_type_slug : '';

		if ( empty( $new_post_type_slug ) || $current_post_type === $new_post_type_slug ) {
			return;
		}

		add_filter(
			'views_edit-' . $current_post_type,
			function ( $views ) use ( $current_post_type, $new_post_type_slug ) {
				foreach ( $views as $view_key => $view_html ) {
					$views[ $view_key ] = str_replace( "post_type=$current_post_type", "post_type=$new_post_type_slug", $view_html );
				}
				return $views;
			}
		);
	}

	/**
	 * Ensures unique slugs for specific post types by appending the post ID.
	 *
	 * This function appends the post ID to the slug for 'gigneo_service' and 'gigneo_job' post types
	 * to guarantee uniqueness.
	 *
	 * @since 0.0.1
	 *
	 * @param string $slug The post-slug.
	 * @param int $post_ID The post-ID.
	 * @param string $post_status The post-status.
	 * @param string $post_type The post-type.
	 * @return string The modified slug.
	 */
	public function post_unique_slug( $slug, $post_ID, $post_status, $post_type ) {
		// Only apply to posts or specific post-types
		if ( 'gigneo_service' === $post_type || 'gigneo_job' === $post_type ) {
			if ( ! str_contains( $slug, '-' . $post_ID ) ) {
				$slug .= '-' . $post_ID;
			}
		}

		return $slug;
	}

	/**
	 * Register custom post statuses.
	 *
	 * This function registers custom post statuses for the plugin.
	 *
	 * @since 0.0.1
	 */
	public function register_post_statuses() {

		//Statuses
		$statuses = array(
			'processing'  => esc_html__( 'Processing', 'gigneo' ),
			'on-hold'     => esc_html__( 'On Hold', 'gigneo' ),
			'completed'   => esc_html__( 'Completed', 'gigneo' ),
			'refunded'    => esc_html__( 'Refunded', 'gigneo' ),
			'cancelled'   => esc_html__( 'Cancelled', 'gigneo' ),
			'failed'      => esc_html__( 'Failed', 'gigneo' ),
			'rejected'    => esc_html__( 'Rejected', 'gigneo' ),
			'paused'      => esc_html__( 'Paused', 'gigneo' ),
			'delivered'   => esc_html__( 'Delivered', 'gigneo' ),
			'delayed'     => esc_html__( 'Delayed', 'gigneo' ),
			'disputed'    => esc_html__( 'Disputed', 'gigneo' ),
			'dismissed'   => esc_html__( 'Dismissed', 'gigneo' ),
			'open'        => esc_html__( 'Open', 'gigneo' ),
			'in-progress' => esc_html__( 'In Progress', 'gigneo' ),
			'paid'        => esc_html__( 'Paid', 'gigneo' ),
			'deactivated' => esc_html__( 'Deactivated', 'gigneo' ),
			'blocked'     => esc_html__( 'Blocked', 'gigneo' ),
			'closed'      => esc_html__( 'Closed', 'gigneo' ),
			'withdrawn'   => esc_html__( 'Withdrawn', 'gigneo' ),
			'viewed'      => esc_html__( 'Viewed', 'gigneo' ),
			'hired'       => esc_html__( 'Hired', 'gigneo' ),
			'shortlisted' => esc_html__( 'Shortlisted', 'gigneo' ),
		);

		foreach ( $statuses as $key => $label ) {

			$args = array(
				'label'                     => $label,
				'public'                    => true,
				'internal'                  => false,
				'show_in_admin_all_list'    => true,
				'show_in_admin_status_list' => true,
			);

			if ( in_array( $key, array( 'blocked', 'deactivated', 'closed', 'dismissed' ), true ) ) {
				$args['public']              = false;
				$args['exclude_from_search'] = true;
			}

			register_post_status( $key, $args );
		}
	}

	/**
	 * Add an Actions column to post list tables.
	 *
	 * Inserts a new 'gigneo_actions' column before the date column.
	 *
	 * @since 0.0.1
	 *
	 * @param array $columns Existing columns.
	 * @return array Modified columns.
	 */
	public function custom_columns( $columns ) {
		$new_columns = array();
		foreach ( $columns as $key => $value ) {
			if ( 'date' === $key ) {
				$new_columns['gigneo_actions'] = esc_html__( 'Actions', 'gigneo' );
				$new_columns['gigneo_wallet']  = esc_html__( 'Wallet balance', 'gigneo' );
			}
			$new_columns[ $key ] = $value;
		}
		return $new_columns;
	}

	/**
	 * Modify columns for the 'service' post type.
	 *
	 * Inserts 'gigneo_service_status' and 'gigneo_actions' columns before the date column.
	 *
	 * @since 0.0.1
	 *
	 * @param array $columns Existing columns.
	 * @return array Modified columns.
	 */
	public function service_columns( $columns ) {
		$new_columns = array();
		foreach ( $columns as $key => $value ) {
			if ( 'date' === $key ) {
				$new_columns['gigneo_service_status'] = esc_html__( 'Service status', 'gigneo' );
				$new_columns['gigneo_actions']        = esc_html__( 'Actions', 'gigneo' );
			}
			$new_columns[ $key ] = $value;
		}
		return $new_columns;
	}

	/**
	 * Modify columns for the 'job' post type.
	 *
	 * Inserts 'gigneo_job_status' and 'gigneo_actions' columns before the date column.
	 *
	 * @since 0.0.1
	 *
	 * @param array $columns Existing columns.
	 * @return array Modified columns.
	 */
	public function job_columns( $columns ) {
		$new_columns = array();
		foreach ( $columns as $key => $value ) {
			if ( 'date' === $key ) {
				$new_columns['gigneo_job_status'] = esc_html__( 'Job status', 'gigneo' );
				$new_columns['gigneo_actions']    = esc_html__( 'Actions', 'gigneo' );
			}
			$new_columns[ $key ] = $value;
		}
		return $new_columns;
	}

	/**
	 * Modify columns for the 'proposal' post type.
	 *
	 * Inserts 'gigneo_proposal_status' and 'gigneo_actions' columns before the date column.
	 *
	 * @since 0.0.1
	 *
	 * @param array $columns Existing columns.
	 * @return array Modified columns.
	 */
	public function proposal_columns( $columns ) {
		$new_columns = array();
		foreach ( $columns as $key => $value ) {
			if ( 'title' === $key ) {
				$new_columns[ $key ]              = $value;
				$new_columns['gigneo_job']        = esc_html__( 'Job', 'gigneo' );
				$new_columns['gigneo_freelancer'] = esc_html__( 'Freelancer', 'gigneo' );
				$new_columns['gigneo_budget']     = esc_html__( 'Budget', 'gigneo' );
				continue;
			}
			if ( 'date' === $key ) {
				$new_columns['gigneo_actions'] = esc_html__( 'Actions', 'gigneo' );
			}
			$new_columns[ $key ] = $value;
		}
		return $new_columns;
	}

	/**
	 * Output custom column content for specific columns.
	 *
	 * This function outputs custom content for the 'gigneo_actions', 'gigneo_job', 'gigneo_freelancer', 'gigneo_budget',
	 * 'gigneo_job_status', and 'gigneo_service_status' columns in the admin post list tables.
	 *
	 * @since 0.0.1
	 *
	 * @param string $column The name of the column.
	 * @param int $post_id The ID of the current post.
	 */
	public function custom_column_content( $column, $post_id ) {
		if ( 'gigneo_actions' === $column ) {
			$author_id = get_post_field( 'post_author', $post_id );
			$post_type = get_post_type( $post_id );
			?>
			<div class="gn-post-actions">
				<?php do_action( 'gigneo_post_type_actions', $post_id, $author_id, $post_type ); ?>
			</div>
			<?php
		}
		if ( 'gigneo_wallet' === $column ) {
			$author_id      = get_post_field( 'post_author', $post_id );
			$post_type      = get_post_type( $post_id );
			$profile_id     = 'gigneo_freelancer' === $post_type ? gigneo_profile_id( $author_id, 'freelancer' ) : gigneo_profile_id( $author_id, 'employer' );
			$wallet_balance = gigneo_wallet_balance( $profile_id );
			?>
			<div class="gn-post-wallet">
				<?php echo esc_html( gigneo_price_format( $wallet_balance, true ) ); ?>
			</div>
			<?php
		}

		if ( 'gigneo_job' === $column ) {
			$job_id = gigneo_post_meta( $post_id, '_gigneo_pm_job_id' );
			if ( ! empty( $job_id ) ) {
				echo '<a href="' . esc_url( get_edit_post_link( $job_id ) ) . '">' . esc_html( get_the_title( $job_id ) ) . '</a>';
			} else {
				echo '&mdash;';
			}
		}

		if ( 'gigneo_freelancer' === $column ) {
			$freelancer_id = gigneo_post_meta( $post_id, '_gigneo_pm_freelancer_profile_id' );
			if ( ! empty( $freelancer_id ) ) {
				echo '<a href="' . esc_url( get_edit_post_link( $freelancer_id ) ) . '">' . esc_html( gigneo_profile_name( $freelancer_id ) ) . '</a>';
			} else {
				echo '&mdash;';
			}
		}

		if ( 'gigneo_budget' === $column ) {
			$budget = gigneo_post_meta( $post_id, '_gigneo_pm_budget' );
			echo esc_html( gigneo_price_format( $budget, true ) );
		}

		if ( 'gigneo_job_status' === $column ) {

			$status = get_post_status( $post_id );
			$obj    = get_post_status_object( $status );

			if ( $obj && ! empty( $obj->label ) ) {
				?>
				<span class="gn-status-tag <?php echo esc_attr( gigneo_status_class( $status ) ); ?>">
					<?php echo esc_html( gigneo_status_label( $status ) ); ?>
				</span>
				<?php
			}
		}
		if ( 'gigneo_service_status' === $column ) {

			$status       = get_post_status( $post_id );
			$status_label = gigneo_status_label( $status );

			if ( $status_label ) {
				?>
				<span class="gn-status-tag <?php echo esc_attr( gigneo_status_class( $status ) ); ?>">
					<?php echo esc_html( gigneo_status_label( $status ) ); ?>
				</span>
				<?php
			}
		}
	}

	/**
	 * Add custom post statuses to the dropdown.
	 *
	 * This function adds custom post statuses to the post status dropdown in the admin area.
	 *
	 * @since 0.0.1
	 */
	public function enqueue_admin_scripts() {

		global $post;

		if ( empty( $post ) || 'gigneo_invoice' !== $post->post_type ) {
			return;
		}

		$custom_statuses = array(
			'on-hold'   => esc_html__( 'On Hold', 'gigneo' ),
			'completed' => esc_html__( 'Completed', 'gigneo' ),
			'refunded'  => esc_html__( 'Refunded', 'gigneo' ),
			'cancelled' => esc_html__( 'Cancelled', 'gigneo' ),
			'failed'    => esc_html__( 'Failed', 'gigneo' ),
		);

		$script = '';

		foreach ( $custom_statuses as $status => $label ) {

			$option = sprintf(
				'<option value="%1$s" %2$s>%3$s</option>',
				esc_attr( $status ),
				selected( $post->post_status, $status, false ),
				esc_html( $label )
			);

			$script .= 'jQuery("#post_status").append(' . wp_json_encode( $option ) . ');';
		}

		wp_register_script(
			'gigneo-admin-status',
			'',
			array( 'jquery' ),
			GIGNEO_VERSION,
			true
		);

		wp_enqueue_script( 'gigneo-admin-status' );

		wp_add_inline_script(
			'gigneo-admin-status',
			'jQuery(function($){' . $script . '});'
		);
	}
}
