<?php
/********************************************************************
 * Copyright (C) 2024 Darko Gjorgjijoski (https://darkog.com/)
 * Copyright (C) 2024 IDEOLOGIX MEDIA Dooel (https://ideologix.com/)
 *
 * This file is property of IDEOLOGIX MEDIA Dooel (https://ideologix.com)
 * This file is part of Vimeify Plugin - https://wordpress.org/plugins/vimeify/
 *
 * Vimeify - Formerly "WP Vimeo Videos" is free software: you can redistribute
 * it and/or modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 2 of the License,
 * or (at your option) any later version.
 *
 * Vimeify - Formerly "WP Vimeo Videos" is distributed in the hope that it
 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this plugin. If not, see <https://www.gnu.org/licenses/>.
 *
 * Code developed by Darko Gjorgjijoski <dg@darkog.com>.
 **********************************************************************/

namespace Vimeify\Core\Backend;

use Vimeify\Core\Plugin;

class MetaboxRenderer {

	/**
	 * The plugin instance
	 *
	 * @var Plugin
	 */
	protected $plugin;

	/**
	 * The metabox configuration
	 *
	 * @var array
	 */
	protected $config;

	/**
	 * Constructor
	 *
	 * @param Plugin $plugin
	 * @param array  $config
	 */
	public function __construct( Plugin $plugin, $config = array() ) {
		$this->plugin = $plugin;
		$this->config = $config;
	}

	/**
	 * Register the metabox
	 *
	 * @return void
	 */
	public function register() {
		add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
		add_action( 'save_post', array( $this, 'save_meta_box' ), 10, 2 );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
	}

	/**
	 * Add the meta box
	 *
	 * @return void
	 */
	public function add_meta_box() {
		$id       = isset( $this->config['id'] ) ? $this->config['id'] : 'vimeify_metabox';
		$title    = isset( $this->config['title'] ) ? $this->config['title'] : __( 'Settings', 'vimeify' );
		$pages    = isset( $this->config['pages'] ) ? $this->config['pages'] : array();
		$context  = isset( $this->config['context'] ) ? $this->config['context'] : 'normal';
		$priority = isset( $this->config['priority'] ) ? $this->config['priority'] : 'high';

		foreach ( $pages as $page ) {
			add_meta_box(
				$id,
				$title,
				array( $this, 'render_meta_box' ),
				$page,
				$context,
				$priority
			);
		}
	}

	/**
	 * Render the meta box
	 *
	 * @param \WP_Post $post
	 *
	 * @return void
	 */
	public function render_meta_box( $post ) {
		$id = isset( $this->config['id'] ) ? $this->config['id'] : 'vimeify_metabox';

		// Nonce field
		wp_nonce_field( 'vimeify_metabox_' . $id, 'vimeify_metabox_nonce_' . $id );

		// Container for JavaScript renderer
		echo '<div id="vimeify-metabox-root-' . esc_attr( $id ) . '" class="vimeify-metabox-root" data-metabox-id="' . esc_attr( $id ) . '" data-post-id="' . esc_attr( $post->ID ) . '"></div>';

		// Hidden input to store compact data
		$save_mode = isset( $this->config['save_mode'] ) ? $this->config['save_mode'] : 'compact';
		if ( $save_mode === 'compact' ) {
			$current_value = get_post_meta( $post->ID, $id, true );
			$current_value = is_array( $current_value ) ? $current_value : array();
			echo '<input type="hidden" name="' . esc_attr( $id ) . '_data" id="' . esc_attr( $id ) . '_data" value="' . esc_attr( wp_json_encode( $current_value ) ) . '">';
		}
	}

	/**
	 * Save the meta box data
	 *
	 * @param int      $post_id
	 * @param \WP_Post $post
	 *
	 * @return void
	 */
	public function save_meta_box( $post_id, $post ) {
		$id = isset( $this->config['id'] ) ? $this->config['id'] : 'vimeify_metabox';

		// Verify nonce
		$nonce_key = 'vimeify_metabox_nonce_' . $id;
		if ( ! isset( $_POST[ $nonce_key ] ) || ! wp_verify_nonce( $_POST[ $nonce_key ], 'vimeify_metabox_' . $id ) ) {
			return;
		}

		// Check autosave
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
			return;
		}

		// Check permissions
		$pages = isset( $this->config['pages'] ) ? $this->config['pages'] : array();
		if ( ! in_array( $post->post_type, $pages, true ) ) {
			return;
		}

		if ( ! current_user_can( 'edit_post', $post_id ) ) {
			return;
		}

		// Get save mode
		$save_mode = isset( $this->config['save_mode'] ) ? $this->config['save_mode'] : 'compact';

		if ( $save_mode === 'compact' ) {
			// Compact mode - save all fields as a single serialized array
			$data_key = $id . '_data';
			if ( isset( $_POST[ $data_key ] ) ) {
				$json_data = sanitize_text_field( wp_unslash( $_POST[ $data_key ] ) );
				$data      = json_decode( $json_data, true );

				if ( is_array( $data ) ) {
					$sanitized_data = $this->sanitize_meta_data( $data );
					update_post_meta( $post_id, $id, $sanitized_data );
				}
			}
		} else {
			// Individual field mode
			$fields = isset( $this->config['fields'] ) ? $this->config['fields'] : array();

			foreach ( $fields as $field ) {
				if ( ! isset( $field['id'] ) || $field['type'] === 'tab' || $field['type'] === 'html' ) {
					continue;
				}

				$field_key = $id . '_' . $field['id'];

				if ( isset( $_POST[ $field_key ] ) ) {
					$value = $this->sanitize_field_value( $_POST[ $field_key ], $field );
					update_post_meta( $post_id, $field_key, $value );
				} else {
					// Handle unchecked checkboxes
					if ( $field['type'] === 'checkbox' ) {
						delete_post_meta( $post_id, $field_key );
					}
				}
			}
		}
	}

	/**
	 * Enqueue assets for the metabox
	 *
	 * @return void
	 */
	public function enqueue_assets() {
		if ( ! $this->is_metabox_screen() ) {
			return;
		}

		$id     = isset( $this->config['id'] ) ? $this->config['id'] : 'vimeify_metabox';
		$fields = isset( $this->config['fields'] ) ? $this->config['fields'] : array();

		// Process HTML callbacks in fields
		$fields = $this->process_field_callbacks( $fields );

		// Get current post ID
		$post_id = isset( $_GET['post'] ) ? intval( $_GET['post'] ) : 0;

		// Get current values
		$values = array();
		if ( $post_id ) {
			$values = get_post_meta( $post_id, $id, true );
			$values = is_array( $values ) ? $values : array();
		}

		// Group fields by tabs
		$tabs   = array();
		$groups = array();

		foreach ( $fields as $field ) {
			if ( $field['type'] === 'tab' ) {
				$tabs[] = array(
					'id'    => $field['id'],
					'label' => $field['label'],
				);
			}
		}

		// Prepare localized data
		$localized_data = array(
			'metaboxId' => $id,
			'postId'    => $post_id,
			'tabs'      => $tabs,
			'fields'    => $fields,
			'values'    => $values,
			'saveMode'  => isset( $this->config['save_mode'] ) ? $this->config['save_mode'] : 'compact',
			'i18n'      => array(
				'loading'      => __( 'Loading...', 'vimeify' ),
				'noResults'    => __( 'No results found', 'vimeify' ),
				'searching'    => __( 'Searching...', 'vimeify' ),
				'typeToSearch' => __( 'Type to search...', 'vimeify' ),
			),
		);

		wp_localize_script( 'vimeify-metabox', 'Vimeify_Metabox_' . $id, $localized_data );
	}

	/**
	 * Check if we're on a screen where metabox should appear
	 *
	 * @return bool
	 */
	protected function is_metabox_screen() {
		if ( ! function_exists( 'get_current_screen' ) ) {
			return false;
		}

		$screen = get_current_screen();
		if ( ! $screen ) {
			return false;
		}

		$pages = isset( $this->config['pages'] ) ? $this->config['pages'] : array();

		return in_array( $screen->post_type, $pages, true );
	}

	/**
	 * Process field callbacks (like HTML markup callbacks)
	 *
	 * @param array $fields
	 *
	 * @return array
	 */
	protected function process_field_callbacks( $fields ) {
		foreach ( $fields as $key => $field ) {
			// Process HTML type with callback
			if ( isset( $field['type'] ) && $field['type'] === 'html' ) {
				if ( isset( $field['markup'] ) && is_callable( $field['markup'] ) ) {
					$fields[ $key ]['markup'] = call_user_func( $field['markup'] );
				}
			}

			// Process choices with callbacks if needed
			if ( isset( $field['choices'] ) && is_callable( $field['choices'] ) ) {
				$fields[ $key ]['choices'] = call_user_func( $field['choices'] );
			}
		}

		return $fields;
	}

	/**
	 * Sanitize meta data
	 *
	 * @param array $data
	 *
	 * @return array
	 */
	protected function sanitize_meta_data( $data ) {
		$sanitized = array();

		foreach ( $data as $key => $value ) {
			$sanitized_key = sanitize_key( $key );

			if ( is_array( $value ) ) {
				$sanitized[ $sanitized_key ] = $this->sanitize_meta_data( $value );
			} elseif ( is_numeric( $value ) ) {
				$sanitized[ $sanitized_key ] = intval( $value );
			} else {
				$sanitized[ $sanitized_key ] = sanitize_text_field( $value );
			}
		}

		return $sanitized;
	}

	/**
	 * Sanitize a field value based on its type
	 *
	 * @param mixed $value
	 * @param array $field
	 *
	 * @return mixed
	 */
	protected function sanitize_field_value( $value, $field ) {
		$type = isset( $field['type'] ) ? $field['type'] : 'text';

		switch ( $type ) {
			case 'checkbox':
				if ( is_array( $value ) ) {
					return array_map( 'intval', $value );
				}
				return intval( $value );

			case 'radio':
			case 'select':
				return sanitize_text_field( $value );

			case 'text':
			default:
				return sanitize_text_field( $value );
		}
	}
}
