<?php
/**
 * Admin and shortcode functionality.
 *
 * @link       https://dcatl.diviaccessories.com/
 * @since      1.0.0
 *
 * @package    WordPress
 * @subpackage display-category-and-taxonomy-list
 */

namespace DCATL\Admin;

use DCATL\Public\Action;

/**
 * Handles the settings page, term images, and shortcode rendering.
 *
 * @since 1.0.0
 */
class Admin {

	use \DCATL\Trait\Singleton;

	/**
	 * Placeholder image URL.
	 *
	 * @var string
	 */
	private $placeholder;

	/**
	 * Initialize the class.
	 */
	public function __construct() {
		$this->placeholder = DCATL_URL . 'assets/admin/img/dcatl-upload-placeholder.png';
	}

	/**
	 * Register term-image fields for the selected taxonomy.
	 *
	 * @return void
	 */
	public function category_list_image_int() {
		$settings   = Action::get_instance()->get_settings();
		$taxonomies = isset( $settings['dcatl_taxonomy_list'] ) && is_array( $settings['dcatl_taxonomy_list'] )
			? $settings['dcatl_taxonomy_list']
			: array( 'category' );

		foreach ( $taxonomies as $taxonomy ) {
			$taxonomy = sanitize_key( $taxonomy );
			$object   = get_taxonomy( $taxonomy );

			if ( ! $object || ! $object->public || ! $object->show_ui ) {
				continue;
			}

			add_action( $taxonomy . '_add_form_fields', array( $this, 'add_term_image_field' ), 10, 1 );
			add_action( $taxonomy . '_edit_form_fields', array( $this, 'add_term_image_field_on_edit' ), 10, 2 );
			add_action( 'created_' . $taxonomy, array( $this, 'save_term_image_field_on_create' ), 10, 2 );
			add_action( 'edited_' . $taxonomy, array( $this, 'update_term_image_field_on_edit' ), 10, 2 );
			add_filter( 'manage_edit-' . $taxonomy . '_columns', array( $this, 'add_term_image_column' ) );
			add_filter( 'manage_' . $taxonomy . '_custom_column', array( $this, 'display_term_image_column' ), 10, 3 );
		}
	}

	/**
	 * Add the top-level settings menu.
	 *
	 * @return void
	 */
	public function add_dcatl_admin_menu() {
		add_menu_page(
			esc_html__( 'Category List', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Category List', 'display-category-and-taxonomy-list' ),
			'manage_options',
			'display-category-and-taxonomy-list',
			array( $this, 'category_list_image_settings_page' ),
			DCATL_URL . 'assets/admin/img/dcatl-dashicon.png'
		);
	}

	/**
	 * Render the settings page wrapper.
	 *
	 * @return void
	 */
	public function category_list_image_settings_page() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$features = array(
			esc_html__( 'Multiple taxonomy display', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Slider, mosaic, and advanced grid layouts', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Advanced layout modes and transitions', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Elementor and block editor support', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Priority support and regular updates', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Export and import settings', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Enable or disable the plugin stylesheet', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Custom Read More text and content length', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Additional sorting controls', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Title position control', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Image, icon, or color for terms', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Selected term display', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Custom counter position', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Tree view with vertical and horizontal layouts', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Multi-line or single-line display', 'display-category-and-taxonomy-list' ),
			esc_html__( 'And many more', 'display-category-and-taxonomy-list' ),
		);

		$items_html = '';
		foreach ( $features as $feature ) {
			$items_html .= sprintf( '<li>%s</li>', $feature );
		}

		$build_available = file_exists( DCATL_PATH . 'build/index.js' )
			&& file_exists( DCATL_PATH . 'build/index.css' )
			&& file_exists( DCATL_PATH . 'build/index.asset.php' );

		$build_notice = '';
		if ( ! $build_available ) {
			$build_notice = sprintf(
				'<div class="notice notice-error inline"><p>%s</p></div>',
				esc_html__( 'The compiled admin build is missing. Run the project build command and add the build directory to the plugin.', 'display-category-and-taxonomy-list' )
			);
		}

		$html = sprintf(
			'<div class="dcatl-settings-wrapper">
				<div class="dcatl-admin-settings-main">%1$s<div id="dcatl-admin-settings"></div></div>
				<div class="dcatl-admin-settings-aside">
					<h3>%2$s</h3>
					<h2>%3$s</h2>
					<p>%4$s</p>
					<ul>%5$s</ul>
					<a href="%6$s" class="dcatl-premium-action-btn" target="_blank" rel="noopener noreferrer">%7$s</a>
				</div>
			</div>',
			$build_notice,
			esc_html__( 'Elevate Your Experience', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Display Category and Taxonomy List', 'display-category-and-taxonomy-list' ),
			esc_html__( 'Our suite of features gives you control over layout, appearance, and content management, with usability and performance in mind.', 'display-category-and-taxonomy-list' ),
			$items_html,
			esc_url( 'https://dcatl.diviaccessories.com/' ),
			esc_html__( 'Learn More', 'display-category-and-taxonomy-list' )
		);

		echo wp_kses(
			$html,
			array(
				'div' => array(
					'class' => true,
					'id'    => true,
				),
				'h2' => array(),
				'h3' => array(),
				'p'  => array(),
				'ul' => array(),
				'li' => array(),
				'a'  => array(
					'href'   => true,
					'class'  => true,
					'target' => true,
					'rel'    => true,
				),
			)
		);
	}

	/**
	 * Render the category/taxonomy list shortcode.
	 *
	 * @param array $atts Shortcode attributes. Reserved for future support.
	 * @return string
	 */
	public function category_list_image_shortcode_func( $atts = array() ) {
		unset( $atts );

		$action = Action::get_instance();
		$action->enqueue_frontend_assets();

		$settings = apply_filters( 'dcatl_admin_style_settings', array() );
		$settings = is_array( $settings ) ? $settings : $action->get_settings();

		$taxonomy_list = isset( $settings['dcatl_taxonomy_list'] ) && is_array( $settings['dcatl_taxonomy_list'] )
			? array_values( array_filter( $settings['dcatl_taxonomy_list'] ) )
			: array();
		$taxonomy_slug = ! empty( $taxonomy_list ) ? sanitize_key( $taxonomy_list[0] ) : 'category';

		$taxonomy_object = get_taxonomy( $taxonomy_slug );
		if ( ! $taxonomy_object || ! $taxonomy_object->public ) {
			return $this->get_empty_shortcode_markup();
		}

		$template_style        = isset( $settings['dcatl_template_style'] ) && in_array( (string) $settings['dcatl_template_style'], array( '1', '2' ), true ) ? (string) $settings['dcatl_template_style'] : '1';
		$wrapper_custom_height = ! empty( $settings['dcatl_wrapper_height_auto'] ) ? '' : 'dcatl-custom-height';
		$item_order_by         = isset( $settings['dcatl_item_order_by'] ) ? (string) $settings['dcatl_item_order_by'] : 'name';
		$item_order            = isset( $settings['dcatl_item_order'] ) && 'DESC' === strtoupper( (string) $settings['dcatl_item_order'] ) ? 'DESC' : 'ASC';
		$hide_empty            = ! empty( $settings['dcatl_hide_empty_cat'] );
		$hide_children         = ! empty( $settings['dcatl_hide_child_item'] );
		$hide_uncategorized    = ! empty( $settings['dcatl_hide_uncategorized'] );

		$allowed_orderby = array( 'name', 'slug', 'term_id', 'id', 'count', 'description', 'parent', 'none', 'term_order' );
		if ( ! in_array( $item_order_by, $allowed_orderby, true ) ) {
			$item_order_by = 'name';
		}

		$terms_args = array(
			'taxonomy'   => $taxonomy_slug,
			'hide_empty' => $hide_empty,
			'orderby'    => $item_order_by,
			'order'      => $item_order,
		);

		if ( $hide_children && is_taxonomy_hierarchical( $taxonomy_slug ) ) {
			$terms_args['parent'] = 0;
		}

		$terms = get_terms( $terms_args );
		if ( is_wp_error( $terms ) || empty( $terms ) ) {
			return $this->get_empty_shortcode_markup( $template_style, $wrapper_custom_height );
		}

		$default_category_id = 'category' === $taxonomy_slug ? absint( get_option( 'default_category' ) ) : 0;
		$term_list           = '';

		foreach ( $terms as $term ) {
			if ( $hide_uncategorized && $default_category_id && $default_category_id === (int) $term->term_id ) {
				continue;
			}

			ob_start();
			do_action( 'dcatl_render_item', $term, $settings );
			$term_list .= ob_get_clean();
		}

		if ( '' === trim( $term_list ) ) {
			return $this->get_empty_shortcode_markup( $template_style, $wrapper_custom_height );
		}

		$html = sprintf(
			'<ul class="dcatl-terms-wrapper dcatl-style-%1$s %2$s">%3$s</ul>',
			esc_attr( $template_style ),
			esc_attr( $wrapper_custom_height ),
			$term_list
		);

		return wp_kses( $html, $this->get_shortcode_allowed_html() );
	}

	/**
	 * Render one validated template file.
	 *
	 * @param \WP_Term $term Term object.
	 * @param array    $settings Settings array.
	 * @return void
	 */
	public function render_list_item( $term, $settings ) {
		if ( ! $term instanceof \WP_Term || ! is_array( $settings ) ) {
			return;
		}

		$template_style = isset( $settings['dcatl_template_style'] ) ? (string) $settings['dcatl_template_style'] : '1';
		if ( ! in_array( $template_style, array( '1', '2' ), true ) ) {
			$template_style = '1';
		}

		$template_file = DCATL_PATH . 'public/template/style-' . $template_style . '/index.php';
		if ( file_exists( $template_file ) && is_readable( $template_file ) ) {
			include $template_file;
		}
	}

	/**
	 * Display the term image field on add-term screens.
	 *
	 * @param string $taxonomy Current taxonomy slug.
	 * @return void
	 */
	public function add_term_image_field( $taxonomy ) {
		unset( $taxonomy );
		?>
		<div class="form-field term-description-wrap dcatl-uploader-wrapper">
			<label for="dcatl_upload_image"><?php esc_html_e( 'Term image', 'display-category-and-taxonomy-list' ); ?></label>
			<button type="button" class="button dcatl-upload-image-button" aria-label="<?php esc_attr_e( 'Choose a term image', 'display-category-and-taxonomy-list' ); ?>">
				<img id="dcatl_upload_image_btn" src="<?php echo esc_url( $this->placeholder ); ?>" alt="<?php esc_attr_e( 'Term image preview', 'display-category-and-taxonomy-list' ); ?>">
			</button>
			<input type="hidden" name="dcatl_term_image" id="dcatl_upload_image" value="">
			<button type="button" class="button-link-delete dcatl_image_remove"><?php esc_html_e( 'Remove image', 'display-category-and-taxonomy-list' ); ?></button>
			<?php wp_nonce_field( 'dcatl_nonce_action', 'dcatl_nonce_field' ); ?>
			<p><?php esc_html_e( 'Choose an image to represent this term in the category list.', 'display-category-and-taxonomy-list' ); ?></p>
		</div>
		<?php
	}

	/**
	 * Save a term image after creating a term.
	 *
	 * @param int $term_id Term ID.
	 * @param int $term_taxonomy_id Term-taxonomy ID.
	 * @return void
	 */
	public function save_term_image_field_on_create( $term_id, $term_taxonomy_id ) {
		unset( $term_taxonomy_id );
		$this->save_term_image( $term_id );
	}

	/**
	 * Display the term image field on edit-term screens.
	 *
	 * @param \WP_Term $term Current term.
	 * @param string   $taxonomy Current taxonomy slug.
	 * @return void
	 */
	public function add_term_image_field_on_edit( $term, $taxonomy ) {
		unset( $taxonomy );

		$image_id  = absint( get_term_meta( $term->term_id, 'dcatl_term_image', true ) );
		$image_url = $image_id ? wp_get_attachment_image_url( $image_id, 'medium' ) : '';
		$image_url = $image_url ? $image_url : $this->placeholder;
		?>
		<tr class="form-field dcatl-uploader-wrapper">
			<th scope="row"><label for="dcatl_upload_image"><?php esc_html_e( 'Term image', 'display-category-and-taxonomy-list' ); ?></label></th>
			<td>
				<button type="button" class="button dcatl-upload-image-button" aria-label="<?php esc_attr_e( 'Choose a term image', 'display-category-and-taxonomy-list' ); ?>">
					<img id="dcatl_upload_image_btn" src="<?php echo esc_url( $image_url ); ?>" alt="<?php esc_attr_e( 'Term image preview', 'display-category-and-taxonomy-list' ); ?>">
				</button>
				<input type="hidden" name="dcatl_term_image" id="dcatl_upload_image" value="<?php echo esc_attr( $image_id ); ?>">
				<button type="button" class="button-link-delete dcatl_image_remove"><?php esc_html_e( 'Remove image', 'display-category-and-taxonomy-list' ); ?></button>
				<?php wp_nonce_field( 'dcatl_nonce_action', 'dcatl_nonce_field' ); ?>
				<p class="description"><?php esc_html_e( 'Choose an image to represent this term in the category list.', 'display-category-and-taxonomy-list' ); ?></p>
			</td>
		</tr>
		<?php
	}

	/**
	 * Update a term image after editing a term.
	 *
	 * @param int $term_id Term ID.
	 * @param int $term_taxonomy_id Term-taxonomy ID.
	 * @return void
	 */
	public function update_term_image_field_on_edit( $term_id, $term_taxonomy_id ) {
		unset( $term_taxonomy_id );
		$this->save_term_image( $term_id );
	}

	/**
	 * Add the image column to taxonomy tables.
	 *
	 * @param array $columns Existing columns.
	 * @return array
	 */
	public function add_term_image_column( $columns ) {
		$new_columns = array();
		$position    = 0;

		foreach ( $columns as $key => $value ) {
			if ( 1 === $position ) {
				$new_columns['dcatl_term_image'] = esc_html__( 'Image', 'display-category-and-taxonomy-list' );
			}
			$new_columns[ $key ] = $value;
			++$position;
		}

		return $new_columns;
	}

	/**
	 * Display the image column value.
	 *
	 * @param string $output Existing output.
	 * @param string $column_name Column name.
	 * @param int    $term_id Term ID.
	 * @return string
	 */
	public function display_term_image_column( $output, $column_name, $term_id ) {
		if ( 'dcatl_term_image' !== $column_name ) {
			return $output;
		}

		$image_id = absint( get_term_meta( $term_id, 'dcatl_term_image', true ) );
		if ( $image_id && wp_attachment_is_image( $image_id ) ) {
			$image = wp_get_attachment_image(
				$image_id,
				array( 60, 60 ),
				false,
				array(
					'class' => 'category-image-thumb',
					'alt'   => esc_attr__( 'Term image', 'display-category-and-taxonomy-list' ),
				)
			);

			return $image ? $image : $output;
		}

		return sprintf(
			'<img class="category-image-thumb" src="%1$s" alt="%2$s">',
			esc_url( $this->placeholder ),
			esc_attr__( 'No term image selected', 'display-category-and-taxonomy-list' )
		);
	}

	/**
	 * Save or remove a validated image attachment ID.
	 *
	 * @param int $term_id Term ID.
	 * @return void
	 */
	private function save_term_image( $term_id ) {
		if ( ! isset( $_POST['dcatl_nonce_field'], $_POST['dcatl_term_image'] ) ) {
			return;
		}

		$nonce = sanitize_text_field( wp_unslash( $_POST['dcatl_nonce_field'] ) );
		if ( ! wp_verify_nonce( $nonce, 'dcatl_nonce_action' ) || ! $this->current_user_can_edit_term( $term_id ) ) {
			return;
		}

		$image_id = absint( wp_unslash( $_POST['dcatl_term_image'] ) );
		if ( 0 === $image_id ) {
			delete_term_meta( $term_id, 'dcatl_term_image' );
			return;
		}

		if ( 'attachment' !== get_post_type( $image_id ) || ! wp_attachment_is_image( $image_id ) ) {
			return;
		}

		update_term_meta( $term_id, 'dcatl_term_image', $image_id );
	}

	/**
	 * Check the taxonomy capability for a term.
	 *
	 * @param int $term_id Term ID.
	 * @return bool
	 */
	private function current_user_can_edit_term( $term_id ) {
		$term = get_term( $term_id );
		if ( is_wp_error( $term ) || ! $term ) {
			return false;
		}

		$taxonomy = get_taxonomy( $term->taxonomy );
		return $taxonomy && isset( $taxonomy->cap->edit_terms ) && current_user_can( $taxonomy->cap->edit_terms );
	}

	/**
	 * Return empty-state shortcode markup.
	 *
	 * @param string $template_style Template ID.
	 * @param string $height_class Optional height class.
	 * @return string
	 */
	private function get_empty_shortcode_markup( $template_style = '1', $height_class = '' ) {
		return sprintf(
			'<ul class="dcatl-terms-wrapper dcatl-style-%1$s %2$s"><li class="dcatl-empty-message">%3$s</li></ul>',
			esc_attr( $template_style ),
			esc_attr( $height_class ),
			esc_html__( 'No terms found.', 'display-category-and-taxonomy-list' )
		);
	}

	/**
	 * Allowed HTML for the shortcode output.
	 *
	 * @return array
	 */
	private function get_shortcode_allowed_html() {
		return array(
			'ul'   => array( 'class' => true ),
			'li'   => array( 'class' => true ),
			'div'  => array(
				'class'       => true,
				'style'       => true,
				'aria-hidden' => true,
			),
			'span' => array( 'class' => true ),
			'h3'   => array( 'class' => true ),
			'p'    => array( 'class' => true ),
			'a'    => array(
				'href'       => true,
				'title'      => true,
				'class'      => true,
				'aria-label' => true,
			),
			'img'  => array(
				'src'      => true,
				'alt'      => true,
				'class'    => true,
				'width'    => true,
				'height'   => true,
				'loading'  => true,
				'decoding' => true,
				'srcset'   => true,
				'sizes'    => true,
			),
		);
	}
}
