<?php
/**
 * PSR-4 hand-rolled autoloader for Lens.
 *
 * Avoids Composer to sidestep the vendor/-bundling debate during WP.org review.
 *
 * Mapping rules:
 *   - Namespace segments are lowercased verbatim (e.g. `AI` → `ai`,
 *     `Crawler` → `crawler`). All Lens sub-namespaces are single words,
 *     so a hyphenation pass is unnecessary and was previously buggy on
 *     acronyms.
 *   - Class file names are matched against multiple kebab-case variants
 *     so acronyms like `OpenAIProvider` resolve to `class-openai-provider.php`
 *     (merged) as well as `class-open-ai-provider.php` (smart split) or the
 *     legacy `class-open-a-i-provider.php` (naïve split).
 *
 * @package WPLens
 */

namespace WPLens;

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

final class Autoloader {

	public static function register(): void {
		spl_autoload_register( array( __CLASS__, 'load' ) );
	}

	public static function load( string $class_name ): void {
		// Only handle our own namespace.
		if ( strpos( $class_name, 'WPLens\\' ) !== 0 ) {
			return;
		}

		$relative = substr( $class_name, strlen( 'WPLens\\' ) );
		$relative = str_replace( '\\', '/', $relative );

		$parts     = explode( '/', $relative );
		$file_name = array_pop( $parts );
		$dir       = '' === implode( '', $parts )
			? ''
			: implode( '/', array_map( 'strtolower', $parts ) ) . '/';

		// Build candidate file-name bases. Try the most specific match first.
		$bases = array_unique(
			array(
				self::merged_kebab( $file_name ),  // OpenAIProvider → openai-provider
				self::smart_kebab( $file_name ),   // OpenAIProvider → open-ai-provider
				self::naive_kebab( $file_name ),   // OpenAIProvider → open-a-i-provider
			)
		);

		$prefixes = array( 'class-', 'interface-', 'trait-' );

		foreach ( $bases as $base ) {
			foreach ( $prefixes as $prefix ) {
				$candidate = WPLENS_PLUGIN_DIR . 'includes/' . $dir . $prefix . $base . '.php';
				if ( file_exists( $candidate ) ) {
					require_once $candidate;
					return;
				}
			}
		}
	}

	/**
	 * Insert hyphens at lowercase→uppercase boundaries only.
	 * Acronyms stay merged: `OpenAIProvider` → `openai-provider`.
	 */
	private static function merged_kebab( string $name ): string {
		$out = (string) preg_replace( '/(?<=[a-z])(?=[A-Z])/', '-', $name );
		$out = strtolower( $out );
		return str_replace( '_', '-', $out );
	}

	/**
	 * Insert hyphens at lowercase→uppercase AND at acronym→PascalCase boundaries:
	 * `OpenAIProvider` → `open-ai-provider`.
	 */
	private static function smart_kebab( string $name ): string {
		$out = (string) preg_replace(
			'/(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])/',
			'-',
			$name
		);
		$out = strtolower( $out );
		return str_replace( '_', '-', $out );
	}

	/**
	 * Insert hyphens before every uppercase (legacy WP-style):
	 * `OpenAIProvider` → `open-a-i-provider`.
	 */
	private static function naive_kebab( string $name ): string {
		$out = (string) preg_replace( '/(?<!^)([A-Z])/', '-$1', $name );
		$out = strtolower( $out );
		return str_replace( '_', '-', $out );
	}
}
