<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class StakMV_Sample_Data
 *
 * Adds admin UI to insert sample product categories, global attributes and
 * category => attribute mappings. Idempotent and safe to run multiple times.
 *
 * Usage:
 *  - The class registers admin hooks on init when this file is required.
 */
class StakMV_Sample_Data {

	/**
	 * Entry point - register hooks.
	 */
	public static function init() {
		add_action( 'stakmv_auctions_settings_tabs', array( __CLASS__, 'render_settings_tab_link' ), 10, 1 );
		add_action( 'stakmv_auctions_render_tab_sample_data', array( __CLASS__, 'render_settings_tab' ) );
		add_action( 'admin_post_stakmv_insert_sample_data', array( __CLASS__, 'handle_insert_action' ) );
	}

	/**
	 * Output the tab link in the admin settings tabs.
	 *
	 * @param string $current_tab Current active tab slug.
	 */
	public static function render_settings_tab_link( $current_tab ) {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			return;
		}
		$active = $current_tab === 'sample_data' ? 'nav-tab-active' : '';
		printf(
			'<a href="?page=stakmv-auctions&tab=sample_data" class="nav-tab %s">Sample Data</a>',
			esc_attr( $active )
		);
	}

	/**
	 * Render the content for the Sample Data tab.
	 */
	public static function render_settings_tab() {
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			echo '<p>Insufficient permissions.</p>';
			return;
		}

		// Show success notice if redirected back after insert.
		// phpcs:disable WordPress.Security.NonceVerification.Recommended -- read-only notice flag.
		$inserted_flag = isset( $_GET['stakmv_sample_data_inserted'] )
			? sanitize_text_field( wp_unslash( $_GET['stakmv_sample_data_inserted'] ) )
			: '';
		// phpcs:enable WordPress.Security.NonceVerification.Recommended
		if ( $inserted_flag !== '' ) {
			echo '<div class="updated"><p>Sample categories, attributes and mappings inserted (or already present).</p></div>';
		}

		$feedback_key = 'stakmv_sample_data_feedback_' . get_current_user_id();
		$feedback = get_transient( $feedback_key );
		if ( is_array( $feedback ) && ! empty( $feedback['errors'] ) ) {
			echo '<div class="notice notice-warning"><p>Sample Data completed with warnings:</p><ul class="wcmv-sample-warnings-list">';
			foreach ( $feedback['errors'] as $err ) {
				echo '<li>' . esc_html( (string) $err ) . '</li>';
			}
			echo '</ul></div>';
			delete_transient( $feedback_key );
		}

		// Nonce-protected form posts to admin-post.php
		$action_url = esc_url( admin_url( 'admin-post.php' ) );
		$description = esc_html__( 'Insert a set of marketplace-style sample categories, global attributes and category→attribute mappings. This operation is idempotent; running it multiple times will not create duplicates.', 'stak-multivendor' );
		?>
		<h2>Sample Data</h2>
			<p><?php echo esc_html( $description ); ?></p>

			<form method="post" action="<?php echo esc_url( $action_url ); ?>">
			<?php wp_nonce_field( 'stakmv_sample_data_action', 'stakmv_sample_data_nonce' ); ?>
			<input type="hidden" name="action" value="stakmv_insert_sample_data">
			<p>
				<label>
					<input type="checkbox" name="stakmv_sample_data_override" value="1">
					<?php esc_html_e( 'Override existing data with the same name/slug', 'stak-multivendor' ); ?>
				</label>
			</p>
			<p>
				<button type="submit" class="button button-primary">
					<?php esc_html_e( 'Insert Sample Categories & Attributes', 'stak-multivendor' ); ?>
				</button>
			</p>
		</form>
		<?php
	}

	/**
	 * Handle the admin_post action to insert sample data.
	 */
	public static function handle_insert_action() {
		// Capability and nonce checks
		if ( ! current_user_can( 'manage_woocommerce' ) ) {
			wp_die( esc_html__( 'Insufficient permissions', 'stak-multivendor' ) );
		}

		if ( ! isset( $_POST['stakmv_sample_data_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['stakmv_sample_data_nonce'] ) ), 'stakmv_sample_data_action' ) ) {
			wp_die( esc_html__( 'Security check failed', 'stak-multivendor' ) );
		}

		// Perform insertion (guarded inside function for testability)
		$override_existing = ! empty( $_POST['stakmv_sample_data_override'] );
		$result = self::perform_insertion( $override_existing );
		set_transient(
			'stakmv_sample_data_feedback_' . get_current_user_id(),
			array(
				'errors' => isset( $result['errors'] ) && is_array( $result['errors'] ) ? $result['errors'] : array(),
			),
			MINUTE_IN_SECONDS
		);

		// Redirect back to settings page (preserve referrer if available)
		$referer = wp_get_referer();
		if ( $referer ) {
			$redirect = add_query_arg( 'stakmv_sample_data_inserted', 1, $referer );
		} else {
			$redirect = add_query_arg(
				array(
					'page'                         => 'stakmv-auctions',
					'tab'                          => 'sample_data',
					'stakmv_sample_data_inserted'    => 1,
				),
				admin_url( 'admin.php' )
			);
		}

		// We could add more detailed feedback in future (transient), but keep it simple.
		wp_safe_redirect( $redirect );
		exit;
	}

	/**
	 * Perform the idempotent creation of categories, attributes, terms and mappings.
	 *
	 * @return array Summary of created / skipped items.
	 */
	public static function perform_insertion( $override_existing = false ) {
		$summary = array(
			'attributes_created' => array(),
			'terms_created'      => array(),
			'categories_created' => array(),
			'mappings_added'     => array(),
			'errors'             => array(),
		);

		// Ensure WooCommerce functions are available.
		if ( ! function_exists( 'wc_create_attribute' ) || ! function_exists( 'wc_get_attribute_taxonomies' ) ) {
			$summary['errors'][] = 'WooCommerce functions are not available.';
			return $summary;
		}

		$dataset = self::load_embedded_dataset();

		// 1) Global attributes to ensure exist
		$attributes = array(
			'Brand',
			'Processor Brand',
			'Graphics Card Brand',
			'Graphics Card Model',
			'RAM Size',
			'Storage Type',
			'Storage Capacity',
			'Condition',
		);
		if ( isset( $dataset['attributes'] ) && is_array( $dataset['attributes'] ) ) {
			$attributes = array_values( array_filter( array_map( 'strval', $dataset['attributes'] ) ) );
		}

		// Map of friendly attribute -> sample terms to create
		$sample_terms = array(
			'Brand'  => array( 'HP', 'Dell', 'Lenovo', 'Apple' ),
			'Processor Brand' => array( 'Intel', 'AMD' ),
			'Graphics Card Brand' => array( 'NVIDIA', 'AMD' ),
			'Graphics Card Model' => array(
				'RTX 2060',
				'RTX 3060',
				'RTX 3070',
				'RTX 3080',
				'RX 6600',
				'RX 6700 XT',
			),
			'RAM Size' => array( '8GB', '16GB', '32GB', '64GB' ),
			'Storage Type' => array( 'SSD', 'HDD' ),
			'Storage Capacity' => array( '256GB', '512GB', '1TB', '2TB' ),
			'Condition' => array( 'New', 'Used', 'Refurbished' ),
		);
		if ( isset( $dataset['attribute_terms'] ) && is_array( $dataset['attribute_terms'] ) ) {
			$sample_terms = $dataset['attribute_terms'];
		}

		// Create attributes idempotently
		foreach ( $attributes as $attr_name ) {
			try {
				$taxonomy = self::create_attribute_if_not_exists( $attr_name );
				if ( $taxonomy ) {
					$summary['attributes_created'][] = $taxonomy;
				}
			} catch ( Exception $e ) {
				$summary['errors'][] = $e->getMessage();
			}
		}

		// After creating attributes, clear attribute cache if helper available
		if ( function_exists( 'wc_delete_attribute_cache' ) ) {
			wc_delete_attribute_cache();
		} else {
			delete_transient( 'wc_attribute_taxonomies' );
		}

		// Create sample terms for selected attributes
		foreach ( $sample_terms as $attr => $terms ) {
			$taxonomy = 'pa_' . sanitize_title( $attr );
			if ( ! taxonomy_exists( $taxonomy ) ) {
				// Skip silently if taxonomy missing (shouldn't happen)
				$summary['errors'][] = "Missing taxonomy {$taxonomy} for attribute {$attr}.";
				continue;
			}
			foreach ( $terms as $t ) {
				$term_id = self::create_term_if_not_exists( $t, $taxonomy, '', null, (bool) $override_existing );
				if ( $term_id ) {
					$summary['terms_created'][] = "{$taxonomy}:{$t}";

					// Special handling: for Graphics Card Model, set parent_brand term meta
					if ( $taxonomy === 'pa_' . sanitize_title( 'Graphics Card Model' ) ) {
						// Determine brand by model prefix: RTX -> nvidia, RX -> amd
						if ( preg_match( '/^RTX/i', $t ) ) {
							update_term_meta( $term_id, 'parent_brand', 'nvidia' );
						} elseif ( preg_match( '/^RX/i', $t ) ) {
							update_term_meta( $term_id, 'parent_brand', 'amd' );
						}
					}
				}
			}
		}

		// 2) Create category tree (generic marketplace-like)
		$tree = array(
			'Electronics' => array( 'Mobile Phones', 'Computers & Tablets', 'Accessories' ),
			'Fashion'     => array( "Men's Clothing", "Women's Clothing", 'Shoes' ),
			'Home & Living' => array( 'Furniture', 'Home Decor' ),
			'Collectibles & Art' => array( 'Coins', 'Trading Cards' ),
			'Vehicles & Parts' => array( 'Cars', 'Motorcycles', 'Parts' ),
		);
		if ( isset( $dataset['categories'] ) && is_array( $dataset['categories'] ) ) {
			$tree = $dataset['categories'];
		}

		$created_categories = array(); // map slug => term_id
		self::insert_category_tree( $tree, 0, $created_categories, $summary, (bool) $override_existing );

		// 3) Category -> attribute mappings (store as term meta 'stakmv_cat_attrs')
		//
		// Use attribute taxonomy slugs, e.g. pa_brand, pa_color, etc.
		$mappings = array(
			'mobile-phones' => array( 'pa_brand', 'pa_model', 'pa_storage-capacity', 'pa_color', 'pa_condition' ),
			'computers-tablets' => array(
				'pa_brand',
				'pa_processor-brand',
				'pa_graphics-card-brand',
				'pa_graphics-card-model',
				'pa_ram-size',
				'pa_storage-type',
				'pa_storage-capacity',
				'pa_condition',
			),
			'shoes'         => array( 'pa_brand', 'pa_size', 'pa_color', 'pa_material', 'pa_condition' ),
			'coins'         => array( 'pa_year', 'pa_country-region-of-manufacture', 'pa_condition' ),
			'cars'          => array( 'pa_brand', 'pa_model', 'pa_year', 'pa_condition' ),
		);
		if ( isset( $dataset['mappings'] ) && is_array( $dataset['mappings'] ) ) {
			$mappings = $dataset['mappings'];
		}

		foreach ( $mappings as $cat_slug => $attrs ) {
			$term_id = isset( $created_categories[ $cat_slug ] ) ? (int) $created_categories[ $cat_slug ] : 0;

			// If not created in this run, try to locate existing term by slug
			if ( $term_id <= 0 ) {
				$existing = get_term_by( 'slug', $cat_slug, 'product_cat' );
				if ( $existing && ! is_wp_error( $existing ) ) {
					$term_id = (int) $existing->term_id;
				}
			}

			if ( $term_id <= 0 ) {
				// Skip silently if category missing
				$summary['errors'][] = "Category '{$cat_slug}' not found to apply mapping.";
				continue;
			}

			// Ensure only existing attribute taxonomies are stored
			$valid_attrs = array();
			foreach ( $attrs as $tax ) {
				if ( taxonomy_exists( $tax ) ) {
					$valid_attrs[] = $tax;
				}
			}

			if ( ! empty( $valid_attrs ) ) {
				update_term_meta( $term_id, 'stakmv_cat_attrs', $valid_attrs );
				$summary['mappings_added'][] = "{$cat_slug} => " . implode( ',', $valid_attrs );
			}
		}

		return $summary;
	}

	/**
	 * Load bundled sample dataset from plugin files.
	 *
	 * @return array
	 */
	private static function load_embedded_dataset() {
		$file = STAKMV_PLUGIN_PATH . 'includes/admin/data/sample-data.json';
		if ( ! file_exists( $file ) ) {
			return array();
		}

		$json = file_get_contents( $file );
		if ( false === $json || '' === trim( $json ) ) {
			return array();
		}

		$data = json_decode( $json, true );
		return is_array( $data ) ? $data : array();
	}

	/**
	 * Insert categories recursively from tree structure.
	 *
	 * Supported formats:
	 * - { "Parent": ["Child A", "Child B"] }
	 * - { "Parent": { "Child A": ["Grandchild"] } }
	 *
	 * @param array $tree Category tree.
	 * @param int $parent_id Parent term ID.
	 * @param array $created_categories Slug => term_id map.
	 * @param array $summary Summary collector.
	 * @return void
	 */
	private static function insert_category_tree( $tree, $parent_id, &$created_categories, &$summary, $override_existing = false ) {
		foreach ( $tree as $name => $children ) {
			$term_name = is_string( $name ) ? $name : ( is_string( $children ) ? $children : '' );
			if ( '' === $term_name ) {
				continue;
			}

			$slug = sanitize_title( $term_name );
			$term = self::create_term_if_not_exists( $term_name, 'product_cat', $slug, (int) $parent_id, (bool) $override_existing );
			if ( is_wp_error( $term ) ) {
				$summary['errors'][] = $term->get_error_message();
				continue;
			}

			$term_id = (int) $term;
			$created_categories[ $slug ] = $term_id;
			$summary['categories_created'][] = $term_name;

			$next_children = array();
			if ( is_array( $children ) ) {
				if ( array_values( $children ) === $children ) {
					// Indexed array children: normalize to key => [].
					foreach ( $children as $child_name ) {
						if ( is_string( $child_name ) ) {
							$next_children[ $child_name ] = array();
						}
					}
				} else {
					$next_children = $children;
				}
			}

			if ( ! empty( $next_children ) ) {
				self::insert_category_tree( $next_children, $term_id, $created_categories, $summary, (bool) $override_existing );
			}
		}
	}

	/**
	 * Create a global product attribute if it does not already exist.
	 *
	 * @param string $name Attribute label (e.g. 'Brand').
	 * @return string|false The attribute taxonomy (pa_...) on success, false on failure or if already exists.
	 * @throws Exception on failure.
	 */
	private static function create_attribute_if_not_exists( $name ) {
		$slug = sanitize_title( $name );
		$taxonomy = 'pa_' . $slug;

		// If taxonomy exists already, return its name.
		if ( taxonomy_exists( $taxonomy ) ) {
			return $taxonomy;
		}

		// Check existing attribute definitions (WooCommerce)
		$existing = wc_get_attribute_taxonomies();
		if ( ! empty( $existing ) ) {
			foreach ( $existing as $def ) {
				if ( isset( $def->attribute_name ) && $def->attribute_name === $slug ) {
					// Ensure taxonomy is registered: return taxonomy slug
					return 'pa_' . $def->attribute_name;
				}
			}
		}

		// Create attribute via WooCommerce helper
		$attribute_data = array(
			'attribute_name' => $slug,
			'attribute_label' => $name,
			'attribute_type' => 'select',
			'attribute_orderby' => 'menu_order',
			'attribute_public' => 0,
		);

		// Use wc_create_attribute where available (WC >= 3.6)
		if ( function_exists( 'wc_create_attribute' ) ) {
			$attr_id = wc_create_attribute( array(
				'name'       => $name,
				'slug'       => $slug,
				'type'       => 'select',
				'order_by'   => 'menu_order',
				'has_archives' => false,
			) );

			if ( is_wp_error( $attr_id ) ) {
				throw new Exception( 'Failed to create attribute definition.' );
			}

			// Registering taxonomy is handled by core; return taxonomy slug.
			return 'pa_' . $slug;
		}

		// Fallback: attempt to insert directly into wc_attribute_taxonomies table - avoid if impossible.
		throw new Exception( 'wc_create_attribute not available; cannot create attribute definition.' );
	}

	/**
	 * Create a term if it does not exist.
	 *
	 * @param string   $name     Term name.
	 * @param string   $taxonomy Taxonomy.
	 * @param string   $slug     Optional slug.
	 * @param int|null $parent   Optional parent term ID.
	 * @return int|WP_Error term_id or WP_Error.
	 */
	private static function create_term_if_not_exists( $name, $taxonomy = 'product_cat', $slug = '', $parent = null, $override_existing = false ) {
		$slug = $slug ? $slug : sanitize_title( $name );

		$existing = get_term_by( 'slug', $slug, $taxonomy );
		if ( $existing && ! is_wp_error( $existing ) ) {
			if ( $override_existing ) {
				$update_args = array(
					'name' => $name,
					'slug' => $slug,
				);
				if ( null !== $parent ) {
					$update_args['parent'] = (int) $parent;
				}
				wp_update_term( (int) $existing->term_id, $taxonomy, $update_args );
			}
			return (int) $existing->term_id;
		}

		$args = array();
		if ( $parent && is_int( $parent ) ) {
			$args['parent'] = $parent;
		}

		// Use wp_insert_term idempotently
		$insert = wp_insert_term( $name, $taxonomy, array_merge( $args, array( 'slug' => $slug ) ) );
		if ( is_wp_error( $insert ) ) {
			// If term exists by name, try to retrieve it
			$by_name = get_term_by( 'name', $name, $taxonomy );
			if ( $by_name && ! is_wp_error( $by_name ) ) {
				if ( $override_existing ) {
					$update_args = array(
						'name' => $name,
						'slug' => $slug,
					);
					if ( null !== $parent ) {
						$update_args['parent'] = (int) $parent;
					}
					wp_update_term( (int) $by_name->term_id, $taxonomy, $update_args );
				}
				return (int) $by_name->term_id;
			}
			return $insert;
		}

		return is_array( $insert ) && isset( $insert['term_id'] ) ? (int) $insert['term_id'] : 0;
	}
}

// Initialize immediately when file is loaded.
StakMV_Sample_Data::init();
