<?php
/**
 * Odysseo SEO — lightweight XML sitemap at /odysseo-sitemap.xml.
 *
 * Lists the home page plus published Posts, Pages and the Destination / Tour
 * Package / Fleet custom post types, each with a <lastmod>.
 *
 * The endpoint is matched directly on parse_request (before WordPress's canonical
 * redirect), so it works on any permalink setting with no rewrite flush needed.
 *
 * @package    Odysseo
 * @author     Chandrabhan Shekhawat
 * @company    Gigai Kripa Services
 * @link       https://gigaikripaservices.com/
 * @copyright  Copyright (c) 2026, Gigai Kripa Services
 */

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

/**
 * Serves the sitemap.
 */
class Odysseo_SEO_Sitemap {

	const PATH = 'odysseo-sitemap.xml';

	/**
	 * Hook up.
	 */
	public function __construct() {
		add_action( 'parse_request', array( $this, 'maybe_render' ) );
		add_filter( 'robots_txt', array( $this, 'robots' ), 10, 2 );
	}

	/**
	 * Advertise the sitemap in robots.txt.
	 *
	 * @param string $output Existing robots.txt.
	 * @param bool   $public Whether the site is public.
	 * @return string
	 */
	public function robots( $output, $public ) {
		if ( $public ) {
			$output .= 'Sitemap: ' . esc_url( home_url( '/' . self::PATH ) ) . "\n";
		}
		return $output;
	}

	/**
	 * Post types included. Filterable.
	 *
	 * @return string[]
	 */
	private function post_types() {
		return apply_filters( 'odysseo_seo_sitemap_post_types', array( 'post', 'page', 'destination', 'tour_package', 'fleet' ) );
	}

	/**
	 * Render the sitemap when the request path matches.
	 */
	public function maybe_render() {
		$path = '';
		if ( isset( $_SERVER['REQUEST_URI'] ) ) {
			$path = (string) wp_parse_url( esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ), PHP_URL_PATH );
		}
		if ( trim( $path, '/' ) !== self::PATH ) {
			return;
		}

		$posts = get_posts(
			array(
				'post_type'              => $this->post_types(),
				'post_status'            => 'publish',
				'posts_per_page'         => 2000,
				'orderby'                => 'modified',
				'order'                  => 'DESC',
				'no_found_rows'          => true,
				'ignore_sticky_posts'    => true,
				'update_post_meta_cache' => false,
				'update_post_term_cache' => false,
			)
		);

		if ( ! headers_sent() ) {
			status_header( 200 );
			header( 'Content-Type: application/xml; charset=UTF-8' );
			header( 'X-Robots-Tag: noindex, follow', true );
		}

		echo '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
		echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";

		$this->url( home_url( '/' ), '' );
		foreach ( $posts as $p ) {
			$this->url( get_permalink( $p ), get_post_modified_time( 'c', true, $p ) );
		}

		echo '</urlset>';
		exit;
	}

	/**
	 * Print one <url> entry.
	 *
	 * @param string $loc     Absolute URL.
	 * @param string $lastmod ISO-8601 date or ''.
	 */
	private function url( $loc, $lastmod ) {
		echo "\t<url>\n";
		echo "\t\t<loc>" . esc_url( $loc ) . "</loc>\n";
		if ( $lastmod ) {
			echo "\t\t<lastmod>" . esc_html( $lastmod ) . "</lastmod>\n";
		}
		echo "\t</url>\n";
	}
}
