<?php
/**
 * Custom Image Sizes Module
 *
 * @package CustomImageSizes
 * @since 1.0.0
 */

namespace CustomImageSizes;

use WP_PowerSuite\Core\AbstractModule;

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

class Module extends AbstractModule {

	private const MODULE_ID           = 'custom-image-sizes';
	private const MODULE_VERSION      = '1.0.0';
	private const THEME_NAMES_TRANSIENT = 'wpps_cis_theme_size_names';
	private const RESERVED_NAMES        = [ 'thumbnail', 'medium', 'medium_large', 'large' ];
	private const MAX_DIMENSION         = 4096;
	private const MAX_SIZES             = 20;

	/** @var array<int, array{name: string, width: int, height: int, crop: bool}>|null */
	private ?array $custom_sizes_cache = null;

	public function getId(): string {
		return self::MODULE_ID;
	}

	public function getName(): string {
		return __( 'Custom Image Sizes', 'wp-powersuite' );
	}

	public function getVersion(): string {
		return self::MODULE_VERSION;
	}

	public function getDescription(): string {
		return __( 'Add custom image sizes beyond WordPress defaults. Create exact dimensions for hero banners, product thumbnails, or any layout requirement — no code needed.', 'wp-powersuite' );
	}

	public function getContext(): string|array {
		return [ 'admin', 'frontend', 'ajax', 'rest' ];
	}

	private function isLicenseActive(): bool {
		return function_exists( 'wp_powersuite_is_license_valid' ) && wp_powersuite_is_license_valid();
	}

	protected function registerHooks(): void {
		if ( ! $this->isLicenseActive() ) {
			return;
		}

		if ( is_admin() ) {
			add_action( 'init', [ $this, 'captureThemeSizeNames' ], 998 );
		}

		if ( $this->getCustomSizes() === [] ) {
			return;
		}

		add_action( 'init', [ $this, 'registerCustomSizes' ], 999 );
	}

	public function captureThemeSizeNames(): void {
		$theme = $GLOBALS['_wp_additional_image_sizes'] ?? null;
		if ( ! is_array( $theme ) || $theme === [] ) {
			return;
		}

		$names = array_keys( $theme );
		sort( $names );

		$cached = get_transient( self::THEME_NAMES_TRANSIENT );
		if ( is_array( $cached ) ) {
			sort( $cached );
			if ( $cached === $names ) {
				return;
			}
		}

		set_transient( self::THEME_NAMES_TRANSIENT, $names, DAY_IN_SECONDS );
	}

	public function registerCustomSizes(): void {
		foreach ( $this->getCustomSizes() as $size ) {
			$name   = preg_replace( '/[^a-z0-9_]/', '', strtolower( $size['name'] ) );
			$width  = min( max( 0, $size['width'] ), self::MAX_DIMENSION );
			$height = min( max( 0, $size['height'] ), self::MAX_DIMENSION );
			$crop   = $size['crop'];

			if ( $name === '' || in_array( $name, self::RESERVED_NAMES, true ) ) {
				continue;
			}
			if ( $width <= 0 && $height <= 0 ) {
				continue;
			}

			add_image_size( $name, $width, $height, $crop );
		}
	}

	/**
	 * @return array<int, array{name: string, width: int, height: int, crop: bool}>
	 */
	private function getCustomSizes(): array {
		if ( $this->custom_sizes_cache !== null ) {
			return $this->custom_sizes_cache;
		}

		$settings = $this->moduleSettings()->all( [] );
		$sizes    = is_array( $settings ) ? ( $settings['custom_sizes'] ?? [] ) : [];

		if ( ! is_array( $sizes ) || $sizes === [] ) {
			$this->custom_sizes_cache = [];
			return $this->custom_sizes_cache;
		}

		$out = [];
		foreach ( array_slice( $sizes, 0, self::MAX_SIZES ) as $s ) {
			if ( ! is_array( $s ) || empty( $s['name'] ) ) {
				continue;
			}

			$name = substr( preg_replace( '/[^a-z0-9_]/', '', strtolower( (string) $s['name'] ) ), 0, 50 );
			if ( $name === '' || in_array( $name, self::RESERVED_NAMES, true ) ) {
				continue;
			}

			$width  = max( 0, min( self::MAX_DIMENSION, (int) ( $s['width'] ?? 0 ) ) );
			$height = max( 0, min( self::MAX_DIMENSION, (int) ( $s['height'] ?? 0 ) ) );
			if ( $width <= 0 && $height <= 0 ) {
				continue;
			}

			$out[] = [
				'name'   => $name,
				'width'  => $width,
				'height' => $height,
				'crop'   => ! empty( $s['crop'] ),
			];
		}

		$this->custom_sizes_cache = $out;
		return $this->custom_sizes_cache;
	}
}
