<?php
/**
 * Scan plugin library/ folder for core templates and kits.
 *
 * @package AuraBuilder
 */

declare(strict_types=1);

namespace AuraBuilder\Templates;

final class CoreLibrary {

	public static function path(): string {
		return trailingslashit( AURA_BUILDER_PATH ) . 'library';
	}

	/**
	 * @return list<array<string, mixed>>
	 */
	public static function list_templates( ?string $type = null ): array {
		$base = self::path();
		if ( ! is_dir( $base ) ) {
			return array();
		}

		$dirs = array(
			TemplateTypes::COMPONENT => $base . '/components',
			TemplateTypes::PAGE      => $base . '/pages',
			TemplateTypes::HEADER    => $base . '/headers',
			TemplateTypes::FOOTER    => $base . '/footers',
		);

		$out = array();
		foreach ( $dirs as $t => $dir ) {
			if ( $type && $type !== $t ) {
				continue;
			}
			if ( ! is_dir( $dir ) ) {
				continue;
			}
			$files = glob( $dir . '/*.json' ) ?: array();
			foreach ( $files as $file ) {
				$tpl = self::load_file( $file, $t );
				if ( $tpl ) {
					$out[] = $tpl;
				}
			}
		}

		// Kits.
		if ( ! $type || $type === TemplateTypes::KIT ) {
			$kits_dir = $base . '/kits';
			if ( is_dir( $kits_dir ) ) {
				$subs = glob( $kits_dir . '/*', GLOB_ONLYDIR ) ?: array();
				foreach ( $subs as $kit_path ) {
					$manifest = $kit_path . '/manifest.json';
					if ( ! is_file( $manifest ) ) {
						continue;
					}
					$raw = self::read_json( $manifest );
					if ( ! $raw ) {
						continue;
					}
					$id = (string) ( $raw['id'] ?? basename( $kit_path ) );
					$out[] = array(
						'id'        => $id,
						'type'      => TemplateTypes::KIT,
						'subtype'   => (string) ( $raw['category'] ?? 'general' ),
						'name'      => (string) ( $raw['name'] ?? $id ),
						'category'  => (string) ( $raw['category'] ?? 'general' ),
						'tags'      => is_array( $raw['tags'] ?? null ) ? $raw['tags'] : array(),
						'version'   => (string) ( $raw['version'] ?? '1.0.0' ),
						'source'    => TemplateTypes::SOURCE_CORE,
						'thumbnail' => self::thumbnail_url( (string) ( $raw['thumbnail'] ?? '' ), $id, TemplateTypes::KIT ),
						'preview'   => self::preview_kind( TemplateTypes::KIT, (string) ( $raw['category'] ?? '' ), $id ),
						'path'      => $kit_path,
						'manifest'  => $raw,
						'meta'      => array(
							'author'          => (string) ( $raw['author'] ?? 'Aura Builder' ),
							'responsive'      => true,
							'requiredPlugins' => is_array( $raw['requiredPlugins'] ?? null ) ? $raw['requiredPlugins'] : array(),
							'templates'       => is_array( $raw['templates'] ?? null ) ? $raw['templates'] : array(),
							'features'        => is_array( $raw['features'] ?? null ) ? $raw['features'] : array(),
							'pages'           => is_array( $raw['pages'] ?? null ) ? $raw['pages'] : array(),
						),
					);
				}
			}
		}

		usort(
			$out,
			static function ( $a, $b ) {
				return strcasecmp( (string) ( $a['name'] ?? '' ), (string) ( $b['name'] ?? '' ) );
			}
		);
		return $out;
	}

	/**
	 * @return array<string, mixed>|null
	 */
	public static function get_template( string $id ): ?array {
		foreach ( self::list_templates( null ) as $tpl ) {
			if ( (string) ( $tpl['id'] ?? '' ) === $id ) {
				// Load full document for non-kits.
				if ( ( $tpl['type'] ?? '' ) === TemplateTypes::KIT ) {
					return $tpl;
				}
				if ( empty( $tpl['document'] ) && ! empty( $tpl['_file'] ) ) {
					$full = self::load_file( (string) $tpl['_file'], (string) $tpl['type'] );
					return $full;
				}
				return $tpl;
			}
		}
		return null;
	}

	/**
	 * @return array<string, mixed>|null
	 */
	public static function get_kit( string $id ): ?array {
		$tpl = self::get_template( $id );
		if ( ! $tpl || ( $tpl['type'] ?? '' ) !== TemplateTypes::KIT ) {
			// Direct path.
			$path = self::path() . '/kits/' . sanitize_file_name( $id );
			if ( ! is_dir( $path ) ) {
				return null;
			}
			$manifest = self::read_json( $path . '/manifest.json' );
			if ( ! $manifest ) {
				return null;
			}
			return array(
				'id'       => $id,
				'type'     => TemplateTypes::KIT,
				'name'     => (string) ( $manifest['name'] ?? $id ),
				'path'     => $path,
				'manifest' => $manifest,
			);
		}
		return $tpl;
	}

	/**
	 * @return array<string, mixed>|null
	 */
	private static function load_file( string $file, string $type ): ?array {
		$raw = self::read_json( $file );
		if ( ! $raw ) {
			return null;
		}
		$id = (string) ( $raw['id'] ?? pathinfo( $file, PATHINFO_FILENAME ) );
		return array(
			'id'        => $id,
			'type'      => $type,
			'subtype'   => (string) ( $raw['subtype'] ?? '' ),
			'name'      => (string) ( $raw['name'] ?? $id ),
			'category'  => (string) ( $raw['category'] ?? 'general' ),
			'tags'      => is_array( $raw['tags'] ?? null ) ? array_values( $raw['tags'] ) : array(),
			'version'   => (string) ( $raw['version'] ?? '1.0.0' ),
			'source'    => TemplateTypes::SOURCE_CORE,
			'thumbnail' => self::thumbnail_url( (string) ( $raw['thumbnail'] ?? '' ), $id, $type ),
			'preview'   => self::preview_kind( $type, (string) ( $raw['subtype'] ?? '' ), $id ),
			'document'  => is_array( $raw['document'] ?? null ) ? $raw['document'] : null,
			'meta'      => is_array( $raw['meta'] ?? null ) ? $raw['meta'] : array(
				'author'     => 'Aura Builder',
				'responsive' => true,
			),
			'_file'     => $file,
		);
	}

	/**
	 * Resolve relative library path → full plugin URL (for admin cards).
	 * Tries declared path, then sensible fallbacks from template id.
	 */
	public static function thumbnail_url( string $relative, string $id = '', string $type = '' ): string {
		$relative = ltrim( str_replace( '\\', '/', $relative ), '/' );
		// Absolute URL already.
		if ( $relative !== '' && preg_match( '#^https?://#i', $relative ) ) {
			return $relative;
		}

		$candidates = array();
		if ( $relative !== '' ) {
			$candidates[] = $relative;
			$candidates[] = 'previews/' . basename( $relative );
		}

		if ( $id !== '' ) {
			$slug = (string) ( preg_replace( '/^core-/', '', $id ) ?: $id );
			// core-page-home-blog → page-home-blog; core-portfolio-home → portfolio-home
			if ( $type === TemplateTypes::KIT ) {
				$candidates[] = 'previews/kit-' . $slug . '.svg';
				$kit_slug     = (string) ( preg_replace( '/^kit-/', '', $slug ) ?: $slug );
				$candidates[] = 'previews/kit-' . $kit_slug . '.svg';
			}
			$candidates[] = 'previews/' . $slug . '.svg';
			// Strip type prefix: page-, header-, footer-, component-
			$short = (string) ( preg_replace( '/^(page|header|footer|component|section)-/', '', $slug ) ?: $slug );
			if ( $short !== '' && $short !== $slug ) {
				$candidates[] = 'previews/' . $short . '.svg';
			}
			// page-home-blog → home-blog (already short), also try without "page-"
			if ( str_starts_with( $slug, 'page-' ) ) {
				$candidates[] = 'previews/' . substr( $slug, 5 ) . '.svg';
			}
		}

		// Also try filename-based slugs (home-school-b, contact-c, landing-d…).
		if ( $id !== '' ) {
			$file_slug = (string) ( preg_replace( '/^core-(page-)?/', '', $id ) ?: $id );
			$candidates[] = 'previews/' . $file_slug . '.svg';
			// core-home-school-b already handled; core-page-contact → contact
			if ( str_contains( $file_slug, '-' ) ) {
				$parts = explode( '-', $file_slug );
				$last  = end( $parts );
				if ( in_array( $last, array( 'a', 'b', 'c', 'd' ), true ) && count( $parts ) > 1 ) {
					// keep full slug; also try without variant letter for fallbacks
					$base_no_var = implode( '-', array_slice( $parts, 0, -1 ) );
					$candidates[] = 'previews/' . $base_no_var . '.svg';
				}
			}
		}

		$candidates = array_values( array_unique( array_filter( $candidates ) ) );
		foreach ( $candidates as $rel ) {
			$rel  = ltrim( str_replace( '\\', '/', $rel ), '/' );
			$path = trailingslashit( AURA_BUILDER_PATH ) . 'library/' . $rel;
			if ( is_file( $path ) ) {
				$url = trailingslashit( AURA_BUILDER_URL ) . 'library/' . str_replace( '%2F', '/', implode( '/', array_map( 'rawurlencode', explode( '/', $rel ) ) ) );
				// Cache-bust so new previews appear after deploy.
				$ver = (string) filemtime( $path );
				return $url . ( str_contains( $url, '?' ) ? '&' : '?' ) . 'v=' . rawurlencode( $ver );
			}
			// Basename under previews/
			$base = basename( $rel );
			$alt  = trailingslashit( AURA_BUILDER_PATH ) . 'library/previews/' . $base;
			if ( is_file( $alt ) ) {
				$url = trailingslashit( AURA_BUILDER_URL ) . 'library/previews/' . rawurlencode( $base );
				$ver = (string) filemtime( $alt );
				return $url . '?v=' . rawurlencode( $ver );
			}
		}

		return '';
	}

	/**
	 * CSS wireframe class hint when no image.
	 */
	public static function preview_kind( string $type, string $subtype, string $id ): string {
		$id = strtolower( $id );
		if ( $type === TemplateTypes::KIT ) {
			if ( str_contains( $id, 'restaurant' ) ) {
				return 'kit-restaurant';
			}
			if ( str_contains( $id, 'portfolio' ) ) {
				return 'kit-portfolio';
			}
			if ( str_contains( $id, 'real' ) || str_contains( $id, 'estate' ) ) {
				return 'kit-realestate';
			}
			return 'kit';
		}
		if ( $subtype === 'hero' || str_contains( $id, 'hero' ) ) {
			return 'hero';
		}
		if ( $subtype === 'cta' || str_contains( $id, 'cta' ) ) {
			return 'cta';
		}
		if ( str_contains( $id, 'feature' ) || str_contains( $id, 'card' ) ) {
			return 'features';
		}
		if ( $type === TemplateTypes::HEADER ) {
			return 'header';
		}
		if ( $type === TemplateTypes::FOOTER ) {
			return 'footer';
		}
		if ( $type === TemplateTypes::PAGE ) {
			return 'page';
		}
		return 'section';
	}

	/**
	 * @return array<string, mixed>|null
	 */
	public static function read_json( string $file ): ?array {
		if ( ! is_file( $file ) ) {
			return null;
		}
		$raw = file_get_contents( $file );
		if ( ! is_string( $raw ) || $raw === '' ) {
			return null;
		}
		$data = json_decode( $raw, true );
		return is_array( $data ) ? $data : null;
	}
}
