<?php

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

if ( class_exists( 'AIEO_SEO_Sitemap', false ) ) {
	return;
}

class AIEO_SEO_Sitemap {

	const DIR_NAME   = 'aieo-sitemaps';
	const SHARD_SIZE = 2000;
	const BUILT_OPT  = 'aieo_seo_sitemap_built_at';

	
	const ROBOTS_MARKER = '# Managed by AI eShop Optimizer';

	
	const ROBOTS_CUSTOM_OPT = 'aieo_seo_robots_custom';

	
	public static function dir() {
		$up = wp_upload_dir();
		return trailingslashit( $up['basedir'] ) . self::DIR_NAME;
	}

	
	public static function url() {
		$up = wp_upload_dir();
		return trailingslashit( $up['baseurl'] ) . self::DIR_NAME;
	}

	
	public static function index_url() {
		return home_url( '/sitemap.xml' );
	}

	
	
	

	public static function register() {
		static $done = false;
		if ( $done ) {
			return;
		}
		$done = true;
		add_action( 'init', array( __CLASS__, 'maybe_serve' ), 1 );
		add_filter( 'robots_txt', array( __CLASS__, 'robots_txt' ), 10, 2 );
		add_filter( 'wp_sitemaps_enabled', array( __CLASS__, 'maybe_disable_core_sitemap' ) );
		
		
		
		add_action( 'update_option_blog_public', array( __CLASS__, 'sync_robots' ) );
		add_action( 'add_option_blog_public', array( __CLASS__, 'sync_robots' ) );
	}

	
	public static function sync_robots() {
		if ( self::is_active() ) {
			self::write_robots();
		}
	}

	
	public static function maybe_disable_core_sitemap( $enabled ) {
		return self::is_active() ? false : $enabled;
	}

	
	public static function maybe_serve() {
		if ( is_admin() ) {
			return;
		}
		$uri = isset( $_SERVER['REQUEST_URI'] )
			? (string) wp_parse_url( wp_unslash( $_SERVER['REQUEST_URI'] ), PHP_URL_PATH )
			: '';

		
		
		if ( '/robots.txt' === $uri ) {
			if ( ! self::is_active() ) {
				return;
			}
			if ( ! headers_sent() ) {
				header( 'Content-Type: text/plain; charset=UTF-8' );
			}
			$file = self::robots_file();
			if ( is_readable( $file ) ) {
				readfile( $file ); 
			} else {
				echo self::robots_body(); 
			}
			exit;
		}

		if ( '/sitemap.xml' !== $uri ) {
			return;
		}
		
		
		if ( ! self::is_active() ) {
			return;
		}
		$file = self::dir() . '/sitemap.xml';
		if ( ! is_readable( $file ) ) {
			return;
		}
		if ( ! headers_sent() ) {
			header( 'Content-Type: application/xml; charset=UTF-8' );
			header( 'X-Robots-Tag: noindex, follow', true );
		}
		readfile( $file ); 
		exit;
	}

	
	public static function robots_txt( $output, $public ) {
		if ( self::is_active() ) {
			$output .= "\nSitemap: " . esc_url( self::index_url() ) . "\n";
		}
		return $output;
	}

	
	private static function robots_file() {
		return trailingslashit( ABSPATH ) . 'robots.txt';
	}

	
	public static function robots_body() {
		$body   = self::robots_default_body();
		$custom = trim( (string) get_option( self::ROBOTS_CUSTOM_OPT, '' ) );
		if ( '' !== $custom ) {
			$body .= "\n# --- Custom rules (SEO -> Redirects) ---\n" . $custom . "\n";
		}
		return $body;
	}

	
	public static function robots_default_body() {
		$public   = get_option( 'blog_public' );
		$site_url = wp_parse_url( site_url() );
		$path     = ! empty( $site_url['path'] ) ? $site_url['path'] : '';
		if ( '0' === (string) $public ) {
			$body = "User-agent: *\nDisallow: /\n";
		} else {
			$body  = "User-agent: *\n";
			$body .= 'Disallow: ' . $path . "/wp-admin/\n";
			$body .= 'Allow: ' . $path . "/wp-admin/admin-ajax.php\n";
		}
		
		
		
		
		$filtered = apply_filters( 'robots_txt', $body, $public );
		if ( is_string( $filtered ) && '' !== trim( $filtered ) ) {
			$body = $filtered;
		}
		return self::ROBOTS_MARKER . " — regenerated automatically; add your own rules in WP-Admin -> SEO -> Redirects.\n" . rtrim( $body ) . "\n";
	}

	
	private static function write_robots() {
		$file = self::robots_file();
		if ( is_file( $file ) ) {
			$head = (string) @file_get_contents( $file, false, null, 0, 256 ); 
			if ( false === strpos( $head, self::ROBOTS_MARKER ) ) {
				return false; 
			}
		}
		return self::write_atomic( $file, self::robots_body() );
	}

	
	
	

	
	public static function build() {
		if ( ! self::is_active() ) {
			self::remove();
			return array( 'shards' => 0, 'urls' => 0, 'active' => false );
		}

		$dir = self::dir();
		if ( ! wp_mkdir_p( $dir ) ) {
			return array( 'shards' => 0, 'urls' => 0, 'active' => true, 'error' => 'mkdir' );
		}

		global $wpdb;
		$t       = $wpdb->prefix . 'aieo_seo_posts';
		$vt      = $wpdb->prefix . 'aieo_core_product_vitals';
		$home    = trailingslashit( home_url() );
		$last_id = 0;
		$shard   = 0;
		$total   = 0;
		$index   = array();

		do {
			
			
			
			
			$rows = $wpdb->get_results(
				$wpdb->prepare(
					"SELECT sp.id, sp.canonical_url, sp.sitemap_priority, sp.sitemap_frequency, sp.updated, sp.og_image_url,
					        v.image_url AS vitals_image
					 FROM `{$t}` sp
					 LEFT JOIN `{$vt}` v ON v.product_id = sp.object_id AND sp.object_type = 'product' AND v.product_id = v.parent_product_id
					 WHERE sp.id > %d AND sp.canonical_url <> '' AND sp.indexable = 1
					 ORDER BY sp.id ASC LIMIT %d",
					$last_id,
					self::SHARD_SIZE
				),
				ARRAY_A
			);
			$count = is_array( $rows ) ? count( $rows ) : 0;
			if ( 0 === $count ) {
				break;
			}
			$shard++;
			$latest = '';
			self::write_atomic( $dir . '/sitemap-' . $shard . '.xml', self::build_urlset( $rows, $home, $latest ) );
			$index[]  = array( 'n' => $shard, 'lastmod' => $latest );
			$total   += $count;
			$last_id  = (int) $rows[ $count - 1 ]['id'];
		} while ( $count === self::SHARD_SIZE );

		
		
		$loc_latest = '';
		$loc_xml    = self::build_locations_urlset( $loc_latest );
		if ( '' !== $loc_xml ) {
			self::write_atomic( $dir . '/sitemap-locations.xml', $loc_xml );
			$index[] = array( 'file' => 'sitemap-locations.xml', 'lastmod' => $loc_latest );
		} elseif ( is_file( $dir . '/sitemap-locations.xml' ) ) {
			@unlink( $dir . '/sitemap-locations.xml' ); 
		}

		if ( ! empty( $index ) ) {
			self::write_atomic( $dir . '/sitemap.xml', self::build_index( $index ) );
		} else {
			
			
			$latest = '';
			self::write_atomic(
				$dir . '/sitemap.xml',
				self::build_urlset( array( array( 'canonical_url' => '/', 'updated' => current_time( 'mysql', true ) ) ), $home, $latest )
			);
		}
		self::cleanup_stale_shards( $dir, $shard );
		self::write_robots(); 
		update_option( self::BUILT_OPT, time(), false );

		return array( 'shards' => $shard, 'urls' => $total, 'active' => true );
	}

	
	public static function remove() {
		$dir = self::dir();
		if ( is_dir( $dir ) ) {
			foreach ( (array) glob( $dir . '/sitemap*.xml' ) as $f ) {
				if ( is_file( $f ) ) {
					@unlink( $f ); 
				}
			}
		}
		
		
		$rf = self::robots_file();
		if ( is_file( $rf ) ) {
			$head = (string) @file_get_contents( $rf, false, null, 0, 256 ); 
			if ( false !== strpos( $head, self::ROBOTS_MARKER ) ) {
				@unlink( $rf ); 
			}
		}
		delete_option( self::BUILT_OPT );
	}

	
	
	

	private static function is_active() {
		
		
		$competitor = defined( 'AIOSEO_VERSION' ) || class_exists( 'AIOSEO\\Plugin\\Common\\Main', false )
			|| defined( 'WPSEO_VERSION' ) || class_exists( 'WPSEO_Options', false )
			|| defined( 'RANK_MATH_VERSION' ) || class_exists( 'RankMath', false );
		if ( $competitor ) {
			return false;
		}
		$opt = get_option( 'aieo_dmm_settings' );
		return is_array( $opt ) && ! empty( $opt['seo']['enabled'] );
	}

	private static function build_urlset( $rows, $home, &$latest ) {
		$out    = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
		$out   .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">' . "\n";
		$latest = '';
		foreach ( (array) $rows as $r ) {
			$cu = (string) $r['canonical_url'];
			if ( '' === $cu ) {
				continue;
			}
			$loc = ( 0 === strpos( $cu, 'http://' ) || 0 === strpos( $cu, 'https://' ) )
				? $cu
				: $home . ltrim( $cu, '/' );

			$out .= '<url><loc>' . esc_url( $loc ) . '</loc>';

			if ( ! empty( $r['updated'] ) ) {
				$ts = strtotime( $r['updated'] . ' UTC' );
				if ( $ts ) {
					$iso = gmdate( 'c', $ts );
					$out .= '<lastmod>' . esc_html( $iso ) . '</lastmod>';
					if ( $iso > $latest ) {
						$latest = $iso;
					}
				}
			}
			
			$freq = ! empty( $r['sitemap_frequency'] ) ? strtolower( (string) $r['sitemap_frequency'] ) : 'weekly';
			if ( ! in_array( $freq, array( 'always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never' ), true ) ) {
				$freq = 'weekly';
			}
			$out .= '<changefreq>' . esc_html( $freq ) . '</changefreq>';
			$pri  = ( isset( $r['sitemap_priority'] ) && '' !== $r['sitemap_priority'] && null !== $r['sitemap_priority'] )
				? number_format( min( 1.0, max( 0.0, (float) $r['sitemap_priority'] ) ), 1 )
				: '0.5';
			$out .= '<priority>' . esc_html( $pri ) . '</priority>';
			
			
			$img_url = '';
			if ( ! empty( $r['vitals_image'] ) ) {
				$img_url = (string) $r['vitals_image'];
			} elseif ( ! empty( $r['og_image_url'] ) ) {
				$img_url = (string) $r['og_image_url'];
			}
			if ( '' !== $img_url ) {
				$out .= '<image:image><image:loc>' . esc_url( $img_url ) . '</image:loc></image:image>';
			}
			$out .= '</url>' . "\n";
		}
		$out .= '</urlset>';
		return $out;
	}

	
	private static function build_locations_urlset( &$latest ) {
		$latest = '';
		if ( ! class_exists( 'AIEO_Google_Reviews_Locations' ) || ! class_exists( 'AIEO_SEO_Location_Page' ) ) {
			return '';
		}
		$locs = AIEO_Google_Reviews_Locations::list_all( true );
		if ( empty( $locs ) ) {
			return '';
		}
		$rows = array();
		foreach ( $locs as $loc ) {
			$url = (string) AIEO_SEO_Location_Page::url_for( $loc );
			if ( '' === $url ) {
				continue; 
			}
			$lastmod = '';
			if ( ! empty( $loc['updated_at'] ) ) {
				$ts = strtotime( $loc['updated_at'] . ' UTC' );
				if ( $ts ) {
					$lastmod = gmdate( 'c', $ts );
				}
			}
			$rows[] = array( 'loc' => $url, 'lastmod' => $lastmod );
		}
		if ( empty( $rows ) ) {
			return '';
		}
		$out  = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
		$out .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
		foreach ( $rows as $r ) {
			$out .= '<url><loc>' . esc_url( $r['loc'] ) . '</loc>';
			if ( '' !== $r['lastmod'] ) {
				$out .= '<lastmod>' . esc_html( $r['lastmod'] ) . '</lastmod>';
				if ( $r['lastmod'] > $latest ) {
					$latest = $r['lastmod'];
				}
			}
			$out .= '<changefreq>monthly</changefreq><priority>0.6</priority></url>' . "\n";
		}
		$out .= '</urlset>';
		return $out;
	}

	private static function build_index( $index ) {
		$base = trailingslashit( self::url() );
		$out  = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
		$out .= '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
		foreach ( (array) $index as $m ) {
			$file = ! empty( $m['file'] ) ? (string) $m['file'] : 'sitemap-' . (int) $m['n'] . '.xml';
			$out .= '<sitemap><loc>' . esc_url( $base . $file ) . '</loc>';
			if ( ! empty( $m['lastmod'] ) ) {
				$out .= '<lastmod>' . esc_html( (string) $m['lastmod'] ) . '</lastmod>';
			}
			$out .= '</sitemap>' . "\n";
		}
		$out .= '</sitemapindex>';
		return $out;
	}

	
	private static function write_atomic( $path, $contents ) {
		$tmp = $path . '.' . wp_generate_password( 6, false ) . '.tmp';
		if ( false === file_put_contents( $tmp, $contents ) ) { 
			return false;
		}
		if ( ! @rename( $tmp, $path ) ) { 
			@unlink( $tmp ); 
			return false;
		}
		return true;
	}

	
	private static function cleanup_stale_shards( $dir, $current_max ) {
		foreach ( (array) glob( $dir . '/sitemap-*.xml' ) as $f ) {
			if ( preg_match( '/sitemap-(\d+)\.xml$/', (string) $f, $mm ) && (int) $mm[1] > $current_max ) {
				@unlink( $f ); 
			}
		}
	}
}
