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

class CCGAL_Cache {

	const SIZE_THUMB  = 'thumb';
	const SIZE_MEDIUM = 'medium';

	public static function init() {
		add_action( 'ccgal_cache_cleanup', array( __CLASS__, 'cleanup_stale' ) );
		// Note: cron schedule is registered in CCGAL_Activator::activate() (one-time).
		// Hitting wp_next_scheduled() on every page load is a flagged anti-pattern.
	}

	public static function get_dir() {
		$upload = wp_upload_dir();
		$dir    = trailingslashit( $upload['basedir'] ) . 'ccgal-cache';
		if ( ! file_exists( $dir ) ) {
			wp_mkdir_p( $dir );
		}
		return $dir;
	}

	public static function get_url() {
		$upload = wp_upload_dir();
		return trailingslashit( $upload['baseurl'] ) . 'ccgal-cache';
	}

	public static function get_sizes() {
		return array(
			self::SIZE_THUMB  => array(
				'max' => 1200,
				'q'   => 82,
			),
			self::SIZE_MEDIUM => array(
				'max' => 2048,
				'q'   => 85,
			),
		);
	}

	public static function get_cached_path( $file_id, $size ) {
		$file_id = CCGAL_Storage_Adapter::sanitize( $file_id );
		$size    = in_array( $size, array( self::SIZE_THUMB, self::SIZE_MEDIUM ), true ) ? $size : self::SIZE_THUMB;
		return self::get_dir() . '/' . $file_id . '_' . $size . '.jpg';
	}

	public static function get_cached_url( $file_id, $size ) {
		$file_id = CCGAL_Storage_Adapter::sanitize( $file_id );
		$size    = in_array( $size, array( self::SIZE_THUMB, self::SIZE_MEDIUM ), true ) ? $size : self::SIZE_THUMB;
		return self::get_url() . '/' . $file_id . '_' . $size . '.jpg';
	}

	public static function is_cached( $file_id, $size ) {
		return file_exists( self::get_cached_path( $file_id, $size ) );
	}

	public static function ensure_cached( $file_id, $size, $provider = 'google_drive' ) {
		$path = self::get_cached_path( $file_id, $size );
		if ( file_exists( $path ) ) {
			// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_touch -- best-effort mtime bump on the plugin's own cache file inside the uploads dir; WP_Filesystem requires interactive FTP credentials on some hosts and is overkill for a silently-no-op'd cache hygiene call.
			@touch( $path );
			return self::get_cached_url( $file_id, $size );
		}

		$sizes = self::get_sizes();
		if ( ! isset( $sizes[ $size ] ) ) {
			return new WP_Error( 'ccgal_bad_size', __( 'Invalid image size.', 'customer-cloud-gallery' ) );
		}

		$max = (int) $sizes[ $size ]['max'];

		$adapter      = CCGAL_Storage::adapter( $provider );
		$thumb_result = $adapter->download_thumbnail( $file_id, $max, $path );
		if ( ! is_wp_error( $thumb_result ) && file_exists( $path ) && filesize( $path ) > 0 ) {
			return self::get_cached_url( $file_id, $size );
		}

		$tmp  = wp_tempnam( 'ccgal-orig-' . $file_id );
		$full = $adapter->download_to_file( $file_id, $tmp );
		if ( is_wp_error( $full ) ) {
			wp_delete_file( $tmp );
			return $full;
		}

		$result = self::resize_image( $tmp, $path, $max, $sizes[ $size ]['q'] );
		wp_delete_file( $tmp );

		if ( is_wp_error( $result ) ) {
			return $result;
		}

		return self::get_cached_url( $file_id, $size );
	}

	private static function resize_image( $src_path, $dest_path, $max_dim, $quality ) {
		$editor = wp_get_image_editor( $src_path );
		if ( is_wp_error( $editor ) ) {
			return $editor;
		}

		$size = $editor->get_size();
		if ( $size && ( $size['width'] > $max_dim || $size['height'] > $max_dim ) ) {
			$editor->resize( $max_dim, $max_dim, false );
		}

		$editor->set_quality( $quality );

		$saved = $editor->save( $dest_path, 'image/jpeg' );
		if ( is_wp_error( $saved ) ) {
			return $saved;
		}

		if ( isset( $saved['path'] ) && $saved['path'] !== $dest_path ) {
			// phpcs:ignore WordPress.WP.AlternativeFunctions.rename_rename -- post-fix for wp_get_image_editor() which sometimes saves to a different path; both paths are inside the just-written-to cache dir, so direct rename() is safe and avoids an extra WP_Filesystem round-trip.
			@rename( $saved['path'], $dest_path );
		}

		return true;
	}

	public static function cleanup_stale() {
		$dir = self::get_dir();
		if ( ! is_dir( $dir ) ) {
			return;
		}

		$ttl   = apply_filters( 'ccgal_cache_ttl', 60 * DAY_IN_SECONDS );
		$limit = time() - $ttl;

		$handle = opendir( $dir );
		if ( ! $handle ) {
			return;
		}

		while ( false !== ( $entry = readdir( $handle ) ) ) { // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition
			if ( '.' === $entry || '..' === $entry ) {
				continue;
			}
			$file = $dir . '/' . $entry;
			if ( ! is_file( $file ) ) {
				continue;
			}
			if ( substr( $entry, -4 ) !== '.jpg' ) {
				continue;
			}
			if ( filemtime( $file ) < $limit ) {
				wp_delete_file( $file );
			}
		}
		closedir( $handle );
	}

	public static function clear_all() {
		$dir = self::get_dir();
		if ( ! is_dir( $dir ) ) {
			return 0;
		}
		$count  = 0;
		$handle = opendir( $dir );
		while ( false !== ( $entry = readdir( $handle ) ) ) { // phpcs:ignore WordPress.CodeAnalysis.AssignmentInCondition
			if ( '.' === $entry || '..' === $entry ) {
				continue;
			}
			$file = $dir . '/' . $entry;
			if ( is_file( $file ) && substr( $entry, -4 ) === '.jpg' ) {
				wp_delete_file( $file );
				if ( ! file_exists( $file ) ) {
					$count++;
				}
			}
		}
		closedir( $handle );
		return $count;
	}
}
