<?php

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

if ( ! class_exists( 'AIEO_SEO_Redirects' ) ) {
	require_once AIEO_DIR . 'includes/seo/class-aieo-seo-redirects.php';
}

if ( ! class_exists( 'AIEO_SEO_Score' ) ) {
	require_once AIEO_DIR . 'includes/seo/class-aieo-seo-score.php';
}
if ( ! class_exists( 'AIEO_SEO_Store' ) ) {
	require_once AIEO_DIR . 'includes/seo/class-aieo-seo-store.php';
}

class AIEO_DMM_SEO_Redirects extends AIEO_DMM_Module_Base {

	public function get_id()       { return 'seo_redirects'; }
	public function get_label()    { return __( 'Redirects', 'ai-eshop-optimizer' ); }
	public function get_priority() { return 10; }
	public function get_group()    { return 'seo'; }
	public function get_section()  { return 'redirects'; }

	public function register_hooks() {
		add_action( 'wp_ajax_aieo_seo_redirect_save', array( $this, 'ajax_save' ) );
		add_action( 'wp_ajax_aieo_seo_redirect_delete', array( $this, 'ajax_delete' ) );
		add_action( 'wp_ajax_aieo_seo_redirect_toggle', array( $this, 'ajax_toggle' ) );
		add_action( 'wp_ajax_aieo_seo_404_dismiss', array( $this, 'ajax_404_dismiss' ) );
		add_action( 'wp_ajax_aieo_seo_redirect_import', array( $this, 'ajax_import' ) );
		add_action( 'wp_ajax_aieo_seo_redirect_export', array( $this, 'ajax_export' ) );
		add_action( 'wp_ajax_aieo_seo_redirect_import_xlsx', array( $this, 'ajax_import_xlsx' ) );
		add_action( 'wp_ajax_aieo_seo_redirect_rebuild_edge', array( $this, 'ajax_rebuild_edge' ) );
		add_action( 'wp_ajax_aieo_seo_index_rebuild', array( $this, 'ajax_seo_index_rebuild' ) );
		add_action( 'wp_ajax_aieo_seo_save_robots', array( $this, 'ajax_save_robots' ) );
	}

	private function guard() {
		AIEO_DMM::verify_ajax_request();
		if ( ! current_user_can( 'manage_woocommerce' ) && ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Insufficient permissions.', 'ai-eshop-optimizer' ) ) );
		}
		if ( ! class_exists( 'AIEO_SEO_Redirects' ) ) {
			wp_send_json_error( array( 'message' => __( 'Redirect engine unavailable.', 'ai-eshop-optimizer' ) ) );
		}
	}

	
	public static function rebuild_types() {
		$types = AIEO_SEO_Score::public_post_types() + AIEO_SEO_Score::public_taxonomies();
		foreach ( get_taxonomies() as $tax ) {
			if ( 0 === strpos( $tax, 'pa_' ) && 'pa_need' !== $tax ) {
				$types['attributes'] = __( 'Attributes', 'ai-eshop-optimizer' );
				break;
			}
		}
		return $types;
	}

	
	public static function rebuild_types_with_counts() {
		$out = array();
		foreach ( self::rebuild_types() as $key => $label ) {
			$out[ $key ] = array(
				'label' => $label,
				'count' => self::seo_rebuild_count( $key ),
			);
		}
		return $out;
	}

	
	public function ajax_seo_index_rebuild() {
		$this->guard();
		if ( ! class_exists( 'AIEO_SEO_Head_Builder' ) || ! method_exists( 'AIEO_SEO_Head_Builder', 'build' ) ) {
			wp_send_json_error( array( 'message' => __( 'SEO engine unavailable.', 'ai-eshop-optimizer' ) ) );
		}
		$allowed = array_keys( self::rebuild_types() );
		$raw     = isset( $_POST['types'] ) ? sanitize_text_field( wp_unslash( $_POST['types'] ) ) : '';
		$types   = array_values( array_intersect( array_filter( array_map( 'trim', explode( ',', $raw ) ) ), $allowed ) );
		if ( empty( $types ) ) {
			wp_send_json_error( array( 'message' => __( 'Select at least one type to rebuild.', 'ai-eshop-optimizer' ) ) );
		}
		$ti         = isset( $_POST['ti'] ) ? max( 0, (int) $_POST['ti'] ) : 0;
		$last_id    = isset( $_POST['last_id'] ) ? max( 0, (int) $_POST['last_id'] ) : 0;
		$done_count = isset( $_POST['done_count'] ) ? max( 0, (int) $_POST['done_count'] ) : 0;
		$total      = isset( $_POST['total'] ) ? (int) $_POST['total'] : -1;
		if ( $total < 0 ) { 
			
			
			update_option( 'aieo_seo_rebuild_last_types', $types, false );
			$total = 0;
			foreach ( $types as $t ) {
				$total += self::seo_rebuild_count( $t );
			}
		}

		$cap      = 600;
		$deadline = microtime( true ) + 12.0;
		$built    = 0;
		$n        = count( $types );
		while ( $ti < $n && $built < $cap && microtime( true ) < $deadline ) {
			$need = min( 200, $cap - $built );
			$rows = $this->seo_rebuild_batch( $types[ $ti ], $last_id, $need );
			foreach ( $rows as $row ) {
				AIEO_SEO_Head_Builder::build( $row[0], $row[1] );
				$last_id = $row[1];
				$built++;
			}
			if ( count( $rows ) < $need ) { 
				$ti++;
				$last_id = 0;
			}
		}
		$done_count += $built;
		$done        = ( $ti >= $n );
		if ( $done && class_exists( 'AIEO_SEO_Sitemap' ) && method_exists( 'AIEO_SEO_Sitemap', 'build' ) ) {
			AIEO_SEO_Sitemap::build();
		}
		$labels = self::rebuild_types();
		wp_send_json_success( array(
			'done'       => $done,
			'ti'         => $ti,
			'last_id'    => $last_id,
			'done_count' => $done_count,
			'total'      => $total,
			'label'      => ( ! $done && isset( $types[ $ti ], $labels[ $types[ $ti ] ] ) ) ? $labels[ $types[ $ti ] ] : '',
		) );
	}

	
	public function ajax_save_robots() {
		AIEO_DMM::verify_ajax_request();
		if ( ! current_user_can( 'manage_woocommerce' ) && ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'Insufficient permissions.', 'ai-eshop-optimizer' ) ) );
		}
		if ( ! class_exists( 'AIEO_SEO_Sitemap' ) ) {
			wp_send_json_error( array( 'message' => __( 'SEO engine unavailable.', 'ai-eshop-optimizer' ) ) );
		}
		$custom = isset( $_POST['custom'] ) ? sanitize_textarea_field( wp_unslash( $_POST['custom'] ) ) : '';
		update_option( AIEO_SEO_Sitemap::ROBOTS_CUSTOM_OPT, $custom, false );
		AIEO_SEO_Sitemap::sync_robots(); 
		wp_send_json_success( array(
			'message' => __( 'robots.txt updated.', 'ai-eshop-optimizer' ),
			'served'  => AIEO_SEO_Sitemap::robots_body(),
		) );
	}

	
	private function seo_rebuild_batch( $type, $after, $limit ) {
		global $wpdb;
		$out   = array();
		$after = (int) $after;
		$limit = (int) $limit;
		if ( 'attributes' === $type ) {
			
			$rows = $wpdb->get_results( $wpdb->prepare( "SELECT t.term_id, tt.taxonomy FROM {$wpdb->terms} t INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_id = t.term_id WHERE tt.taxonomy LIKE %s AND tt.taxonomy <> 'pa_need' AND t.term_id > %d ORDER BY t.term_id ASC LIMIT %d", $wpdb->esc_like( 'pa_' ) . '%', $after, $limit ) );
			foreach ( (array) $rows as $r ) {
				$out[] = array( (string) $r->taxonomy, (int) $r->term_id );
			}
		} elseif ( post_type_exists( $type ) ) {
			
			$ids = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_type = %s AND post_status = 'publish' AND ID > %d ORDER BY ID ASC LIMIT %d", $type, $after, $limit ) );
			foreach ( $ids as $id ) {
				$out[] = array( $type, (int) $id );
			}
		} elseif ( taxonomy_exists( $type ) ) {
			
			$ids = $wpdb->get_col( $wpdb->prepare( "SELECT t.term_id FROM {$wpdb->terms} t INNER JOIN {$wpdb->term_taxonomy} tt ON tt.term_id = t.term_id WHERE tt.taxonomy = %s AND t.term_id > %d ORDER BY t.term_id ASC LIMIT %d", $type, $after, $limit ) );
			foreach ( $ids as $id ) {
				$out[] = array( $type, (int) $id );
			}
		}
		return $out;
	}

	
	public static function seo_rebuild_count( $type ) {
		global $wpdb;
		if ( 'attributes' === $type ) {
			
			return (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->term_taxonomy} WHERE taxonomy LIKE %s AND taxonomy <> 'pa_need'", $wpdb->esc_like( 'pa_' ) . '%' ) );
		}
		if ( post_type_exists( $type ) ) {
			
			return (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->posts} WHERE post_type = %s AND post_status = 'publish'", $type ) );
		}
		if ( taxonomy_exists( $type ) ) {
			
			return (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->term_taxonomy} WHERE taxonomy = %s", $type ) );
		}
		return 0;
	}

	public function ajax_save() {
		$this->guard();
		$source   = isset( $_POST['source'] ) ? sanitize_text_field( wp_unslash( $_POST['source'] ) ) : '';
		$target   = isset( $_POST['target'] ) ? sanitize_text_field( wp_unslash( $_POST['target'] ) ) : '';
		$code     = isset( $_POST['code'] ) ? (int) $_POST['code'] : 301;
		$is_regex = ! empty( $_POST['is_regex'] ) ? 1 : 0;
		if ( '' === $source ) {
			wp_send_json_error( array( 'message' => __( 'Source path is required.', 'ai-eshop-optimizer' ) ) );
		}
		$ok = AIEO_SEO_Redirects::add( $source, $target, $code, array( 'is_regex' => $is_regex, 'source' => 'manual' ) );
		if ( $ok && ! $is_regex ) {
			AIEO_SEO_Redirects::mark_404_redirected( AIEO_SEO_Redirects::normalize_path( $source ) );
		}
		if ( $ok ) {
			wp_send_json_success();
		}
		wp_send_json_error( array( 'message' => __( 'Could not save the redirect.', 'ai-eshop-optimizer' ) ) );
	}

	public function ajax_delete() {
		$this->guard();
		AIEO_SEO_Redirects::delete( isset( $_POST['id'] ) ? (int) $_POST['id'] : 0 );
		wp_send_json_success();
	}

	public function ajax_toggle() {
		$this->guard();
		$ok = AIEO_SEO_Redirects::set_enabled( isset( $_POST['id'] ) ? (int) $_POST['id'] : 0, ! empty( $_POST['enabled'] ) );
		if ( ! $ok ) {
			wp_send_json_error( array( 'message' => __( 'Refused: enabling this rule would create a redirect loop.', 'ai-eshop-optimizer' ) ) );
		}
		wp_send_json_success();
	}

	public function ajax_404_dismiss() {
		$this->guard();
		AIEO_SEO_Redirects::delete_404( isset( $_POST['id'] ) ? (int) $_POST['id'] : 0 );
		wp_send_json_success();
	}

	public function ajax_import() {
		$this->guard();
		wp_send_json_success( AIEO_SEO_Redirects::import_aioseo() );
	}

	
	public function ajax_export() {
		$this->guard();
		require_once AIEO_DIR . 'includes/dmm/services/class-aieo-dmm-xlsx-writer.php';
		global $wpdb;
		$t = $wpdb->prefix . 'aieo_seo_redirects';
		$w = new AIEO_DMM_XLSX_Writer( 'Redirects' );
		$w->add_header_row( array( 'ID', 'Source Path', 'Target', 'Code', 'Regex', 'Enabled' ) );
		
		$rows = $wpdb->get_results( "SELECT id, source_path, target, status_code, is_regex, enabled FROM `{$t}` ORDER BY id ASC", ARRAY_A );
		foreach ( (array) $rows as $r ) {
			$w->add_row(
				array( (int) $r['id'], (string) $r['source_path'], (string) $r['target'], (int) $r['status_code'], (int) $r['is_regex'], (int) $r['enabled'] ),
				array( 0 => 'integer', 3 => 'integer', 4 => 'integer', 5 => 'integer' )
			);
		}
		$w->stream_download( 'aieo-redirects-' . gmdate( 'Y-m-d' ) . '.xlsx' );
	}

	
	public function ajax_import_xlsx() {
		$this->guard();
		if ( empty( $_FILES['xlsx_file'] ) || ! isset( $_FILES['xlsx_file']['tmp_name'] ) || ! is_uploaded_file( $_FILES['xlsx_file']['tmp_name'] ) ) {
			wp_send_json_error( array( 'message' => __( 'No file uploaded.', 'ai-eshop-optimizer' ) ) );
		}
		require_once AIEO_DIR . 'includes/dmm/services/class-aieo-dmm-xlsx-reader.php';
		
		$rows = AIEO_DMM_XLSX_Reader::read( $_FILES['xlsx_file']['tmp_name'] );
		if ( null === $rows || count( $rows ) < 2 ) {
			wp_send_json_error( array( 'message' => __( 'Could not read the file as an .xlsx with a header + data rows.', 'ai-eshop-optimizer' ) ) );
		}

		
		$header = array_shift( $rows );
		$map    = array();
		foreach ( (array) $header as $i => $h ) {
			$key = strtolower( trim( preg_replace( '/\s+/', ' ', (string) $h ) ) );
			if ( '' !== $key ) {
				$map[ $key ] = (int) $i;
			}
		}
		$pick = function ( $names, $default ) use ( $map ) {
			foreach ( (array) $names as $n ) {
				if ( isset( $map[ $n ] ) ) {
					return $map[ $n ];
				}
			}
			return $default;
		};
		$ci_source  = $pick( array( 'source path', 'source' ), 1 );
		$ci_target  = $pick( array( 'target' ), 2 );
		$ci_code    = $pick( array( 'code', 'status', 'status code' ), 3 );
		$ci_regex   = $pick( array( 'regex', 'is_regex', 'is regex' ), 4 );
		$ci_enabled = $pick( array( 'enabled', 'on' ), 5 );

		$truthy = function ( $v ) {
			$v = strtolower( trim( (string) $v ) );
			return ! ( '' === $v || '0' === $v || 'no' === $v || 'false' === $v || 'off' === $v );
		};

		$full_sync    = ! empty( $_POST['full_sync'] );
		$count_before = (int) AIEO_SEO_Redirects::count_all();

		
		
		
		$file_sources = array();
		foreach ( $rows as $r ) {
			$s = isset( $r[ $ci_source ] ) ? trim( (string) $r[ $ci_source ] ) : '';
			if ( '' !== $s && ! ( isset( $r[ $ci_regex ] ) && $truthy( $r[ $ci_regex ] ) ) ) {
				$file_sources[ AIEO_SEO_Redirects::source_key( $s ) ] = true;
			}
		}

		$seen            = array(); 
		$upserts         = 0;
		$skipped         = 0;
		$skipped_missing = 0; 
		$skipped_loop    = 0; 
		foreach ( $rows as $r ) {
			$source = isset( $r[ $ci_source ] ) ? trim( (string) $r[ $ci_source ] ) : '';
			if ( '' === $source ) {
				$skipped++;
				continue;
			}
			$target   = isset( $r[ $ci_target ] ) ? trim( (string) $r[ $ci_target ] ) : '';
			$code     = isset( $r[ $ci_code ] ) ? (int) $r[ $ci_code ] : 301;
			$is_regex = ( isset( $r[ $ci_regex ] ) && $truthy( $r[ $ci_regex ] ) ) ? 1 : 0;
			$enabled  = isset( $r[ $ci_enabled ] ) ? ( $truthy( $r[ $ci_enabled ] ) ? 1 : 0 ) : 1;
			
			
			
			
			$seen[ $is_regex ? $source : AIEO_SEO_Redirects::source_key( $source ) ] = true;
			if ( ! $is_regex ) {
				if ( ! AIEO_SEO_Redirects::target_exists( $target, $code, $file_sources ) ) {
					$skipped_missing++;
					$skipped++;
					continue;
				}
				
				if ( $enabled && AIEO_SEO_Redirects::would_loop( $source, $target, $code ) ) {
					$skipped_loop++;
					$skipped++;
					continue;
				}
			}
			$ok = AIEO_SEO_Redirects::add( $source, $target, $code, array( 'is_regex' => $is_regex, 'enabled' => $enabled, 'source' => 'xlsx' ) );
			if ( $ok ) {
				$upserts++;
			} else {
				$skipped++;
			}
		}

		$deleted = 0;
		if ( $full_sync ) {
			if ( $count_before > 0 && count( $seen ) < $count_before * 0.5 ) {
				wp_send_json_error( array(
					'message' => sprintf(
						
						__( 'Full-sync refused: the file has %1$d rules but the site has %2$d. Upload the complete export, or untick full-sync.', 'ai-eshop-optimizer' ),
						count( $seen ),
						$count_before
					),
				) );
			}
			global $wpdb;
			$t = $wpdb->prefix . 'aieo_seo_redirects';
			
			$all = $wpdb->get_results( "SELECT id, source_path, is_regex FROM `{$t}`", ARRAY_A );
			foreach ( (array) $all as $row ) {
				
				
				
				$key = ! empty( $row['is_regex'] ) ? (string) $row['source_path'] : AIEO_SEO_Redirects::source_key( (string) $row['source_path'] );
				if ( ! isset( $seen[ $key ] ) ) {
					AIEO_SEO_Redirects::delete( (int) $row['id'] );
					$deleted++;
				}
			}
		}

		if ( method_exists( 'AIEO_SEO_Redirects', 'export_edge_map' ) ) {
			AIEO_SEO_Redirects::export_edge_map();
		}

		wp_send_json_success( array(
			'upserts'                => $upserts,
			'deleted'                => $deleted,
			'skipped'                => $skipped,
			'skipped_missing_target' => $skipped_missing,
			'skipped_loop'           => $skipped_loop,
			'total'                  => (int) AIEO_SEO_Redirects::count_all(),
		) );
	}

	
	public function ajax_rebuild_edge() {
		$this->guard();
		$out = array( 'redirect_maps' => false, 'sitemap' => false );

		if ( method_exists( 'AIEO_SEO_Redirects', 'export_edge_map' ) ) {
			AIEO_SEO_Redirects::export_edge_map();
			$out['redirect_maps'] = true;
		}
		if ( class_exists( 'AIEO_SEO_Sitemap' ) && method_exists( 'AIEO_SEO_Sitemap', 'build' ) ) {
			$r = AIEO_SEO_Sitemap::build();
			$out['sitemap'] = is_array( $r ) ? $r : true;
		}

		$dir = method_exists( 'AIEO_SEO_Redirects', 'edge_dir' ) ? AIEO_SEO_Redirects::edge_dir() : '';
		$out['version'] = '';
		$out['counts']  = array();
		if ( $dir ) {
			$vf = $dir . '/version.txt';
			$out['version'] = is_readable( $vf ) ? trim( (string) file_get_contents( $vf ) ) : '';
			foreach ( array( '301', '302', '307', '308', '410' ) as $code ) {
				$p = $dir . '/' . $code . '.map';
				$n = 0;
				if ( is_readable( $p ) ) {
					foreach ( (array) file( $p ) as $line ) {
						$line = ltrim( (string) $line );
						if ( '' !== $line && '#' !== $line[0] ) {
							$n++;
						}
					}
				}
				$out['counts'][ $code ] = $n;
			}
		}
		wp_send_json_success( $out );
	}

	public function render_subtab() {
		$this->render_template(
			'seo/redirects.php',
			array(
				'redirects'  => class_exists( 'AIEO_SEO_Redirects' ) ? AIEO_SEO_Redirects::all( 200 ) : array(),
				'fourohfour' => class_exists( 'AIEO_SEO_Redirects' ) ? AIEO_SEO_Redirects::top_404( 50 ) : array(),
				'rebuild_types' => self::rebuild_types_with_counts(),
				'provider_active' => AIEO_SEO_Store::is_active_provider(),
				'nginx'      => class_exists( 'AIEO_SEO_Redirects' ) ? AIEO_SEO_Redirects::nginx_config() : '',
				'edge_dir'   => class_exists( 'AIEO_SEO_Redirects' ) ? AIEO_SEO_Redirects::edge_dir() : '',
				'nonce'      => wp_create_nonce( AIEO_DMM::NONCE_ACTION ),
				'ajax'       => admin_url( 'admin-ajax.php' ),
				'robots_default' => class_exists( 'AIEO_SEO_Sitemap' ) ? AIEO_SEO_Sitemap::robots_default_body() : '',
				'robots_custom'  => (string) get_option( 'aieo_seo_robots_custom', '' ),
			)
		);
	}
}
