<?php
/**
 * Sitemap Builder
 *
 * Builds and caches all sitemap files atomically.
 *
 * @package SEOvaultSEO
 */

namespace SEOvaultSEO\Sitemap;

use SEOvaultSEO\Core\Options;

/**
 * Builds sitemap cache files
 */
class Builder {

	/**
	 * Rebuild the entire sitemap cache.
	 *
	 * @param bool $force Force rebuild.
	 * @return bool
	 */
	public static function rebuild( $force = false ) {
		if ( ! $force && Cache::is_rebuild_locked() ) {
			return false;
		}

		Cache::clear_rebuild_lock();

		if ( ! Cache::begin_atomic_rebuild( 'sitemap' ) ) {
			return false;
		}

		try {
			Cache::clear_all();

			$post_types = Options::get_sitemap_post_types();
			foreach ( $post_types as $post_type ) {
				self::rebuild_for_post_type( $post_type );
			}

			$taxonomies = Options::get_sitemap_taxonomies();
			foreach ( $taxonomies as $taxonomy ) {
				self::rebuild_for_taxonomy( $taxonomy );
			}

			if ( Options::is_sitemap_users_enabled() ) {
				self::rebuild_for_users();
			}

			self::rebuild_for_archives();

			self::build_index();

			Cache::commit_atomic_rebuild( 'sitemap' );
			Options::set_sitemap_last_generated( time() );
			return true;
		} catch ( \Exception $e ) {
			Cache::abort_atomic_rebuild( 'sitemap' );
			if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
				// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
				error_log( 'SEOvault sitemap rebuild failed: ' . $e->getMessage() );
			}
			return false;
		}
	}

	/**
	 * Rebuild cache for a specific post type.
	 *
	 * @param string $post_type Post type.
	 */
	public static function rebuild_for_post_type( $post_type ) {
		$post_type = Sanitizer::slug( $post_type );
		if ( '' === $post_type ) {
			return;
		}

		$per_page = Options::get_sitemap_entries_per_page();
		$count    = Query::get_post_type_count( $post_type );
		$pages    = max( 1, (int) ceil( $count / $per_page ) );

		for ( $page = 1; $page <= $pages; $page++ ) {
			$urls = PostType::build_urls( $post_type, $page );
			$xml  = Renderer::urlset( $urls );
			Cache::store( 'sitemap/' . $post_type . '-page-' . $page . '.xml', $xml );
			Cache::store( 'sitemap/' . $post_type . '-page-' . $page . '.json', wp_json_encode( $urls, JSON_PRETTY_PRINT ) );
		}
	}

	/**
	 * Rebuild cache for a specific taxonomy.
	 *
	 * @param string $taxonomy Taxonomy.
	 */
	public static function rebuild_for_taxonomy( $taxonomy ) {
		$taxonomy = Sanitizer::slug( $taxonomy );
		if ( '' === $taxonomy ) {
			return;
		}

		$per_page = Options::get_sitemap_entries_per_page();
		$count    = Query::get_term_count( $taxonomy );
		$pages    = max( 1, (int) ceil( $count / $per_page ) );

		for ( $page = 1; $page <= $pages; $page++ ) {
			$urls = Taxonomy::build_urls( $taxonomy, $page );
			$xml  = Renderer::urlset( $urls );
			Cache::store( 'sitemap/taxonomy-' . $taxonomy . '-page-' . $page . '.xml', $xml );
			Cache::store( 'sitemap/taxonomy-' . $taxonomy . '-page-' . $page . '.json', wp_json_encode( $urls, JSON_PRETTY_PRINT ) );
		}
	}

	/**
	 * Rebuild cache for users.
	 */
	public static function rebuild_for_users() {
		$per_page = Options::get_sitemap_entries_per_page();
		$count    = Query::get_user_count();
		$pages    = max( 1, (int) ceil( $count / $per_page ) );

		for ( $page = 1; $page <= $pages; $page++ ) {
			$urls = User::build_urls( $page );
			$xml  = Renderer::urlset( $urls );
			Cache::store( 'sitemap/users-page-' . $page . '.xml', $xml );
			Cache::store( 'sitemap/users-page-' . $page . '.json', wp_json_encode( $urls, JSON_PRETTY_PRINT ) );
		}
	}

	/**
	 * Rebuild cache for post-type archives.
	 */
	public static function rebuild_for_archives() {
		$urls = Archives::build_urls();
		if ( empty( $urls ) ) {
			Cache::delete( 'sitemap/' . Archives::SLUG . '-page-1.xml' );
			Cache::delete( 'sitemap/' . Archives::SLUG . '-page-1.json' );
			return;
		}

		$xml = Renderer::urlset( $urls );
		Cache::store( 'sitemap/' . Archives::SLUG . '-page-1.xml', $xml );
		Cache::store( 'sitemap/' . Archives::SLUG . '-page-1.json', wp_json_encode( $urls, JSON_PRETTY_PRINT ) );
	}

	/**
	 * Build and store the unified index.
	 */
	public static function build_index() {
		$index = Index::build();
		Cache::store( 'unified_index.json', wp_json_encode( $index, JSON_PRETTY_PRINT ) );
	}

	/**
	 * Calculate the number of pages for a total count.
	 *
	 * @param int $count Total count.
	 * @param int $per_page Per page.
	 * @return int
	 */
	public static function calculate_page_count( $count, $per_page ) {
		$count    = (int) $count;
		$per_page = max( 1, (int) $per_page );
		return max( 1, (int) ceil( $count / $per_page ) );
	}

	/**
	 * Build the index data structure.
	 *
	 * @return array
	 */
	public static function build_index_data() {
		return Index::build();
	}

	/**
	 * Quick partial invalidation helper for a post.
	 *
	 * @param int $post_id Post ID.
	 */
	public static function rebuild_for_post( $post_id ) {
		$post = get_post( $post_id );
		if ( ! $post ) {
			return;
		}
		self::rebuild_for_post_type( $post->post_type );

		$object = get_post_type_object( $post->post_type );
		if ( $object && ! empty( $object->has_archive ) ) {
			self::rebuild_for_archives();
			self::build_index();
		}
	}

	/**
	 * Quick partial invalidation helper for a term.
	 *
	 * @param string $taxonomy Taxonomy.
	 * @param int    $term_id Term ID.
	 */
	public static function rebuild_for_term( $taxonomy, $term_id ) {
		self::rebuild_for_taxonomy( $taxonomy );
	}
}
