<?php
/**
 * The core metabox framework class.
 *
 * @package Sifency
 */

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

class Sifency_Addons_Master_Metabox {

	private $metaboxes;

	public function __construct( array $metabox_definitions ) {
		$this->metaboxes = $metabox_definitions;
		add_action( 'add_meta_boxes', array( $this, 'register_meta_boxes' ) );
		add_action( 'save_post', array( $this, 'save_meta_data' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
	}

	public function enqueue_admin_scripts( $hook ) {
		if ( 'post.php' !== $hook && 'post-new.php' !== $hook ) {
			return;
		}

		wp_enqueue_style( 'wp-color-picker' );
		wp_enqueue_media();
		wp_enqueue_script( 'jquery-ui-sortable' );

		$script_dependencies = array( 'jquery', 'jquery-ui-sortable', 'wp-color-picker' );

		wp_enqueue_style(
			'sifency-admin-metabox',
			SIFENCY_TB_URL . 'assets/css/admin-metabox.css',
			array(),
			SIFENCY_TB_VERSION
		);

		wp_enqueue_script(
			'sifency-admin-metabox',
			SIFENCY_TB_URL . 'assets/js/admin-metabox.js',
			$script_dependencies,
			SIFENCY_TB_VERSION,
			true
		);
	}
	public function register_meta_boxes() {
		foreach ( $this->metaboxes as $id => $metabox ) {
			add_meta_box(
				$id,
				$metabox['title'],
				array( $this, 'render_metabox_content' ),
				$metabox['post_type'],
				$metabox['context'] ?? 'normal',
				$metabox['priority'] ?? 'high',
				array(
					'fields' => $metabox['fields'],
					'id'     => $id,
				)
			);
		}
	}

	public function render_metabox_content( $post, $args ) {
		$fields       = $args['args']['fields'];
		$metabox_id   = $args['args']['id'];
		$nonce_action = $metabox_id . '_nonce_action';
		$nonce_name   = $metabox_id . '_nonce';

		wp_nonce_field( $nonce_action, $nonce_name );
		$sections      = array();
		$section_order = array();
		foreach ( $fields as $field ) {
			$section_name = isset( $field['section'] ) ? $field['section'] : '';
			if ( '' === $section_name ) {
				$section_name = '__default__';
			}
			if ( ! isset( $sections[ $section_name ] ) ) {
				$sections[ $section_name ] = array();
				$section_order[]           = $section_name;
			}
			$sections[ $section_name ][] = $field;
		}
		echo '<div class="sifency-metabox-wrapper">';

		$use_tabs = count( $sections ) > 1;
		if ( $use_tabs ) {
			echo '<div class="sifency-tabs">';
			echo '<ul class="sifency-tabs-nav">';
			$first = true;
			foreach ( $section_order as $section_name ) {
				$label = ( '__default__' === $section_name ) ? esc_html__( 'General', 'sifency-addons' ) : esc_html( $section_name );
				$slug  = sanitize_title( $section_name );
				echo '<li class="sifency-tab-nav-item sifency-admin-btn' . ( $first ? ' active' : '' ) . '" data-section="' . esc_attr( $slug ) . '"><a href="#" class="sifency-admin-btn">' . esc_html( $label ) . ' ' . esc_html( $label ) . '</a></li>';
				$first = false;
			}
			echo '</ul>';
			echo '<div class="sifency-tabs-panels">';
		}

		if ( $use_tabs ) {
			$first_panel = true;
			foreach ( $section_order as $section_name ) {
				$slug = sanitize_title( $section_name );
				echo '<div class="sifency-tab-panel' . ( $first_panel ? ' active' : '' ) . '" data-section="' . esc_attr( $slug ) . '"' . ( $first_panel ? '' : ' style="display:none;"' ) . '>';
				foreach ( $sections[ $section_name ] as $field ) {
					$value = get_post_meta( $post->ID, $field['id'], true );
					if ( '' === $value && isset( $field['default'] ) ) {
						$value = $field['default'];
					}

					$field_classes = array(
						'sifency-addons-field-row',
						'sifency-addons-field-type-' . esc_attr( $field['type'] ),
						'sifency-addons-field-id-' . esc_attr( $field['id'] ),
					);

					if ( ! empty( $field['class'] ) ) {
						$field_classes[] = esc_attr( $field['class'] );
					}

					$dependency_attrs = '';
					if ( ! empty( $field['dependency'] ) ) {
						list( $controller, $operator, $dep_value ) = $field['dependency'];
						$dependency_attrs                          = sprintf(
							' data-dependency-controller="%s" data-dependency-operator="%s" data-dependency-value="%s"',
							esc_attr( $controller ),
							esc_attr( $operator ),
							esc_attr( $dep_value )
						);
					}

					echo '<div class="' . esc_attr( implode( ' ', $field_classes ) ) . '"' . wp_kses_post( $dependency_attrs ) . '>';
					echo '<div class="sifency-addons-label-col"><label for="' . esc_attr( $field['id'] ) . '">' . esc_html( $field['title'] ) . '</label></div>';
					echo '<div class="sifency-addons-field-col">';
					$this->render_field( $field, $value );
					if ( ! empty( $field['desc'] ) ) {
						echo '<p class="description">' . wp_kses_post( $field['desc'] ) . '</p>';
					}
					echo '</div></div>';
				}
				echo '</div>';
				$first_panel = false;
			}
			echo '</div></div>';
		} else {
			foreach ( $fields as $field ) {
				$value = get_post_meta( $post->ID, $field['id'], true );
				if ( '' === $value && isset( $field['default'] ) ) {
					$value = $field['default'];
				}

				$field_classes = array(
					'sifency-addons-field-row',
					'sifency-addons-field-type-' . esc_attr( $field['type'] ),
					'sifency-addons-field-id-' . esc_attr( $field['id'] ),
				);

				if ( ! empty( $field['class'] ) ) {
					$field_classes[] = esc_attr( $field['class'] );
				}

				$dependency_attrs = '';
				if ( ! empty( $field['dependency'] ) ) {
					list( $controller, $operator, $dep_value ) = $field['dependency'];
					$dependency_attrs                          = sprintf(
						' data-dependency-controller="%s" data-dependency-operator="%s" data-dependency-value="%s"',
						esc_attr( $controller ),
						esc_attr( $operator ),
						esc_attr( $dep_value )
					);
				}

				echo '<div class="' . esc_attr( implode( ' ', $field_classes ) ) . '"' . wp_kses_post( $dependency_attrs ) . '>';
				echo '<div class="sifency-addons-label-col"><label for="' . esc_attr( $field['id'] ) . '">' . esc_html( $field['title'] ) . '</label></div>';
				echo '<div class="sifency-addons-field-col">';
				$this->render_field( $field, $value );
				if ( ! empty( $field['desc'] ) ) {
					echo '<p class="description">' . wp_kses_post( $field['desc'] ) . '</p>';
				}
				echo '</div></div>';
			}
		}
		echo '</div>';
	}

	private function render_field( $field, $value, $name_prefix = '' ) {
		$field_id       = $field['id'];
		$field_name     = $name_prefix ? $name_prefix . '[' . $field_id . ']' : $field_id;
		$attributes_str = '';
		if ( ! empty( $field['attributes'] ) && is_array( $field['attributes'] ) ) {
			foreach ( $field['attributes'] as $attr => $attr_val ) {
				$attributes_str .= ' ' . esc_attr( $attr ) . '="' . esc_attr( $attr_val ) . '"';
			}
		}

		switch ( $field['type'] ) {
			case 'repeater':
				$template_id = 'sifency-repeater-template-' . esc_attr( $field_id );
				echo '<div class="sifency-repeater-items" id="' . esc_attr( $field_id ) . '-items" data-template-id="' . esc_attr( $template_id ) . '">';
				$items = ! empty( $value ) && is_array( $value ) ? $value : ( $field['default'] ?? array() );
				foreach ( $items as $index => $item_data ) {
					echo '<div class="sifency-repeater-row">';
					echo '<span class="sifency-repeater-handle" title="' . esc_attr__( 'Drag to reorder', 'sifency-addons' ) . '"></span>';
					echo '<a href="#" class="sifency-repeater-remove" title="' . esc_attr__( 'Remove item', 'sifency-addons' ) . '"></a>';
					$repeater_name_prefix = $field_id . '[' . $index . ']';
					foreach ( $field['fields'] as $sub_field ) {
						echo '<div class="sifency-repeater-sub-field">';
						echo '<label>' . esc_html( $sub_field['title'] ) . '</label>';
						$sub_value = $item_data[ $sub_field['id'] ] ?? '';
						$this->render_field( $sub_field, $sub_value, $repeater_name_prefix );
						echo '</div>';
					}
					echo '</div>';
				}
				echo '</div>';
				echo '<button type="button" class="button sifency-repeater-add">' . esc_html__( 'Add New', 'sifency-addons' ) . '</button>';
				echo '<script type="text/html" id="' . esc_attr( $template_id ) . '">';
				echo '<div class="sifency-repeater-row">';
				echo '<span class="sifency-repeater-handle" title="' . esc_attr__( 'Drag to reorder', 'sifency-addons' ) . '"></span>';
				echo '<a href="#" class="sifency-repeater-remove" title="' . esc_attr__( 'Remove item', 'sifency-addons' ) . '"></a>';
				$repeater_name_prefix = $field_id . '[__i__]';
				foreach ( $field['fields'] as $sub_field ) {
					echo '<div class="sifency-repeater-sub-field">';
					echo '<label>' . esc_html( $sub_field['title'] ) . '</label>';
					$this->render_field( $sub_field, $sub_field['default'] ?? '', $repeater_name_prefix );
					echo '</div>';
				}
				echo '</div></script>';
				break;
			case 'button_set':
				echo '<div class="sifency-button-set">';
				foreach ( $field['options'] as $key => $label ) {
					$radio_id = esc_attr( $field_id ) . '_' . esc_attr( $key );
					echo '<input type="radio" id="' . esc_attr( $radio_id ) . '" name="' . esc_attr( $field_name ) . '" value="' . esc_attr( $key ) . '" ' . checked( $value, $key, false ) . '/>';
					echo '<label for="' . esc_attr( $radio_id ) . '">' . esc_html( $label ) . '</label>';
				}
				echo '</div>';
				break;
			case 'select':
				$options_array = array();
				if ( is_array( $field['options'] ) ) {
					$options_array = $field['options'];
				} elseif ( is_string( $field['options'] ) && is_callable( $field['options'] ) ) {
					$options_array = call_user_func( $field['options'] );
				}

				echo '<select id="' . esc_attr( $field_id ) . '" name="' . esc_attr( $field_name ) . '">';
				foreach ( (array) $options_array as $key => $label ) {
					echo '<option value="' . esc_attr( $key ) . '" ' . selected( $value, $key, false ) . '>' . esc_html( $label ) . '</option>';
				}
				echo '</select>';
				break;
			case 'upload':
				$file_id     = $value;
				$filename    = $file_id ? basename( get_attached_file( $file_id ) ) : '';
				$hide_remove = empty( $file_id ) ? 'style="display:none;"' : '';
				$hide_name   = empty( $filename ) ? 'style="display:none;"' : '';
				echo '<div class="sifency-upload-field">';
				echo '<input type="hidden" class="sifency-upload-input" id="' . esc_attr( $field_id ) . '" name="' . esc_attr( $field_name ) . '" value="' . esc_attr( $file_id ) . '" />';
				echo '<span class="sifency-upload-filename" ' . esc_attr( $hide_name ) . '>' . esc_html( $filename ) . '</span>';
				echo '<button type="button" class="button sifency-upload-add">' . esc_html__( 'Upload File', 'sifency-addons' ) . '</button> ';
				echo '<button type="button" class="button button-link-delete sifency-upload-remove" ' . esc_attr( $hide_remove ) . '>' . esc_html__( 'Remove', 'sifency-addons' ) . '</button>';
				echo '</div>';
				break;
			case 'media':
				$image_src = $value ? wp_get_attachment_image_url( $value, 'thumbnail' ) : '';
				echo '<div class="sifency-media-field">';
				echo '<input type="hidden" class="sifency-media-input" id="' . esc_attr( $field_id ) . '" name="' . esc_attr( $field_name ) . '" value="' . esc_attr( $value ) . '" />';
				echo '<button type="button" class="button sifency-media-upload">' . esc_html__( 'Upload/Select Image', 'sifency-addons' ) . '</button> ';
				echo '<button type="button" class="button button-link-delete sifency-media-remove">' . esc_html__( 'Remove Image', 'sifency-addons' ) . '</button>';
				echo '<div class="sifency-media-preview">' . ( $image_src ? '<img src="' . esc_url( $image_src ) . '" style="max-width:150px; height:auto;" />' : '' ) . '</div>';
				echo '</div>';
				break;
			case 'textarea':
				echo '<textarea id="' . esc_attr( $field_id ) . '" name="' . esc_attr( $field_name ) . '">' . esc_textarea( $value ) . '</textarea>';
				break;
			case 'slider':
				$min  = $field['min'] ?? 0;
				$max  = $field['max'] ?? 100;
				$step = $field['step'] ?? 1;
				$val  = ! empty( $value ) ? $value : ( $field['default'] ?? $min );
				echo '<div class="sifency-slider-wrapper">';
				echo '<input type="range" class="sifency-slider-input" id="' . esc_attr( $field_id ) . '" name="' . esc_attr( $field_name ) . '" min="' . esc_attr( $min ) . '" max="' . esc_attr( $max ) . '" step="' . esc_attr( $step ) . '" value="' . esc_attr( $val ) . '" />';
				echo '<span class="sifency-slider-value">' . esc_html( $val ) . '</span>';
				echo '</div>';
				break;
			case 'checkbox':
				echo '<div class="sifency-checkbox-group">';
				$value = is_array( $value ) ? $value : array();
				foreach ( $field['options'] as $key => $label ) {
					$checkbox_id = esc_attr( $field_id ) . '_' . esc_attr( $key );
					echo '<label for="' . esc_attr( $checkbox_id ) . '"><input type="checkbox" id="' . esc_attr( $checkbox_id ) . '" name="' . esc_attr( $field_name ) . '[]" value="' . esc_attr( $key ) . '" ' . checked( in_array( $key, $value ), true, false ) . '/> ' . esc_html( $label ) . '</label><br>';
				}
				echo '</div>';
				break;

			case 'wp_editor':
				$editor_id                 = str_replace( array( '[', ']' ), array( '_', '' ), $field_name );
				$settings                  = $field['settings'] ?? array();
				$settings['textarea_name'] = $field_name;
				wp_editor( $value, $editor_id, $settings );
				break;
			case 'color':
				echo '<input type="text" class="sifency-color-picker" id="' . esc_attr( $field_id ) . '" name="' . esc_attr( $field_name ) . '" value="' . esc_attr( $value ) . '" data-default-color="' . esc_attr( $field['default'] ?? '' ) . '"' . esc_attr( $attributes_str ) . ' />';
				break;

			case 'datetime':
				echo '<input type="datetime-local" class="sifency-field-date" id="' . esc_attr( $field_id ) . '" name="' . esc_attr( $field_name ) . '" value="' . esc_attr( $value ) . '"' . esc_attr( $attributes_str ) . ' />';
				break;
			case 'text':
			case 'email':
			case 'url':
			case 'number':
			case 'time':
			case 'date':
			default:
				echo '<input type="' . esc_attr( $field['type'] ) . '" id="' . esc_attr( $field_id ) . '" name="' . esc_attr( $field_name ) . '" value="' . esc_attr( $value ) . '"' . esc_attr( $attributes_str ) . ' />';
				break;
		}
	}

	public function save_meta_data( $post_id ) {
		$current_post_type = get_post_type( $post_id );
		$active_metabox    = null;
		foreach ( $this->metaboxes as $id => $metabox ) {
			if ( $metabox['post_type'] === $current_post_type ) {
				$active_metabox = $metabox;
				$metabox_id     = $id;
				break;
			}
		}
		if ( ! $active_metabox ) {
			return;
		}
		$nonce_action = $metabox_id . '_nonce_action';
		$nonce_name   = $metabox_id . '_nonce';
		if ( ! isset( $_POST[ $nonce_name ] ) || ! wp_verify_nonce( sanitize_key( $_POST[ $nonce_name ] ), $nonce_action ) ) {
			return;
		}
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
			return;
		}
		if ( ! current_user_can( 'edit_post', $post_id ) ) {
			return;
		}
		foreach ( $active_metabox['fields'] as $field ) {
			if ( isset( $_POST[ $field['id'] ] ) ) {
				$value = $this->sanitize_field( $_POST[ $field['id'] ], $field ); // phpcs:ignore
				update_post_meta( $post_id, $field['id'], $value );
			} elseif ( 'checkbox' === $field['type'] ) {
					update_post_meta( $post_id, $field['id'], array() );
			} else {
				delete_post_meta( $post_id, $field['id'] );
			}
		}
	}

	private function sanitize_field( $data, $field_config ) {
		if ( 'repeater' === $field_config['type'] ) {
			$sanitized_data = array();
			if ( is_array( $data ) ) {
				foreach ( $data as $index => $row_data ) {
					$sanitized_row = array();
					foreach ( $field_config['fields'] as $sub_field ) {
						if ( isset( $row_data[ $sub_field['id'] ] ) ) {
							$sanitized_row[ $sub_field['id'] ] = $this->sanitize_field( $row_data[ $sub_field['id'] ], $sub_field );
						}
					}
					$sanitized_data[] = $sanitized_row;
				}
			}
			return $sanitized_data;
		}
		if ( isset( $field_config['sanitize'] ) ) {
			switch ( $field_config['sanitize'] ) {
				case 'wp_kses_post':
					return wp_kses_post( $data );
				case 'allow_iframe':
					$allowed_html = array(
						'iframe' => array(
							'src'             => true,
							'width'           => true,
							'height'          => true,
							'style'           => true,
							'frameborder'     => true,
							'allowfullscreen' => true,
							'loading'         => true,
							'referrerpolicy'  => true,
						),
					);
					return wp_kses( $data, $allowed_html );
				case false:
				case 'none':
					return $data;
			}
		}

		$type = $field_config['type'];
		switch ( $type ) {
			case 'textarea':
				return sanitize_textarea_field( $data );
			case 'checkbox':
				return is_array( $data ) ? array_map( 'sanitize_text_field', $data ) : array();
			case 'slider':
				return floatval( $data );
			case 'upload':
			case 'media':
				return absint( $data );
			case 'email':
				return sanitize_email( $data );
			case 'url':
				return esc_url_raw( $data );
			case 'number':
				return intval( $data );
			case 'wp_editor':
				return wp_kses_post( $data );
			case 'color':
				return sanitize_hex_color( $data );

			case 'select':
			case 'button_set':
			case 'text':
			case 'date':
			case 'time':
			case 'datetime':
			default:
				return sanitize_text_field( $data );
		}
	}
}
