<?php
defined( 'ABSPATH' ) || exit;

/**
 * Breadcrumbs — the trail from the site root to the current page.
 *
 * Emits schema.org BreadcrumbList microdata so search engines can render the
 * trail in results, and marks the current item with aria-current so screen
 * readers announce position rather than offering a link to the current page.
 *
 * The trail is derived at render time from the queried object, so it always
 * reflects the real page rather than anything stored in the builder.
 */
class Jalpi_Element_Breadcrumbs extends Jalpi_Element {

	public static function type(): string {
		return 'breadcrumbs';
	}

	/** Ancestor walk guard — a corrupt parent chain must not loop forever. */
	private const MAX_ANCESTORS = 20;

	public function render( array $node, Jalpi_Renderer $renderer ): string {
		$id       = sanitize_html_class( $node['id'] ?? '' );
		$content  = $node['content']  ?? [];
		$styles   = $node['styles']   ?? [];
		$settings = $node['settings'] ?? [];
		$a        = $renderer->get_css_attrs( $node );

		$separator = (string) ( $content['separator'] ?? 'chevron' );
		if ( ! in_array( $separator, [ 'chevron', 'slash', 'arrow', 'dot', 'pipe' ], true ) ) {
			$separator = 'chevron';
		}

		$home_label = sanitize_text_field( $content['homeLabel'] ?? __( 'Home', 'jalpi-page-builder' ) );
		$show_home  = ! isset( $content['showHome'] ) || ! empty( $content['showHome'] );
		$show_current = ! isset( $content['showCurrent'] ) || ! empty( $content['showCurrent'] );

		$crumbs = $this->build_trail( $show_home, $home_label );

		// In the editor there is no real query, so show a representative trail
		// rather than an empty element the user cannot see or style.
		if ( count( $crumbs ) < 2 && ! is_admin() && ! $show_current ) {
			return '';
		}

		if ( ! $show_current && count( $crumbs ) > 1 ) {
			array_pop( $crumbs );
		}

		if ( empty( $crumbs ) ) {
			return '';
		}

		$this->emit_css( $renderer, $id, $styles, $settings );

		$sep_char = $this->separator_char( $separator );
		$aria     = sanitize_text_field( $content['ariaLabel'] ?? __( 'Breadcrumb', 'jalpi-page-builder' ) );

		$html = '<nav class="jalpi-el jalpi-breadcrumbs jalpi-' . esc_attr( $id ) . $a['extra_cls'] . '"'
			. $a['id_attr'] . ' aria-label="' . esc_attr( $aria ) . '">';

		$html .= '<ol class="jalpi-breadcrumbs__list" itemscope itemtype="https://schema.org/BreadcrumbList">';

		$total = count( $crumbs );
		foreach ( $crumbs as $i => $crumb ) {
			$is_last = ( $i === $total - 1 );

			$html .= '<li class="jalpi-breadcrumbs__item' . ( $is_last ? ' is-current' : '' ) . '"'
				. ' itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">';

			if ( $is_last || '' === $crumb['url'] ) {
				// The current page is not a link — offering one that goes
				// nowhere is a common accessibility complaint.
				$html .= '<span class="jalpi-breadcrumbs__current" itemprop="name"'
					. ( $is_last ? ' aria-current="page"' : '' ) . '>'
					. esc_html( $crumb['label'] ) . '</span>';
			} else {
				$html .= '<a class="jalpi-breadcrumbs__link" href="' . esc_url( $crumb['url'] ) . '" itemprop="item">'
					. '<span itemprop="name">' . esc_html( $crumb['label'] ) . '</span>'
					. '</a>';
			}

			$html .= '<meta itemprop="position" content="' . ( $i + 1 ) . '" />';

			if ( ! $is_last ) {
				$html .= '<span class="jalpi-breadcrumbs__sep" aria-hidden="true">'
					. esc_html( $sep_char ) . '</span>';
			}

			$html .= '</li>';
		}

		return $html . '</ol></nav>';
	}

	/**
	 * Build the trail for whatever is currently queried.
	 *
	 * @return array<int,array{label:string,url:string}>
	 */
	private function build_trail( bool $show_home, string $home_label ): array {
		$crumbs = [];

		if ( $show_home ) {
			$crumbs[] = [ 'label' => $home_label, 'url' => home_url( '/' ) ];
		}

		// Admin/editor preview: no main query to inspect, so show a sample
		// trail that demonstrates the separator and styling.
		if ( is_admin() || ! did_action( 'wp' ) ) {
			$crumbs[] = [ 'label' => __( 'Parent Page', 'jalpi-page-builder' ), 'url' => home_url( '/' ) ];
			$crumbs[] = [ 'label' => __( 'Current Page', 'jalpi-page-builder' ), 'url' => '' ];
			return $crumbs;
		}

		if ( is_front_page() ) {
			return $crumbs;
		}

		if ( is_singular() ) {
			$post_id = get_queried_object_id();

			// Products sit under the shop page, which is not a post ancestor.
			if ( 'product' === get_post_type( $post_id ) && function_exists( 'wc_get_page_id' ) ) {
				$shop = wc_get_page_id( 'shop' );
				if ( $shop > 0 ) {
					$crumbs[] = [ 'label' => get_the_title( $shop ), 'url' => get_permalink( $shop ) ];
				}
			} elseif ( 'post' === get_post_type( $post_id ) ) {
				// Primary category gives blog posts a meaningful parent.
				$cats = get_the_category( $post_id );
				if ( ! empty( $cats[0] ) ) {
					$crumbs[] = [ 'label' => $cats[0]->name, 'url' => get_category_link( $cats[0]->term_id ) ];
				}
			}

			foreach ( $this->ancestors( $post_id ) as $ancestor_id ) {
				$crumbs[] = [
					'label' => get_the_title( $ancestor_id ),
					'url'   => (string) get_permalink( $ancestor_id ),
				];
			}

			$crumbs[] = [ 'label' => get_the_title( $post_id ), 'url' => '' ];
			return $crumbs;
		}

		if ( is_category() || is_tag() || is_tax() ) {
			$term = get_queried_object();
			if ( $term instanceof WP_Term ) {
				foreach ( array_reverse( get_ancestors( $term->term_id, $term->taxonomy ) ) as $anc_id ) {
					$anc = get_term( $anc_id, $term->taxonomy );
					if ( $anc instanceof WP_Term ) {
						$crumbs[] = [ 'label' => $anc->name, 'url' => (string) get_term_link( $anc ) ];
					}
				}
				$crumbs[] = [ 'label' => $term->name, 'url' => '' ];
			}
			return $crumbs;
		}

		if ( is_search() ) {
			$crumbs[] = [
				/* translators: %s: search query. */
				'label' => sprintf( __( 'Search results for “%s”', 'jalpi-page-builder' ), get_search_query() ),
				'url'   => '',
			];
			return $crumbs;
		}

		if ( is_404() ) {
			$crumbs[] = [ 'label' => __( 'Page not found', 'jalpi-page-builder' ), 'url' => '' ];
			return $crumbs;
		}

		if ( is_author() ) {
			$crumbs[] = [ 'label' => get_the_author_meta( 'display_name', get_queried_object_id() ), 'url' => '' ];
			return $crumbs;
		}

		if ( is_archive() ) {
			$crumbs[] = [ 'label' => wp_strip_all_tags( get_the_archive_title() ), 'url' => '' ];
			return $crumbs;
		}

		if ( is_home() ) {
			$blog_id = (int) get_option( 'page_for_posts' );
			if ( $blog_id ) {
				$crumbs[] = [ 'label' => get_the_title( $blog_id ), 'url' => '' ];
			}
		}

		return $crumbs;
	}

	/**
	 * Post ancestors, outermost first, with a hard depth cap.
	 *
	 * @return array<int,int>
	 */
	private function ancestors( int $post_id ): array {
		$out    = [];
		$parent = (int) wp_get_post_parent_id( $post_id );
		$guard  = 0;

		while ( $parent > 0 && $guard++ < self::MAX_ANCESTORS ) {
			$out[]  = $parent;
			$parent = (int) wp_get_post_parent_id( $parent );
		}

		return array_reverse( $out );
	}

	private function separator_char( string $key ): string {
		$map = [
			'chevron' => '›',
			'slash'   => '/',
			'arrow'   => '→',
			'dot'     => '·',
			'pipe'    => '|',
		];
		return $map[ $key ] ?? '›';
	}

	private function emit_css( Jalpi_Renderer $renderer, string $id, array $styles, array $settings ): void {
		$sel = '.jalpi-el.jalpi-' . $id;
		$css = '';

		$base = $renderer->styles_to_css( $styles );
		if ( $base ) {
			$css .= "{$sel}{{$base}}";
		}

		$link = '';
		$colour = Jalpi_Sanitizer::sanitize_color( $settings['bc_link_color'] ?? '' );
		if ( $colour ) {
			$link .= 'color:' . $colour . ';';
		}
		if ( $link ) {
			$css .= "{$sel}.jalpi-breadcrumbs .jalpi-breadcrumbs__link{{$link}}";
		}

		$hover = Jalpi_Sanitizer::sanitize_color( $settings['bc_link_hover'] ?? '' );
		if ( $hover ) {
			$css .= "{$sel}.jalpi-breadcrumbs .jalpi-breadcrumbs__link:hover{color:{$hover};}";
		}

		$current = Jalpi_Sanitizer::sanitize_color( $settings['bc_current_color'] ?? '' );
		if ( $current ) {
			$css .= "{$sel}.jalpi-breadcrumbs .jalpi-breadcrumbs__current{color:{$current};}";
		}

		$sep_colour = Jalpi_Sanitizer::sanitize_color( $settings['bc_sep_color'] ?? '' );
		if ( $sep_colour ) {
			$css .= "{$sel}.jalpi-breadcrumbs .jalpi-breadcrumbs__sep{color:{$sep_colour};}";
		}

		$gap = $this->len( $settings['bc_gap'] ?? '' );
		if ( $gap ) {
			$css .= "{$sel}.jalpi-breadcrumbs .jalpi-breadcrumbs__list{gap:{$gap};}";
		}

		$size = $this->len( $settings['bc_font_size'] ?? '' );
		if ( $size ) {
			$css .= "{$sel}.jalpi-breadcrumbs{font-size:{$size};}";
		}

		if ( $css ) {
			$renderer->add_css( $css );
		}
	}

	/** Only well-formed lengths reach the stylesheet. */
	private function len( $value ): string {
		$value = trim( (string) $value );
		return preg_match( '/^-?\d+(\.\d+)?(px|em|rem|%)$/', $value ) ? $value : '';
	}
}
