<?php

// phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedNamespaceFound -- APD is the established namespace shared with the Pro add-on and retained for backward compatibility.
namespace APD\Support;

use APD\Admin\AdminSettings;

defined('ABSPATH') || exit;

class PreviewStorage
{
    public function store(string $dataUrl, string $prefix = 'apd-preview', array $args = []) : array
    {
        if (! preg_match('#^data:image/(png|jpeg);base64,(.*)$#', $dataUrl, $matches)) {
            return ['success' => false, 'message' => __('Unsupported preview format.', 'asuka-product-designer')];
        }

        $extension = $matches[1] === 'jpeg' ? 'jpg' : 'png';
        $binary = base64_decode($matches[2], true);

        if ($binary === false) {
            return ['success' => false, 'message' => __('Preview decoding failed.', 'asuka-product-designer')];
        }

        $defaultMaxBytes = (new AdminSettings())->uploadMaxBytes(10);
        // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- The apd_ hook is a documented integration API retained for backward compatibility.
        $maxBytes = (int) apply_filters('apd_preview_max_bytes', $defaultMaxBytes, $prefix, $args);
        if ($maxBytes > 0 && strlen($binary) > $maxBytes) {
            return [
                'success' => false,
                'message' => sprintf(
                    /* translators: %s = maximum preview size */
                    __('The preview image exceeds the maximum allowed size of %s.', 'asuka-product-designer'),
                    size_format($maxBytes)
                ),
            ];
        }

        $upload = wp_upload_bits(sanitize_file_name($prefix . '-' . wp_generate_password(10, false, false) . '.' . $extension), null, $binary);

        if (! empty($upload['error'])) {
            return ['success' => false, 'message' => $upload['error']];
        }

        if (! function_exists('wp_insert_attachment')) {
            require_once ABSPATH . 'wp-admin/includes/post.php';
        }

        if (! function_exists('wp_generate_attachment_metadata') || ! function_exists('wp_update_attachment_metadata')) {
            require_once ABSPATH . 'wp-admin/includes/image.php';
        }

        if (! function_exists('wp_handle_sideload') || ! function_exists('wp_upload_bits')) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
        }

        if (! function_exists('wp_read_image_metadata')) {
            require_once ABSPATH . 'wp-admin/includes/media.php';
        }

        $filetype = wp_check_filetype($upload['file'], null);
        $attachmentId = wp_insert_attachment([
            'post_mime_type' => $filetype['type'] ?? 'image/' . $extension,
            'post_title' => sanitize_file_name(pathinfo($upload['file'], PATHINFO_FILENAME)),
            'post_status' => 'inherit',
        ], $upload['file']);

        if ($attachmentId && ! is_wp_error($attachmentId)) {
            $metadata = wp_generate_attachment_metadata($attachmentId, $upload['file']);
            if (! is_wp_error($metadata)) {
                wp_update_attachment_metadata($attachmentId, $metadata);
            }

            if (! empty($args['temporary'])) {
                update_post_meta((int) $attachmentId, '_apd_temporary_preview', '1');
            }

            if (! empty($args['context'])) {
                update_post_meta((int) $attachmentId, '_apd_preview_context', sanitize_key((string) $args['context']));
            }
        }

        return [
            'success' => true,
            'url' => $upload['url'],
            'attachmentId' => (int) $attachmentId,
        ];
    }

    public function attachmentIdFromUrl(string $url) : int
    {
        $url = esc_url_raw($url);
        if ($url === '') {
            return 0;
        }

        $attachmentId = function_exists('attachment_url_to_postid') ? (int) attachment_url_to_postid($url) : 0;
        if ($attachmentId > 0) {
            return $attachmentId;
        }

        return 0;
    }

    public function deleteAttachment(int $attachmentId) : bool
    {
        $attachmentId = absint($attachmentId);
        if ($attachmentId <= 0) {
            return false;
        }

        if (! function_exists('wp_delete_attachment')) {
            require_once ABSPATH . 'wp-admin/includes/post.php';
        }

        $deleted = wp_delete_attachment($attachmentId, true);
        return ! empty($deleted);
    }
}
