<?php
/**
 * Plugin Name: BW AI Schema Pro
 * Plugin URI: https://bowdenworks.com
 * Description: Advanced Schema Markup plugin optimized for AI era - Enhance your content's visibility and understanding by AI systems with comprehensive schema markup.
 * Version: 2.1.3
 * Author: Bowden Works
 * Author URI: https://bowdenworks.com
 * License: GPL v2 or later
 * License URI: https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain: bw-ai-schema-pro
 * Domain Path: /languages
 */

// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

// Define plugin constants
// Version is read from plugin header to ensure single source of truth
if ( ! function_exists( 'get_file_data' ) ) {
	require_once ABSPATH . 'wp-includes/functions.php';
}
$bw_schema_plugin_data = get_file_data( __FILE__, array( 'Version' => 'Version' ) );
define( 'BW_SCHEMA_VERSION', $bw_schema_plugin_data['Version'] );
define( 'BW_SCHEMA_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'BW_SCHEMA_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'BW_SCHEMA_PLUGIN_FILE', __FILE__ );
define( 'BW_SCHEMA_PREFIX', 'bw_schema_' );

// Initialize Plugin Update Checker for self-hosted updates
require_once BW_SCHEMA_PLUGIN_DIR . 'vendor/plugin-update-checker/plugin-update-checker.php';
use YahnisElsts\PluginUpdateChecker\v5\PucFactory;

$bwSchemaUpdateChecker = PucFactory::buildUpdateChecker(
    'https://bwgeo.demoing.info/wp-content/uploads/plugin-updates/bw-ai-schema-pro.json',
    __FILE__,
    'bw-ai-schema-pro'
);

// Autoloader for plugin classes
spl_autoload_register( function ( $class ) {
	$prefix = 'BW_Schema_';
	$base_dir = BW_SCHEMA_PLUGIN_DIR . 'includes/';

	$len = strlen( $prefix );
	if ( strncmp( $prefix, $class, $len ) !== 0 ) {
		return;
	}

	$relative_class = substr( $class, $len );
	
	// Convert class name to file name
	$file_name = 'class-' . strtolower( str_replace( '_', '-', $class ) ) . '.php';
	
	// Check in main includes directory
	$file = $base_dir . $file_name;
	if ( file_exists( $file ) ) {
		require $file;
		return;
	}
	
	// Check in schemas subdirectory
	$file = $base_dir . 'schemas/' . $file_name;
	if ( file_exists( $file ) ) {
		require $file;
		return;
	}
});

/**
 * Main plugin class
 */
class BW_AI_Schema_Pro {
	
	/**
	 * Instance of this class
	 */
	private static $instance = null;
	
	/**
	 * Get instance of this class
	 */
	public static function get_instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}
		return self::$instance;
	}
	
	/**
	 * Constructor
	 */
	private function __construct() {
		$this->init_hooks();
		$this->load_dependencies();
	}
	
	/**
	 * Initialize hooks
	 */
	private function init_hooks() {
		add_action( 'init', array( $this, 'load_textdomain' ) );
		add_action( 'wp_head', array( $this, 'output_schema_markup' ), 1 );
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_scripts' ) );
		add_filter( 'body_class', array( $this, 'add_body_classes' ) );

		// Run option migration check (early priority)
		add_action( 'init', array( 'BW_Schema_Core', 'maybe_migrate_options' ), 1 );

		// Disable conflicting schema sources
		add_action( 'init', array( 'BW_Schema_Core', 'disable_conflicting_schema' ), 5 );
		
		// Initialize cache system
		add_action( 'init', array( 'BW_Schema_Cache', 'init' ) );
		
		// Initialize developer hooks
		add_action( 'init', array( 'BW_Schema_Hooks', 'init' ) );
		
		// Initialize security
		add_action( 'init', array( 'BW_Schema_Security', 'init' ) );
		
		// Initialize author override
		add_action( 'init', array( 'BW_Schema_Author_Override', 'init' ) );

		// Initialize team member enhancements
		add_action( 'init', array( 'BW_Schema_Team_Member', 'init' ) );

		// Author archive redirect (v2.0 - redirect /author/username/ to team page)
		add_action( 'template_redirect', array( $this, 'maybe_redirect_author_archive' ) );
		
		// Admin hooks
		if ( is_admin() ) {
			add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_assets' ) );
			add_action( 'add_meta_boxes', array( $this, 'add_meta_boxes' ) );
			add_action( 'save_post', array( $this, 'save_post_meta' ) );

			// AJAX handlers
			add_action( 'wp_ajax_bw_schema_get_simple_fields', array( $this, 'ajax_get_simple_fields' ) );
			add_action( 'wp_ajax_bw_schema_preview', array( $this, 'ajax_preview_schema' ) );
			add_action( 'wp_ajax_bw_schema_get_taxonomy_terms', array( $this, 'ajax_get_taxonomy_terms' ) );

			// Setup wizard
			add_action( 'admin_init', array( $this, 'maybe_redirect_to_setup' ) );

			// User profile - Default Author field (v2.0)
			add_action( 'show_user_profile', array( $this, 'render_user_default_author_field' ) );
			add_action( 'edit_user_profile', array( $this, 'render_user_default_author_field' ) );
			add_action( 'personal_options_update', array( $this, 'save_user_default_author' ) );
			add_action( 'edit_user_profile_update', array( $this, 'save_user_default_author' ) );
		}
	}
	
	/**
	 * Load plugin dependencies
	 */
	private function load_dependencies() {
		// Core classes
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/class-bw-schema-core.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/class-bw-schema-renderer.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/class-bw-schema-templates.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/class-bw-schema-cache.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/class-bw-schema-hooks.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/class-bw-schema-helpers.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/class-bw-schema-security.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/class-bw-schema-author-override.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/class-bw-schema-team-member.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/class-bw-schema-author-box.php';

		// Admin classes
		if ( is_admin() ) {
			require_once BW_SCHEMA_PLUGIN_DIR . 'includes/class-bw-schema-admin.php';
		}
		
		// Schema type classes
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-base.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-article.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-person.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-organization.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-localbusiness.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-product.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-event.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-howto.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-faq.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-review.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-recipe.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-video.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-course.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-jobposting.php';
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/schemas/class-bw-schema-webpage.php';
		
		// Load blocks if Gutenberg is available
		require_once BW_SCHEMA_PLUGIN_DIR . 'includes/class-bw-schema-blocks.php';
		BW_Schema_Blocks::init();
	}
	
	/**
	 * Load plugin textdomain
	 */
	public function load_textdomain() {
		load_plugin_textdomain( 'bw-ai-schema-pro', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
	}
	
	/**
	 * Add admin menu
	 */
	public function add_admin_menu() {
		$admin = new BW_Schema_Admin();
		$admin->add_menu_pages();
	}
	
	/**
	 * Enqueue admin assets
	 */
	public function enqueue_admin_assets( $hook ) {
		// Only load on our plugin pages
		if ( strpos( $hook, 'bw-ai-schema' ) !== false || $hook === 'post.php' || $hook === 'post-new.php' ) {
			wp_enqueue_style( 'bw-schema-admin', BW_SCHEMA_PLUGIN_URL . 'admin/assets/css/admin.css', array(), BW_SCHEMA_VERSION );
			wp_enqueue_script( 'bw-schema-admin', BW_SCHEMA_PLUGIN_URL . 'admin/assets/js/admin.js', array( 'jquery' ), BW_SCHEMA_VERSION, true );
			
			// Enqueue media scripts for author profiles page
			if ( strpos( $hook, 'bw-ai-schema-authors' ) !== false || strpos( $hook, 'bw-ai-schema-author-profiles' ) !== false ) {
				wp_enqueue_media();
			}
			
			wp_localize_script( 'bw-schema-admin', 'bwSchema', array(
				'ajaxurl' => admin_url( 'admin-ajax.php' ),
				'nonce' => wp_create_nonce( 'bw_schema_nonce' ),
				'i18n' => array(
					'confirmDelete' => __( 'Are you sure you want to delete this schema?', 'bw-ai-schema-pro' ),
					'saved' => __( 'Settings saved successfully!', 'bw-ai-schema-pro' ),
					'error' => __( 'An error occurred. Please try again.', 'bw-ai-schema-pro' )
				)
			));
		}
	}
	
	/**
	 * Add meta boxes
	 */
	public function add_meta_boxes() {
		// Get meta box display settings
		$metabox_post_types = get_option( 'bw_schema_metabox_post_types', array() );
		$metabox_position = get_option( 'bw_schema_metabox_position', 'normal' );
		$metabox_priority = ( $metabox_position === 'side' ) ? 'default' : 'high';

		// Get post type defaults (for schema type defaults)
		$defaults = get_option( 'bw_schema_post_type_defaults', array() );

		// If no post types configured, default to all public except excluded
		if ( empty( $metabox_post_types ) ) {
			$all_post_types = get_post_types( array( 'public' => true ), 'names' );
			$excluded = array( 'attachment' );
			$metabox_post_types = array_diff( $all_post_types, $excluded );
		}

		foreach ( $metabox_post_types as $post_type ) {
			// Skip if this post type is set to "No Schema" in schema defaults
			if ( isset( $defaults[$post_type] ) &&
			    ( $defaults[$post_type] === 'no_schema' || $defaults[$post_type] === 'none:None' ) ) {
				continue;
			}

			add_meta_box(
				'bw_schema_settings',
				__( 'AI Schema Settings', 'bw-ai-schema-pro' ),
				array( $this, 'render_meta_box' ),
				$post_type,
				$metabox_position,
				$metabox_priority
			);
		}
	}
	
	/**
	 * Render meta box
	 */
	public function render_meta_box( $post ) {
		$admin = new BW_Schema_Admin();
		$admin->render_post_meta_box( $post );
	}
	
	/**
	 * Save post meta
	 */
	public function save_post_meta( $post_id ) {
		// Verify nonce
		if ( ! isset( $_POST['bw_schema_meta_nonce'] ) || ! wp_verify_nonce( $_POST['bw_schema_meta_nonce'], 'bw_schema_meta' ) ) {
			return;
		}
		
		// Check autosave
		if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
			return;
		}
		
		// Check permissions
		if ( ! current_user_can( 'edit_post', $post_id ) ) {
			return;
		}
		
		// Save simple mode preference
		if ( isset( $_POST['bw_schema_simple_mode'] ) ) {
			update_post_meta( $post_id, '_bw_schema_simple_mode', sanitize_text_field( $_POST['bw_schema_simple_mode'] ) );
		}
		
		// Save schema settings
		if ( isset( $_POST['bw_schema_type'] ) ) {
			update_post_meta( $post_id, '_bw_schema_type', sanitize_text_field( $_POST['bw_schema_type'] ) );
		}
		
		if ( isset( $_POST['bw_schema_custom'] ) ) {
			update_post_meta( $post_id, '_bw_schema_custom', wp_kses_post( $_POST['bw_schema_custom'] ) );
		}
		
		if ( isset( $_POST['bw_schema_disable'] ) ) {
			update_post_meta( $post_id, '_bw_schema_disable', 'yes' );
		} else {
			delete_post_meta( $post_id, '_bw_schema_disable' );
		}
		
		// Save AI fields
		if ( isset( $_POST['bw_schema_about_entities'] ) ) {
			$entities = array_map( 'trim', explode( ',', sanitize_text_field( $_POST['bw_schema_about_entities'] ) ) );
			update_post_meta( $post_id, '_bw_schema_about_entities', array_filter( $entities ) );
		}
		
		if ( isset( $_POST['bw_schema_fact_checked_by'] ) ) {
			update_post_meta( $post_id, '_bw_schema_fact_checked_by', sanitize_text_field( $_POST['bw_schema_fact_checked_by'] ) );
		}
		
		if ( isset( $_POST['bw_schema_last_reviewed'] ) ) {
			update_post_meta( $post_id, '_bw_schema_last_reviewed', sanitize_text_field( $_POST['bw_schema_last_reviewed'] ) );
		}
		
		// Save custom author selection (legacy support)
		if ( isset( $_POST['bw_schema_custom_author'] ) ) {
			update_post_meta( $post_id, '_bw_schema_custom_author', sanitize_text_field( $_POST['bw_schema_custom_author'] ) );
		}
		
		// Save multiple authors
		if ( isset( $_POST['bw_schema_authors'] ) && is_array( $_POST['bw_schema_authors'] ) ) {
			$authors = array();
			
			foreach ( $_POST['bw_schema_authors'] as $author ) {
				if ( empty( $author['type'] ) ) {
					continue;
				}
				
				$author_data = array(
					'type' => sanitize_text_field( $author['type'] )
				);
				
				switch ( $author['type'] ) {
					// v2.0: Team Member Author
					case 'team_member':
						if ( ! empty( $author['team_member_id'] ) ) {
							$author_data['team_member_id'] = intval( $author['team_member_id'] );
							$authors[] = $author_data;
						}
						break;

					// v2.0: External Author (saved in settings)
					case 'external_saved':
						if ( ! empty( $author['external_author_id'] ) ) {
							$author_data['external_author_id'] = sanitize_text_field( $author['external_author_id'] );
							$authors[] = $author_data;
						}
						break;

					// Legacy: WordPress User
					case 'wordpress':
						if ( ! empty( $author['wordpress_user_id'] ) ) {
							$author_data['wordpress_user_id'] = intval( $author['wordpress_user_id'] );
							$authors[] = $author_data;
						}
						break;

					// Legacy: Custom Author (from old settings)
					case 'custom':
						if ( ! empty( $author['custom_author_id'] ) ) {
							$author_data['custom_author_id'] = sanitize_text_field( $author['custom_author_id'] );
							$authors[] = $author_data;
						}
						break;

					// External (One-time) - inline data
					case 'external':
						if ( ! empty( $author['external']['name'] ) ) {
							$author_data['external'] = array(
								'name' => sanitize_text_field( $author['external']['name'] ),
								'job_title' => sanitize_text_field( $author['external']['job_title'] ?? '' ),
								'bio' => sanitize_textarea_field( $author['external']['bio'] ?? '' ),
								'image' => esc_url_raw( $author['external']['image'] ?? '' ),
								'email' => sanitize_email( $author['external']['email'] ?? '' ),
								'website' => esc_url_raw( $author['external']['website'] ?? '' ),
								'linkedin' => esc_url_raw( $author['external']['linkedin'] ?? '' ),
								'twitter' => esc_url_raw( $author['external']['twitter'] ?? '' ),
								'expertise' => sanitize_text_field( $author['external']['expertise'] ?? '' )
							);
							$authors[] = $author_data;
						}
						break;
				}
			}
			
			if ( ! empty( $authors ) ) {
				update_post_meta( $post_id, '_bw_schema_multiple_authors', $authors );
			} else {
				delete_post_meta( $post_id, '_bw_schema_multiple_authors' );
			}
		}
		
		// Save disable default author box option
		if ( isset( $_POST['bw_schema_disable_default_author'] ) ) {
			update_post_meta( $post_id, '_bw_schema_disable_default_author', '1' );
		} else {
			delete_post_meta( $post_id, '_bw_schema_disable_default_author' );
		}
		
		// Save show author box option (v2.0: 'default', 'show', 'hide')
		if ( isset( $_POST['bw_schema_show_author_box'] ) ) {
			$author_box_value = sanitize_text_field( $_POST['bw_schema_show_author_box'] );
			if ( in_array( $author_box_value, array( 'default', 'show', 'hide' ), true ) ) {
				if ( $author_box_value === 'default' ) {
					// Remove the meta to use default
					delete_post_meta( $post_id, '_bw_schema_show_author_box' );
				} else {
					update_post_meta( $post_id, '_bw_schema_show_author_box', $author_box_value );
				}
			}
		}
		
		// Save team page option
		if ( isset( $_POST['bw_schema_is_team_page'] ) ) {
			update_post_meta( $post_id, '_bw_schema_is_team_page', 'yes' );
		} else {
			delete_post_meta( $post_id, '_bw_schema_is_team_page' );
		}
		
		// Save price range for LocalBusiness
		if ( isset( $_POST['bw_schema_price_range'] ) ) {
			update_post_meta( $post_id, '_bw_schema_price_range', sanitize_text_field( $_POST['bw_schema_price_range'] ) );
		}
	}
	
	/**
	 * Output schema markup
	 */
	public function output_schema_markup() {
		$renderer = new BW_Schema_Renderer();
		$renderer->render();
	}
	
	/**
	 * Enqueue frontend scripts
	 */
	public function enqueue_frontend_scripts() {
		if ( ! is_singular() ) {
			return;
		}
		
		global $post;
		if ( ! $post ) {
			return;
		}
		
		// Check if we have multiple authors
		$multiple_authors = get_post_meta( $post->ID, '_bw_schema_multiple_authors', true );
		
		if ( ! empty( $multiple_authors ) && is_array( $multiple_authors ) && count( $multiple_authors ) > 1 ) {
			// Enqueue CSS
			wp_enqueue_style( 
				'bw-schema-frontend', 
				BW_SCHEMA_PLUGIN_URL . 'assets/css/frontend.css', 
				array(), 
				BW_SCHEMA_VERSION 
			);
			// Get formatted author names and URLs
			$author_info = array();
			$author_names = array();
			$custom_authors_list = get_option( 'bw_schema_custom_authors', array() );
			
			foreach ( $multiple_authors as $author_data ) {
				$info = array(
					'name' => null,
					'url' => ''
				);
				
				switch ( $author_data['type'] ) {
					case 'wordpress':
						if ( ! empty( $author_data['wordpress_user_id'] ) ) {
							$user = get_userdata( $author_data['wordpress_user_id'] );
							if ( $user ) {
								$info['name'] = $user->display_name;
								$info['url'] = get_author_posts_url( $user->ID );
							}
						}
						break;
						
					case 'custom':
						if ( ! empty( $author_data['custom_author_id'] ) ) {
							foreach ( $custom_authors_list as $custom_author ) {
								if ( $custom_author['id'] === $author_data['custom_author_id'] ) {
									$info['name'] = $custom_author['name'];
									if ( ! empty( $custom_author['social']['website'] ) ) {
										$info['url'] = $custom_author['social']['website'];
									}
									break;
								}
							}
						}
						break;
						
					case 'external':
						if ( ! empty( $author_data['external']['name'] ) ) {
							$info['name'] = $author_data['external']['name'];
							if ( ! empty( $author_data['external']['website'] ) ) {
								$info['url'] = $author_data['external']['website'];
							}
						}
						break;
				}
				
				if ( $info['name'] ) {
					$author_info[] = $info;
					$author_names[] = $info['name'];
				}
			}
			
			if ( count( $author_names ) > 1 ) {
				// Format the names
				$formatted_names = '';
				$count = count( $author_names );
				
				if ( $count === 2 ) {
					$formatted_names = $author_names[0] . ' and ' . $author_names[1];
				} elseif ( $count === 3 ) {
					$formatted_names = $author_names[0] . ', ' . $author_names[1] . ' and ' . $author_names[2];
				} else {
					$others_count = $count - 2;
					$formatted_names = $author_names[0] . ', ' . $author_names[1] . ' and ' . $others_count . ' ' . ( $others_count === 1 ? 'other' : 'others' );
				}
				
				// Enqueue the script
				wp_enqueue_script( 
					'bw-schema-frontend-authors', 
					BW_SCHEMA_PLUGIN_URL . 'assets/js/frontend-authors.js', 
					array(), 
					BW_SCHEMA_VERSION, 
					true 
				);
				
				// Pass data to the script
				wp_localize_script( 'bw-schema-frontend-authors', 'bwSchemaAuthors', array(
					'hasMultiple' => true,
					'authors' => $author_names,
					'authorsInfo' => $author_info,
					'formattedNames' => $formatted_names,
					'count' => $count
				) );
			}
		}
	}
	
	/**
	 * Add body classes
	 */
	public function add_body_classes( $classes ) {
		if ( is_singular() ) {
			global $post;
			if ( $post ) {
				$multiple_authors = get_post_meta( $post->ID, '_bw_schema_multiple_authors', true );
				if ( ! empty( $multiple_authors ) && is_array( $multiple_authors ) && count( $multiple_authors ) > 1 ) {
					$classes[] = 'bw-has-multiple-authors';
				}
			}
		}
		return $classes;
	}
	
	/**
	 * AJAX handler for getting simple fields
	 */
	public function ajax_get_simple_fields() {
		// Verify nonce
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'bw_schema_nonce' ) ) {
			wp_die();
		}

		// Verify capabilities - only editors and above
		if ( ! current_user_can( 'edit_posts' ) ) {
			wp_send_json_error( 'Insufficient permissions' );
		}
		
		$type = isset( $_POST['type'] ) ? sanitize_text_field( $_POST['type'] ) : '';
		$post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;
		
		if ( ! $type ) {
			wp_send_json_error( 'No type specified' );
		}
		
		// Generate fields based on type
		ob_start();
		$this->render_simple_fields( $type, $post_id );
		$html = ob_get_clean();
		
		wp_send_json_success( $html );
	}

	/**
	 * Render default author field on user profile (v2.0)
	 *
	 * @param WP_User $user User object
	 */
	public function render_user_default_author_field( $user ) {
		// Get team post type
		$team_post_type = BW_Schema_Team_Member::get_team_post_type();
		if ( ! $team_post_type ) {
			return; // No team post type configured
		}

		// Get team members flagged as authors
		$team_member_authors = get_posts( array(
			'post_type'      => $team_post_type,
			'posts_per_page' => -1,
			'meta_query'     => array(
				array(
					'key'   => '_bw_schema_is_author',
					'value' => '1',
				),
			),
			'orderby'        => 'title',
			'order'          => 'ASC',
		) );

		// Get external authors
		$external_authors = get_option( 'bw_schema_external_authors', array() );

		// If no authors available, don't show the field
		if ( empty( $team_member_authors ) && empty( $external_authors ) ) {
			return;
		}

		// Get current default author setting
		$default_author = get_user_meta( $user->ID, 'bw_schema_default_author', true );
		$default_type   = $default_author['type'] ?? '';
		$default_id     = $default_author['id'] ?? '';
		?>
		<h3><?php _e( 'Schema Author Settings', 'bw-ai-schema-pro' ); ?></h3>
		<table class="form-table" role="presentation">
			<tr>
				<th><label for="bw_schema_default_author"><?php _e( 'Default Post Author', 'bw-ai-schema-pro' ); ?></label></th>
				<td>
					<select name="bw_schema_default_author" id="bw_schema_default_author" class="regular-text">
						<option value=""><?php _e( '— Use WordPress post author —', 'bw-ai-schema-pro' ); ?></option>

						<?php if ( ! empty( $team_member_authors ) ) : ?>
							<optgroup label="<?php _e( 'Team Members', 'bw-ai-schema-pro' ); ?>">
								<?php foreach ( $team_member_authors as $member ) :
									$job_title_data = BW_Schema_Team_Member::detect_job_title( $member );
									$job_title      = is_array( $job_title_data ) ? ( $job_title_data['value'] ?? '' ) : $job_title_data;
									$value          = 'team_member:' . $member->ID;
									$selected       = ( $default_type === 'team_member' && $default_id == $member->ID ) ? 'selected' : '';
									?>
									<option value="<?php echo esc_attr( $value ); ?>" <?php echo $selected; ?>>
										<?php echo esc_html( $member->post_title ); ?>
										<?php if ( $job_title ) : ?>
											— <?php echo esc_html( $job_title ); ?>
										<?php endif; ?>
									</option>
								<?php endforeach; ?>
							</optgroup>
						<?php endif; ?>

						<?php if ( ! empty( $external_authors ) ) : ?>
							<optgroup label="<?php _e( 'External Authors', 'bw-ai-schema-pro' ); ?>">
								<?php foreach ( $external_authors as $author_id => $author ) :
									$value    = 'external:' . $author_id;
									$selected = ( $default_type === 'external' && $default_id === $author_id ) ? 'selected' : '';
									?>
									<option value="<?php echo esc_attr( $value ); ?>" <?php echo $selected; ?>>
										<?php echo esc_html( $author['name'] ?? '' ); ?>
										<?php if ( ! empty( $author['jobTitle'] ) ) : ?>
											— <?php echo esc_html( $author['jobTitle'] ); ?>
										<?php endif; ?>
									</option>
								<?php endforeach; ?>
							</optgroup>
						<?php endif; ?>
					</select>
					<p class="description">
						<?php _e( 'When you create a new post, this author will be pre-selected in the Schema meta box.', 'bw-ai-schema-pro' ); ?>
					</p>
				</td>
			</tr>
		</table>
		<?php
	}

	/**
	 * Save user default author setting (v2.0)
	 *
	 * @param int $user_id User ID being saved
	 */
	public function save_user_default_author( $user_id ) {
		// Check permissions
		if ( ! current_user_can( 'edit_user', $user_id ) ) {
			return;
		}

		$default_author_value = isset( $_POST['bw_schema_default_author'] ) ? sanitize_text_field( $_POST['bw_schema_default_author'] ) : '';

		if ( empty( $default_author_value ) ) {
			delete_user_meta( $user_id, 'bw_schema_default_author' );
		} else {
			// Parse "type:id" format
			$parts = explode( ':', $default_author_value, 2 );
			if ( count( $parts ) === 2 ) {
				update_user_meta( $user_id, 'bw_schema_default_author', array(
					'type' => $parts[0],
					'id'   => $parts[1],
				) );
			}
		}
	}

	/**
	 * Maybe redirect author archive to team member page (v2.0)
	 *
	 * When viewing /author/username/ and that user has a linked team member,
	 * 301 redirect to the team member page instead.
	 */
	public function maybe_redirect_author_archive() {
		// Only on author archives
		if ( ! is_author() ) {
			return;
		}

		// Check if redirect is enabled (default: yes)
		$redirect_enabled = get_option( 'bw_schema_redirect_author_archives', 'yes' );
		if ( $redirect_enabled !== 'yes' ) {
			return;
		}

		// Get the author being viewed
		$author = get_queried_object();
		if ( ! $author || ! isset( $author->ID ) ) {
			return;
		}

		// Check if this author has a linked team member
		if ( ! class_exists( 'BW_Schema_Team_Member' ) ) {
			return;
		}

		$team_post_type = BW_Schema_Team_Member::get_team_post_type();
		if ( ! $team_post_type ) {
			return;
		}

		// Find team member linked to this user
		$team_members = get_posts( array(
			'post_type'      => $team_post_type,
			'posts_per_page' => 1,
			'meta_query'     => array(
				array(
					'key'   => '_bw_schema_linked_user',
					'value' => $author->ID,
				),
			),
		) );

		if ( ! empty( $team_members ) ) {
			$team_member_url = get_permalink( $team_members[0] );
			if ( $team_member_url ) {
				wp_redirect( $team_member_url, 301 );
				exit;
			}
		}
	}

	/**
	 * Render simple fields for schema type
	 */
	private function render_simple_fields( $type, $post_id ) {
		list( $main_type, $sub_type ) = explode( ':', $type );
		
		switch ( $main_type ) {
			case 'article':
				?>
				<div class="bw-schema-simple-field">
					<label><?php _e( 'Article Headline (Optional)', 'bw-ai-schema-pro' ); ?></label>
					<input type="text" name="bw_schema_simple[headline]" class="widefat" 
						placeholder="<?php _e( 'Leave blank to use post title', 'bw-ai-schema-pro' ); ?>" />
				</div>
				<?php
				break;
				
			case 'localbusiness':
				// Get current post meta values
				$price_range = get_post_meta( $post_id, '_bw_schema_price_range', true );
				$global_price_range = get_option( 'bw_schema_price_range', '' );
				$enable_price_range = get_option( 'bw_schema_enable_price_range', 'no' );
				?>
				<div class="bw-schema-simple-field">
					<label><?php _e( 'Business Phone', 'bw-ai-schema-pro' ); ?></label>
					<input type="tel" name="bw_schema_simple[telephone]" class="widefat" />
				</div>
				<div class="bw-schema-simple-field">
					<label><?php _e( 'Business Address', 'bw-ai-schema-pro' ); ?></label>
					<input type="text" name="bw_schema_simple[address]" class="widefat" 
						placeholder="<?php _e( '123 Main St, City, State 12345', 'bw-ai-schema-pro' ); ?>" />
				</div>
				<?php if ( $enable_price_range === 'yes' ) : ?>
				<div class="bw-schema-simple-field">
					<label><?php _e( 'Price Range', 'bw-ai-schema-pro' ); ?></label>
					<select name="bw_schema_price_range" class="widefat">
						<option value=""><?php _e( '-- Use Global Default --', 'bw-ai-schema-pro' ); ?></option>
						<option value="$" <?php selected( $price_range, '$' ); ?>><?php _e( '$ - Inexpensive', 'bw-ai-schema-pro' ); ?></option>
						<option value="$$" <?php selected( $price_range, '$$' ); ?>><?php _e( '$$ - Moderate', 'bw-ai-schema-pro' ); ?></option>
						<option value="$$$" <?php selected( $price_range, '$$$' ); ?>><?php _e( '$$$ - Expensive', 'bw-ai-schema-pro' ); ?></option>
						<option value="$$$$" <?php selected( $price_range, '$$$$' ); ?>><?php _e( '$$$$ - Very Expensive', 'bw-ai-schema-pro' ); ?></option>
					</select>
					<?php if ( $global_price_range ) : ?>
						<span class="description"><?php printf( __( 'Global default: %s', 'bw-ai-schema-pro' ), esc_html( $global_price_range ) ); ?></span>
					<?php endif; ?>
				</div>
				<?php endif; ?>
				<?php
				if ( $sub_type === 'ProfessionalService' || $sub_type === 'ConsultingBusiness' ) {
					?>
					<div class="bw-schema-simple-field">
						<label><?php _e( 'Services Offered', 'bw-ai-schema-pro' ); ?></label>
						<textarea name="bw_schema_simple[services]" class="widefat" rows="3" 
							placeholder="<?php _e( 'Strategic Planning, Digital Marketing, Business Analysis', 'bw-ai-schema-pro' ); ?>"></textarea>
						<span class="description"><?php _e( 'Comma-separated list of services', 'bw-ai-schema-pro' ); ?></span>
					</div>
					<?php
				}
				break;
				
			case 'person':
				?>
				<div class="bw-schema-simple-field">
					<label><?php _e( 'Job Title', 'bw-ai-schema-pro' ); ?></label>
					<input type="text" name="bw_schema_simple[job_title]" class="widefat" />
				</div>
				<div class="bw-schema-simple-field">
					<label><?php _e( 'Organization', 'bw-ai-schema-pro' ); ?></label>
					<input type="text" name="bw_schema_simple[organization]" class="widefat" />
				</div>
				<?php
				break;
		}
		
		// Common fields for all types
		?>
		<p class="description" style="margin-top: 15px;">
			<?php _e( '💡 These are the most important fields. Additional properties will be automatically added.', 'bw-ai-schema-pro' ); ?>
		</p>
		<?php
	}
	
	/**
	 * AJAX handler for schema preview
	 */
	public function ajax_preview_schema() {
		// Verify nonce
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'bw_schema_nonce' ) ) {
			wp_die();
		}

		// Verify capabilities - user must be able to edit the post
		$post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;
		if ( $post_id && ! current_user_can( 'edit_post', $post_id ) ) {
			wp_send_json_error( 'Insufficient permissions' );
		}
		
		if ( ! $post_id ) {
			wp_send_json_error( 'Invalid post ID' );
		}
		
		// Get the post
		$post = get_post( $post_id );
		if ( ! $post ) {
			wp_send_json_error( 'Post not found' );
		}
		
		// Generate schema
		$renderer = new BW_Schema_Renderer();
		$schema = $renderer->get_post_schema( $post );

		wp_send_json_success( $schema );
	}

	/**
	 * AJAX handler to get taxonomy terms with schema type dropdowns
	 */
	public function ajax_get_taxonomy_terms() {
		// Verify nonce
		if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( $_POST['nonce'], 'bw_schema_setup' ) ) {
			wp_send_json_error( 'Invalid nonce' );
		}

		// Verify capabilities - only admins can access setup wizard
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( 'Insufficient permissions' );
		}

		$taxonomy = isset( $_POST['taxonomy'] ) ? sanitize_key( $_POST['taxonomy'] ) : '';
		$post_type = isset( $_POST['post_type'] ) ? sanitize_key( $_POST['post_type'] ) : '';

		if ( empty( $taxonomy ) || empty( $post_type ) ) {
			wp_send_json_error( 'Missing required parameters' );
		}

		// Check taxonomy exists and is valid for this post type
		$tax_object = get_taxonomy( $taxonomy );
		if ( ! $tax_object || ! in_array( $post_type, $tax_object->object_type ) ) {
			wp_send_json_error( 'Invalid taxonomy for this post type' );
		}

		// Get terms
		$terms = get_terms( array(
			'taxonomy'   => $taxonomy,
			'hide_empty' => false,
		) );

		if ( is_wp_error( $terms ) ) {
			wp_send_json_error( 'Error loading terms' );
		}

		if ( empty( $terms ) ) {
			wp_send_json_success( '<p class="description" style="color: #666; font-style: italic;">' .
				__( 'No terms found in this taxonomy.', 'bw-ai-schema-pro' ) . '</p>' );
		}

		// Get existing term mappings
		$taxonomy_mappings = BW_Schema_Core::get_taxonomy_mappings();
		$current_mapping = isset( $taxonomy_mappings[ $post_type ] ) ? $taxonomy_mappings[ $post_type ] : array();
		$term_mappings = $current_mapping['term_mappings'] ?? array();

		// Get schema types for dropdown
		$schema_types = BW_Schema_Core::get_schema_types();

		// Build HTML
		ob_start();
		?>
		<div class="bw-schema-term-mappings" style="background: #fff; padding: 10px; border-radius: 4px;">
			<p style="margin-top: 0;"><strong><?php _e( 'Map terms to schema types:', 'bw-ai-schema-pro' ); ?></strong></p>
			<?php foreach ( $terms as $term ) : ?>
			<div class="bw-schema-field" style="margin-bottom: 8px; display: flex; align-items: center; gap: 10px;">
				<label style="min-width: 150px; font-weight: normal;"><?php echo esc_html( $term->name ); ?></label>
				<select name="taxonomy_mappings[<?php echo esc_attr( $post_type ); ?>][term_mappings][<?php echo esc_attr( $term->slug ); ?>]" style="flex: 1;">
					<option value=""><?php _e( '— Use default —', 'bw-ai-schema-pro' ); ?></option>
					<?php foreach ( $schema_types as $key => $type ) : ?>
					<optgroup label="<?php echo esc_attr( $type['label'] ); ?>">
						<?php foreach ( $type['subtypes'] as $subtype_key => $subtype_label ) : ?>
						<option value="<?php echo esc_attr( $key . ':' . $subtype_key ); ?>" <?php selected( isset( $term_mappings[ $term->slug ] ) ? $term_mappings[ $term->slug ] : '', $key . ':' . $subtype_key ); ?>>
							<?php echo esc_html( $subtype_label ); ?>
						</option>
						<?php endforeach; ?>
					</optgroup>
					<?php endforeach; ?>
				</select>
			</div>
			<?php endforeach; ?>
		</div>
		<?php
		$html = ob_get_clean();
		wp_send_json_success( $html );
	}

	/**
	 * Maybe redirect to setup wizard
	 */
	public function maybe_redirect_to_setup() {
		// Check if setup is complete or skipped
		if ( get_option( 'bw_schema_setup_complete' ) || isset( $_GET['skip_setup'] ) ) {
			if ( isset( $_GET['skip_setup'] ) ) {
				update_option( 'bw_schema_setup_complete', true );
			}
			return;
		}
		
		// Don't redirect if already on setup page
		if ( isset( $_GET['page'] ) && $_GET['page'] === 'bw-ai-schema-setup' ) {
			return;
		}
		
		// Only redirect on plugin pages
		if ( isset( $_GET['page'] ) && strpos( $_GET['page'], 'bw-ai-schema' ) === 0 ) {
			wp_redirect( admin_url( 'options-general.php?page=bw-ai-schema-setup' ) );
			exit;
		}
	}
}

// Initialize plugin
add_action( 'plugins_loaded', array( 'BW_AI_Schema_Pro', 'get_instance' ) );

// Activation hook
register_activation_hook( __FILE__, function() {
	// Load required files first
	require_once BW_SCHEMA_PLUGIN_DIR . 'includes/class-bw-schema-core.php';

	// Create database tables if needed
	BW_Schema_Core::activate();

	// Set default options
	add_option( 'bw_schema_version', BW_SCHEMA_VERSION );

	// Flush rewrite rules
	flush_rewrite_rules();
});

// Deactivation hook
register_deactivation_hook( __FILE__, function() {
	// Clean up
	flush_rewrite_rules();
});