<?php

namespace SugarCalendarBookings\Support\Helpers;

/**
 * Class ImageUploader.
 *
 * Helper for uploading images to the WordPress media library.
 *
 * @since 1.2.0
 */
class ImageUploader {

	/**
	 * Supported mime types and their extensions.
	 *
	 * @since 1.2.0
	 *
	 * @var array
	 */
	private const EXTENSIONS = [
		'image/jpeg' => 'jpg',
		'image/png'  => 'png',
		'image/gif'  => 'gif',
		'image/webp' => 'webp',
	];

	/**
	 * Upload a base64 encoded image to the media library.
	 *
	 * @since 1.2.0
	 *
	 * @param string $base64_data Base64 encoded image data (with or without data URI prefix).
	 * @param string $name        Name for the file (used in filename and title).
	 *
	 * @return int|false Attachment ID on success, false on failure.
	 */
	public static function upload_base64( $base64_data, $name = 'image' ) {

		$parsed = self::parse_base64_data( $base64_data );

		if ( ! $parsed ) {
			return false;
		}

		$upload = self::save_to_uploads( $parsed['data'], $parsed['mime_type'], $name );

		if ( ! $upload ) {
			return false;
		}

		return self::create_attachment( $upload, $parsed['mime_type'], $name );
	}

	/**
	 * Parse base64 data URI and extract mime type and raw data.
	 *
	 * @since 1.2.0
	 *
	 * @param string $base64_data Base64 encoded image data.
	 *
	 * @return array|false Array with 'mime_type' and 'data' keys, or false on failure.
	 */
	private static function parse_base64_data( $base64_data ) {

		$mime_type = 'image/jpeg';

		// Parse data URI format: data:image/jpeg;base64,/9j/4AAQ...
		if ( strpos( $base64_data, 'data:' ) === 0 ) {
			$parts = explode( ',', $base64_data, 2 );

			if ( count( $parts ) !== 2 ) {
				return false;
			}

			// Extract mime type from data:image/jpeg;base64.
			preg_match( '/data:([^;]+);/', $parts[0], $matches );
			$mime_type   = $matches[1] ?? 'image/jpeg';
			$base64_data = $parts[1];
		}

		// Decode base64 data.
		$image_data = base64_decode( $base64_data ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode

		if ( ! $image_data ) {
			return false;
		}

		return [
			'mime_type' => $mime_type,
			'data'      => $image_data,
		];
	}

	/**
	 * Save image data to WordPress uploads directory.
	 *
	 * @since 1.2.0
	 *
	 * @param string $image_data Binary image data.
	 * @param string $mime_type  Image mime type.
	 * @param string $name       Name for the file.
	 *
	 * @return array|false Upload result array or false on failure.
	 */
	private static function save_to_uploads( $image_data, $mime_type, $name ) {

		$extension = self::EXTENSIONS[ $mime_type ] ?? 'jpg';
		$filename  = sanitize_file_name( $name ) . '-' . uniqid() . '.' . $extension;

		$upload = wp_upload_bits( $filename, null, $image_data );

		if ( ! empty( $upload['error'] ) ) {
			return false;
		}

		return $upload;
	}

	/**
	 * Create WordPress attachment from uploaded file.
	 *
	 * @since 1.2.0
	 *
	 * @param array  $upload    Upload result from wp_upload_bits.
	 * @param string $mime_type Image mime type.
	 * @param string $name      Name for the attachment.
	 *
	 * @return int|false Attachment ID or false on failure.
	 */
	private static function create_attachment( $upload, $mime_type, $name ) {

		$attachment = [
			'post_mime_type' => $mime_type,
			'post_title'     => sanitize_file_name( $name ),
			'post_content'   => '',
			'post_status'    => 'inherit',
		];

		$attachment_id = wp_insert_attachment( $attachment, $upload['file'] );

		if ( is_wp_error( $attachment_id ) || ! $attachment_id ) {
			return false;
		}

		// Generate attachment metadata.
		require_once ABSPATH . 'wp-admin/includes/image.php';

		$metadata = wp_generate_attachment_metadata( $attachment_id, $upload['file'] );

		wp_update_attachment_metadata( $attachment_id, $metadata );

		return $attachment_id;
	}
}
