<?php
/**
 * The core framework class for adding custom fields to nav menu items.
 *
 * @package Sifency
 */

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

class Sifency_Nav_Menu_Fields {

	private $fields = array();

	public function __construct( array $field_definitions ) {
		$this->fields = $field_definitions;

		// Add hooks
		add_action( 'wp_nav_menu_item_custom_fields', array( $this, 'add_custom_fields' ), 10, 2 );
		add_action( 'wp_update_nav_menu_item', array( $this, 'save_custom_fields' ), 10, 3 );

		// Add filters to apply the saved data to the front-end menu
		add_filter( 'nav_menu_css_class', array( $this, 'apply_custom_classes' ), 10, 4 );
		add_filter( 'nav_menu_item_title', array( $this, 'apply_menu_icon' ), 10, 4 );
		add_filter( 'nav_menu_submenu_css_class', array( $this, 'apply_submenu_classes' ), 10, 3 );
	}

	/**
	 * Renders the custom fields in the "Appearance > Menus" admin screen.
	 */
	public function add_custom_fields( $item_id, $item ) {
		wp_nonce_field( 'sifency_menu_nonce_action', 'sifency_menu_nonce_field' );

		foreach ( $this->fields as $field ) {
			$field_id    = $field['id'];
			$field_title = $field['title'];
			$field_desc  = $field['desc'] ?? '';
			$meta_key    = '_menu_item_' . $field_id; // Good practice to prefix menu item meta
			$value       = get_post_meta( $item_id, $meta_key, true );
			?>
			<p class="field-<?php echo esc_attr( $field_id ); ?> description description-wide">
				<label for="edit-menu-item-<?php echo esc_attr( $field_id ); ?>-<?php echo esc_attr( $item_id ); ?>">
					<?php echo esc_html( $field_title ); ?><br />
					<?php $this->render_field( $field, $item_id, $meta_key, $value ); ?>
					<?php if ( $field_desc ) : ?>
						<span class="description"><?php echo esc_html( $field_desc ); ?></span>
					<?php endif; ?>
				</label>
			</p>
			<?php
		}
	}

	/**
	 * Renders a single input field based on its type.
	 */
	private function render_field( $field, $item_id, $meta_key, $value ) {
		// WordPress requires a specific name format for menu item fields: menu-item-field_id[item_id]
		$name = 'menu-item-' . $field['id'] . '[' . $item_id . ']';
		$id   = 'edit-menu-item-' . $field['id'] . '-' . $item_id;

		switch ( $field['type'] ) {
			case 'select':
				echo '<select id="' . esc_attr( $id ) . '" name="' . esc_attr( $name ) . '" class="widefat">';
				foreach ( $field['options'] as $opt_key => $opt_val ) {
					echo '<option value="' . esc_attr( $opt_key ) . '" ' . selected( $value, $opt_key, false ) . '>' . esc_html( $opt_val ) . '</option>';
				}
				echo '</select>';
				break;
			case 'text':
			case 'url':
			default:
				echo '<input type="text" id="' . esc_attr( $id ) . '" name="' . esc_attr( $name ) . '" value="' . esc_attr( $value ) . '" class="widefat" />';
				break;
		}
	}

	/**
	 * Saves the custom field data when the menu is saved.
	 */
	public function save_custom_fields( $menu_id, $menu_item_db_id, $args ) {
		if ( ! isset( $_POST['sifency_menu_nonce_field'] ) || ! wp_verify_nonce( sanitize_key( $_POST['sifency_menu_nonce_field'] ), 'sifency_menu_nonce_action' ) ) {
			return;
		}

		foreach ( $this->fields as $field ) {
			$field_id = $field['id'];
			$post_key = 'menu-item-' . $field_id;
			$meta_key = '_menu_item_' . $field_id;

			if ( isset( $_POST[ $post_key ][ $menu_item_db_id ] ) ) {
				$value = sanitize_text_field( wp_unslash( $_POST[ $post_key ][ $menu_item_db_id ] ) );
				update_post_meta( $menu_item_db_id, $meta_key, $value );
			} else {
				delete_post_meta( $menu_item_db_id, $meta_key );
			}
		}
	}

	/**
	 * Adds custom CSS classes to the menu item's <li> element on the front-end.
	 */
	public function apply_custom_classes( $classes, $item, $args, $depth ) {
		$custom_class = get_post_meta( $item->ID, '_menu_item_menu_class', true );
		if ( ! empty( $custom_class ) ) {
			$classes[] = sanitize_html_class( $custom_class );
		}

		$is_mega_menu_plugin = get_post_meta( $item->ID, '_menu_item_make_as_a_mega_menu', true );
		$menu_item_options   = get_post_meta( $item->ID, 'sifency_menu_options', true );
		$is_mega_menu_theme  = ! empty( $menu_item_options['make_as_a_mega_menu'] ) && $menu_item_options['make_as_a_mega_menu'] === 'true';

		if ( 'true' === $is_mega_menu_plugin || $is_mega_menu_theme ) {
			$classes[] = 'cs-mega_menu';
			// Set global flag to let the sub-menu filter know this is a mega menu parent
			global $sifency_is_mega_menu_active;
			$sifency_is_mega_menu_active = true;
		} else {
			global $sifency_is_mega_menu_active;
			$sifency_is_mega_menu_active = false;
		}

		return $classes;
	}

	/**
	 * Adds an icon to the menu item's title (the <a> tag) on the front-end.
	 */
	public function apply_menu_icon( $title, $item, $args, $depth ) {
		$icon_class = get_post_meta( $item->ID, '_menu_item_menu_icon', true );

		if ( ! empty( $icon_class ) ) {
			$title = '<i class="' . esc_attr( $icon_class ) . '"></i> <span class="sifency-menu-title-text">' . $title . '</span>';
		}

		return $title;
	}

	/**
	 * Adds custom CSS classes to the sub-menu (ul) if the parent is a mega menu.
	 */
	public function apply_submenu_classes( $classes, $args, $depth ) {
		global $sifency_is_mega_menu_active;

		if ( ! empty( $sifency_is_mega_menu_active ) && 0 === $depth ) {
			$classes[] = 'cs-mega_wrapper';
		}

		return $classes;
	}
}