<?php
/**
 * Use namespace to avoid conflict
 */
namespace jobus\includes\Classes\submission;

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

/**
 * Class to handle job form submissions (create/update job posts)
 */
class Job_Form_Submission {

	/**
	 * Initialize the class
	 */
	public function __construct() {
		add_action( 'wp_loaded', [ $this, 'job_form_submission' ] );
	}

	/**
	 * Main form submission handler
	 */
	public function job_form_submission(): void {
		if ( ! isset( $_POST['employer_submit_job_form'] ) ) {
			return;
		}

		if ( wp_doing_ajax() ) {
			return;
		}

		// Nonce check
		$nonce = isset( $_POST['employer_submit_job_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['employer_submit_job_nonce'] ) ) : '';
		if ( ! $nonce || ! wp_verify_nonce( $nonce, 'employer_submit_job' ) ) {
			wp_die( esc_html__( 'Security check failed.', 'jobus' ) );
		}

		// Must be an employer
		$user = wp_get_current_user();
		$allowed_roles = [ 'jobus_employer', 'administrator' ];
		if ( ! array_intersect( $allowed_roles, $user->roles ) ) {
			wp_die( esc_html__( 'Access denied. You do not have permission to post a job.', 'jobus' ) );
		}

		$result = $this->process_submission();
		if ( is_wp_error( $result ) ) {
			wp_die( esc_html( $result->get_error_message() ) );
		}

		$this->redirect_after_submission( (int) $result['job_id'], (bool) $result['is_update'] );
	}

	/**
	 * Process the actual form submission (create/update job post).
	 *
	 * @return array|\WP_Error
	 */
	public function process_submission() {
		// Define expected fields to sanitize
		$expected_fields = [
			'job_id',
			'job_title',
			'job_description',
			'company_website',
			'is_company_website',
			'apply_form_url',
			'is_apply_btn'
		];

		$post_data = [];
		foreach ( $expected_fields as $field ) {
			if ( isset( $_POST[ $field ] ) ) {
				$post_data[ $field ] = jobus_recursive_sanitize_text_field( $_POST[ $field ] );
			}
		}

		// Collect job specifications dynamically from CSF options
		if ( function_exists( 'jobus_opt' ) ) {
			$specifications = jobus_opt('job_specifications');
			if ( is_array($specifications) ) {
				foreach ( $specifications as $field ) {
					if ( empty($field['meta_key']) ) continue;
					$meta_key = $field['meta_key'];
					if ( isset( $_POST[$meta_key] ) ) {
						$post_data[$meta_key] = $_POST[$meta_key]; // sanitized later
					}
				}
			}
		}
		
		// Collect taxonomy fields (IDs)
		$tax_fields = ['job_categories', 'job_locations', 'job_tags'];
		foreach ($tax_fields as $tax) {
			if ( isset($_POST[$tax]) ) {
				// normalize as array of IDs
				$values = $_POST[$tax];
				if ( is_string($values) ) {
					$values = explode(',', $values);
				}
				$post_data[$tax] = array_map('intval', (array) $values);
			}
		}

		// Get user and company
		$user       = wp_get_current_user();
		if ( ! $user || ! $user->ID ) {
			return new \WP_Error( 'jobus_job_submit_auth', esc_html__( 'You must be logged in to post a job.', 'jobus' ) );
		}
		// If editing an existing job, verify ownership
		$company_id = $this->get_company_id( $user->ID );
		// if ( ! $company_id ) {
		// 	wp_die( esc_html__( 'Company profile not found.', 'jobus' ) );
		// }

		$company_id = $this->get_company_id( $user->ID );
		$job_id 	= isset( $post_data['job_id'] ) ? absint( $post_data['job_id'] ) : 0;

		// Verify editing permissions
		if ( $job_id ) {
			$job_post = get_post( $job_id );
			if ( ! $job_post || $job_post->post_type !== 'jobus_job' ) {
				return new \WP_Error( 'jobus_job_invalid', esc_html__( 'Invalid job post.', 'jobus' ) );
			}
			if ( (int) $job_post->post_author !== (int) $user->ID ) {
				return new \WP_Error( 'jobus_job_edit_forbidden', esc_html__( 'You are not allowed to edit this job.', 'jobus' ) );
			}
		} else {
            // New job submission check
            $packages_enabled = function_exists( 'jobus_opt' ) && jobus_opt( 'enable_job_packages', false );
            $monetization_active = $packages_enabled && class_exists( 'WooCommerce' ) && jobus_is_premium();
            $can_post = ! $monetization_active || apply_filters( 'jobus_user_can_post_job', true, $user->ID, $post_data );
            if ( ! $can_post ) {
                return new \WP_Error( 'jobus_job_package_required', esc_html__( 'You cannot post a job. Please check your packages or purchase a new one.', 'jobus' ) );
            }
        }

		// Save job content (title/content)
		if ( isset( $post_data['job_title'] ) || isset( $post_data['job_description'] ) ) {
			$job_id = $this->save_job_content( $job_id, $post_data, $company_id );
			if ( is_wp_error( $job_id ) ) {
				return $job_id;
			}
		}

		// Save job specifications
		$this->save_job_specifications( $job_id, $post_data );

		// Save job taxonomies
		$this->save_job_taxonomies_by_id($job_id, $post_data);
		
		// Save company website
		if ( isset( $post_data['company_website'] ) ) {
			$this->save_company_website( $job_id, $post_data );
		}

		// Save external application URL
		if ( isset( $post_data['apply_form_url'] ) || isset( $post_data['is_apply_btn'] ) ) {
			$this->save_application_method( $job_id, $post_data );
		}

		// Save company logo (featured image)
		if ( isset( $_POST['job_company_logo_id'] ) ) {
			$logo_id = absint( $_POST['job_company_logo_id'] );
			if ( $logo_id > 0 ) {
				// Set as featured image
				set_post_thumbnail( $job_id, $logo_id );
			} else {
				// Remove featured image if logo ID is empty
				delete_post_thumbnail( $job_id );
			}
		}

        // Fire hooks after everything is saved
        if ( isset( $post_data['job_id'] ) && ! empty( $post_data['job_id'] ) ) {
            do_action( 'jobus_job_updated', $job_id, $post_data );
        } else {
            do_action( 'jobus_job_submitted', $job_id, $post_data );
        }

		return [
			'job_id'    => $job_id,
			'is_update' => ! empty( $post_data['job_id'] ),
		];
	}

	/**
	 * Redirect to the employer dashboard after a successful submission.
	 *
	 * Prevents duplicate posts on refresh and surfaces a success notice.
	 *
	 * @param int  $job_id     Saved job ID.
	 * @param bool $is_update  Whether the submission updated an existing job.
	 *
	 * @return void
	 */
	private function redirect_after_submission( int $job_id, bool $is_update ): void {
		$dashboard_url = \jobus\includes\Frontend\Dashboard::get_dashboard_page_url( 'jobus_employer' );
		$redirect_url  = $dashboard_url
			? jobus_get_dashboard_endpoint_url( 'jobs', $dashboard_url )
			: get_permalink( $job_id );

		$redirect_url = add_query_arg(
			[
				'message'  => $is_update ? 'job_updated' : 'job_created',
				'job_id'   => $job_id,
				'_wpnonce' => wp_create_nonce( 'jobus_dashboard_action' ),
			],
			$redirect_url
		);

		wp_safe_redirect( $redirect_url );
		exit;
	}

	/**
	 * Save taxonomies by IDs for a job post
	 */	
	private function save_job_taxonomies_by_id( int $job_id, array $post_data ): void {
		if ( empty( $job_id ) ) return;

		$taxonomy_map = [
			'job_categories' => 'jobus_job_cat',
			'job_locations'  => 'jobus_job_location',
			'job_tags'       => 'jobus_job_tag',
		];

		foreach ( $taxonomy_map as $field => $taxonomy ) {
			if ( ! isset( $post_data[ $field ] ) ) continue;
			$raw 		= $post_data[$field];
			$term_ids 	= [];

			// Normalize input to array of integers
			if ( is_string( $raw ) ) {
				$term_ids = array_map( 'intval', explode( ',', $raw ) );
			} elseif ( is_array( $raw ) ) {
				foreach ( $raw as $value ) {
					if ( is_string( $value ) && strpos( $value, ',' ) !== false ) {
						$parts = explode( ',', $value );
						foreach ( $parts as $p ) {
							$term_ids[] = intval( trim( $p ) );
						}
					} elseif ( is_numeric( $value ) ) {
						$term_ids[] = intval( $value );
					}
				}
			}

			$term_ids = array_filter( array_unique( $term_ids ) );

			// Now save it safely
			if ( ! empty( $term_ids ) ) {
				wp_set_post_terms( $job_id, $term_ids, $taxonomy, false );
			}
		}
	}
		
	/**
	 * Get the company ID associated with a user
	 *
	 * @param $user_id . If null, uses current user.
	 *
	 * @return int|false Company post ID or false if not found
	 */
	public static function get_company_id( $user_id = null ) {
		if ( null === $user_id ) {
			$user_id = get_current_user_id();
		}

		$args = [
			'post_type'      => 'jobus_company',
			'author'         => $user_id,
			'posts_per_page' => 1,
			'fields'         => 'ids',
		];

		$query = new \WP_Query( $args );

		return ! empty( $query->posts ) ? $query->posts[0] : false;
	}

	/**
	 * Save job content data (create or update post)
	 *
	 * @param int   $job_id     The job post ID (0 for new post, or existing ID for update)
	 * @param array $post_data  The full form data (title, content, etc)
	 * @param int   $company_id The company to associate with the job (used only when creating a new job)
	 *
	 * @return int Job post ID
	 *
	 * Note: $company_id is required here because when creating a new job, we must link it to a company.
	 *       For updates, the company link is not changed, but the parameter is still required for consistency.
	 */
	public function save_job_content( int $job_id, array $post_data, int $company_id ) {
		$user            = wp_get_current_user();
		$job_title       = isset( $post_data['job_title'] ) ? sanitize_text_field( $post_data['job_title'] ) : '';
		$job_description = isset( $post_data['job_description'] ) ? wp_kses_post( $post_data['job_description'] ) : '';

		if ( empty( $job_title ) ) {
			return new \WP_Error( 'jobus_job_title_required', esc_html__( 'Job title is required.', 'jobus' ) );
		}

		if ( $job_id && get_post_type( $job_id ) === 'jobus_job' ) {
			$job_post = get_post( $job_id );
			if ( ! $job_post ) {
				return new \WP_Error( 'jobus_job_invalid', esc_html__( 'Invalid job post.', 'jobus' ) );
			}
			if ( (int) $job_post->post_author !== (int) $user->ID ) {
				return new \WP_Error( 'jobus_job_edit_forbidden', esc_html__( 'You are not allowed to edit this job.', 'jobus' ) );
			}
			wp_update_post( array(
				'ID'           => $job_id,
				'post_title'   => $job_title,
				'post_content' => $job_description,
			) );
		} else {
			$submission_status  = 'publish';
			$valid_statuses     = [ 'publish', 'pending', 'draft' ];
			if ( function_exists( 'jobus_opt' ) ) {
				$configured = jobus_opt( 'job_submission_status' );
				if ( ! empty( $configured ) && in_array( $configured, $valid_statuses, true ) ) {
					$submission_status = $configured;
				}
			}

			$job_id = wp_insert_post( array(
				'post_type'    => 'jobus_job',
				'post_title'   => $job_title,
				'post_content' => $job_description,
				'post_status'  => $submission_status,
				'post_author'  => $user->ID,
			) );
			if ( is_wp_error( $job_id ) ) {
				return new \WP_Error( 'jobus_job_create_failed', esc_html__( 'Failed to create job post.', 'jobus' ) );
			}
			// Link job to company
			if ( ! empty( $company_id ) ) {
				update_post_meta( $job_id, '_jobus_company_id', $company_id );
			}

			// Check CSF options for Auto Expiry
			$jobus_opt         = get_option( 'jobus_opt', [] );
			$enable_job_expiry = ! isset( $jobus_opt['enable_job_expiry'] ) || $jobus_opt['enable_job_expiry'];

			if ( $enable_job_expiry ) {
				$expiry_days = ! empty( $jobus_opt['job_expiry_days'] ) ? (int) $jobus_opt['job_expiry_days'] : 30;
				update_post_meta( $job_id, '_jobus_expiration_date', current_time( 'Y-m-d H:i:s', strtotime( '+' . $expiry_days . ' days', current_time( 'timestamp' ) ) ) );
			}

		}

		return $job_id;
	}

	/**
	 * Get job content data and apply status for current user
	 *
	 * @param int $job_id The job post ID
	 *
	 * @return array
	 */
	public static function get_job_content( int $job_id ): array {
		$job_title       = get_post_field( 'post_title', $job_id ) ?? '';
		$job_description = get_post_field( 'post_content', $job_id ) ?? '';
		$author_id       = get_post_field( 'post_author', $job_id ) ?? '';
		$has_applied     = false;

		if ( is_user_logged_in() ) {
			$user            = wp_get_current_user();
			$applicant_posts = get_posts( [
				'post_type'   => 'jobus_applicant',
				'post_status' => 'publish',
				'meta_query'  => [
					[
						'key'     => 'job_applied_for_id',
						'value'   => $job_id,
						'compare' => '='
					],
					[
						'key'     => 'candidate_email',
						'value'   => $user->user_email,
						'compare' => '='
					]
				],
				'fields'      => 'ids',
				'numberposts' => 1
			] );
			if ( ! empty( $applicant_posts ) ) {
				$has_applied = true;
			}
		}

		return array(
			'job_title'       => $job_title,
			'job_description' => $job_description,
			'author_id'       => $author_id,
			'has_applied'     => $has_applied,
		);
	}


	/**
	 * Get job specifications data
	 *
	 * @param int $job_id
	 *
	 * @return array
	 */
	public static function get_job_specifications( int $job_id ): array {
		$meta = get_post_meta( $job_id, 'jobus_meta_options', true );
		if ( ! is_array( $meta ) ) {
			$meta = array();
		}
		$specs = array(
			'specifications' => $meta['job_specifications'] ?? array(),
			'dynamic_fields' => array()
		);
		if ( function_exists( 'jobus_opt' ) ) {
			$fields = jobus_opt( 'job_specifications' );
			if ( ! empty( $fields ) ) {
				foreach ( $fields as $field ) {
					$meta_key = $field['meta_key'] ?? '';
					if ( $meta_key ) {
						$val                                  = $meta[ $meta_key ] ?? array();
						$specs['dynamic_fields'][ $meta_key ] = is_array( $val ) ? $val : ( $val !== '' ? array( $val ) : array() );
					}
				}
			}
		}

		return $specs;
	}

	/**
	 * Save job specifications data
	 *
	 * @param int   $job_id    The job post ID (must already exist)
	 * @param array $post_data The form data (only specification fields are used)
	 *
	 * @return bool True on success, false on failure
	 *
	 * Note: $company_id is NOT needed here because specifications are only meta fields for the job post,
	 *       and do not affect the company relationship. Only $job_id and $post_data are required.
	 */
	public function save_job_specifications( int $job_id, array $post_data ): bool {

		// Load existing meta
		$meta = get_post_meta( $job_id, 'jobus_meta_options', true );
		if ( ! is_array( $meta ) ) {
			$meta = [];
		}

		// Load specification fields from CSF settings
		if ( function_exists( 'jobus_opt' ) ) {
			$specifications = jobus_opt( 'job_specifications' );

			if ( ! empty( $specifications ) && is_array( $specifications ) ) {

				foreach ( $specifications as $field ) {

					// Skip invalid meta keys
					if ( empty( $field['meta_key'] ) ) {
						continue;
					}

					$meta_key 		 = $field['meta_key'];
					$meta[$meta_key] = [];

					// If field value was submitted from form
					if ( isset( $post_data[$meta_key] ) ) {

						$value = $post_data[$meta_key];

						// MULTIPLE select values
						if ( is_array( $value ) ) {

							$clean = array_map(
								function( $v ) {
									return sanitize_text_field( wp_unslash( $v ) );
								},
								$value
							);

							$meta[$meta_key] = $clean;

						}
						// SINGLE select value
						else {

							$clean = sanitize_text_field( wp_unslash( $value ) );

							$meta[$meta_key] = $clean !== '' ? [ $clean ] : [];
						}
					}
				}
			}
		}

		// Save the final meta array back to database
		return update_post_meta( $job_id, 'jobus_meta_options', $meta );
	}
	
	/**
	 * Save job taxonomies (categories, locations, tags) by IDs
	 */
	public function save_job_taxonomies( int $job_id, array $post_data ): void {

		// Normalize comma-separated strings or arrays into integer arrays
		$normalize_ids = function($val) {
			if ( is_array($val) ) {
				return array_map('intval', $val);
			}
			if ( is_string($val) ) {
				$val = explode(',', $val);
				return array_map('intval', $val);
			}
			return [];
		};

		// Job Categories
		if ( isset($post_data['job_categories']) ) {
			$cats = $normalize_ids($post_data['job_categories']);
			if ( ! empty($cats) ) {
				wp_set_post_terms( $job_id, $cats, 'jobus_job_cat', false );
			}
		}
		
		// Job Locations
		if ( isset($post_data['job_locations']) ) {
			$locations = $normalize_ids($post_data['job_locations']);
			if ( ! empty($locations) ) {
				wp_set_post_terms( $job_id, $locations, 'jobus_job_location', false );
			}
		}
		
		// Job Tags
		if ( isset($post_data['job_tag']) ) {
			$tags = $normalize_ids($post_data['job_tag']);
			if ( ! empty($tags) ) {
				wp_set_post_terms( $job_id, $tags, 'jobus_job_tag', false );
			}
		}
	}
	
	/**
	 * Get company website data
	 *
	 * @param int $job_id
	 *
	 * @return array
	 */
	public static function get_company_website( int $job_id ): array {
		$meta    = get_post_meta( $job_id, 'jobus_meta_options', true );
		$website = [
			'url'                => '',
			'text'               => '',
			'target'             => '_self',
			'is_company_website' => 'default',
		];
		if ( isset( $meta['company_website'] ) && is_array( $meta['company_website'] ) ) {
			$website['url']    = $meta['company_website']['url'] ?? '';
			$website['text']   = $meta['company_website']['text'] ?? '';
			$website['target'] = $meta['company_website']['target'] ?? '_self';
		}
		if ( isset( $meta['is_company_website'] ) ) {
			$website['is_company_website'] = $meta['is_company_website'];
		}

		return $website;
	}

	/**
	 * Save company website data
	 *
	 * @param int   $job_id
	 * @param array $post_data
	 *
	 * @return bool
	 */
	public function save_company_website( int $job_id, array $post_data ): bool {
		$meta = get_post_meta( $job_id, 'jobus_meta_options', true );
		if ( ! is_array( $meta ) ) {
			$meta = array();
		}
		if ( isset( $post_data['company_website'] ) && is_array( $post_data['company_website'] ) ) {
			$website_data            = array(
				'url'    => isset( $post_data['company_website']['url'] ) ? esc_url_raw( $post_data['company_website']['url'] ) : '',
				'text'   => isset( $post_data['company_website']['text'] ) ? sanitize_text_field( wp_unslash( $post_data['company_website']['text'] ) ) : '',
				'target' => isset( $post_data['company_website']['target'] ) ? sanitize_text_field( $post_data['company_website']['target'] ) : '_self',
			);
			$meta['company_website'] = $website_data;
		}
		if ( isset( $post_data['is_company_website'] ) ) {
			$meta['is_company_website'] = sanitize_text_field( $post_data['is_company_website'] );
		}

		return update_post_meta( $job_id, 'jobus_meta_options', $meta );
	}

	/**
	 * Save application method (default form, custom URL, or external redirect)
	 *
	 * @param int   $job_id
	 * @param array $post_data
	 *
	 * @return bool
	 */
	public function save_application_method( int $job_id, array $post_data ): bool {
		$meta = get_post_meta( $job_id, 'jobus_meta_options', true );
		if ( ! is_array( $meta ) ) {
			$meta = array();
		}
		
		// Save application method type (default, custom, external)
		if ( isset( $post_data['is_apply_btn'] ) ) {
			$meta['is_apply_btn'] = sanitize_text_field( $post_data['is_apply_btn'] );
		}
		
		// Save application URL
		if ( isset( $post_data['apply_form_url'] ) ) {
			$meta['apply_form_url'] = esc_url_raw( $post_data['apply_form_url'] );
		}

		return update_post_meta( $job_id, 'jobus_meta_options', $meta );
	}
}
