<?php

namespace FleekDash\API\Performance;

use WP_Error;

// Load debug helpers
if (!function_exists('fleekdash_log_info')) {
    require_once FLEEKDASH_PLUGIN_DIR . 'includes/Core/debug-helpers.php';
}

/**
 * Thumbnail Regenerator
 *
 * Handles thumbnail regeneration operations
 * Extracted from PerformanceController for better organization
 *
 * @package FleekDash\API\Performance
 * @since 2.2.0
 */
class ThumbnailRegenerator
{
    private $wpdb;

    public function __construct()
    {
        global $wpdb;
        $this->wpdb = $wpdb;
    }

    /**
     * Process a batch of thumbnails
     *
     * @param int $offset Starting offset
     * @param int $batch_size Number of images to process
     * @return array Process result with 'processed' and 'errors' counts
     */
    public function processBatch($offset, $batch_size)
    {
        $this->ensureImageFunctionsLoaded();

        // Get batch of images
        $images = $this->wpdb->get_results($this->wpdb->prepare("
            SELECT ID, guid, post_title
            FROM {$this->wpdb->posts}
            WHERE post_type = 'attachment'
            AND post_mime_type LIKE 'image%%'
            ORDER BY ID DESC
            LIMIT %d OFFSET %d
        ", $batch_size, $offset));

        $this->debugLog("processBatch called: offset={$offset}, batch_size={$batch_size}, found_images=" . count($images));

        if (empty($images)) {
            $this->debugLog("No images found for batch. Returning empty result.");
            return ['processed' => 0, 'errors' => 0];
        }

        $processed = 0;
        $errors = 0;

        foreach ($images as $image) {
            $result = $this->processSingleImage($image);
            $processed += $result['processed'];
            $errors += $result['errors'];
            if (function_exists('set_time_limit')) {
                set_time_limit(30);
            }
        }

        $this->debugLog("processBatch result: processed={$processed}, errors={$errors} (total in batch: " . count($images) . ")");
        return ['processed' => $processed, 'errors' => $errors];
    }

    /**
     * Process a single image for thumbnail regeneration.
     *
     * @param object $image Image row with ID, guid, post_title
     * @return array{processed: int, errors: int}
     */
    private function processSingleImage($image)
    {
        $errorResult = ['processed' => 0, 'errors' => 1];
        $result = $errorResult;

        try {
            $file_path = \get_attached_file($image->ID);
            if ($file_path && file_exists($file_path)) {
                $result = $this->tryApplyMetadata($image, $file_path);
            } else {
                $this->debugLog("ERROR: File not found for image {$image->ID}: {$file_path}");
            }
        } catch (\Exception $e) {
            $this->debugLog("EXCEPTION: Error processing image {$image->ID}: " . $e->getMessage());
        }

        return $result;
    }

    /**
     * Generate metadata, update attachment, and return process result.
     *
     * @param object $image Image row with ID, guid, post_title
     * @param string $file_path Path to the image file
     * @return array{processed: int, errors: int}
     */
    private function tryApplyMetadata($image, $file_path)
    {
        $errorResult = ['processed' => 0, 'errors' => 1];
        $successResult = ['processed' => 1, 'errors' => 0];
        $result = $errorResult;

        $metadata = \wp_generate_attachment_metadata($image->ID, $file_path);
        if ($metadata instanceof \WP_Error) {
            $this->debugLog(sprintf(
                'ERROR: Failed to generate metadata for image %d: %s',
                $image->ID,
                $metadata->get_error_message()
            ));
        } elseif (empty($metadata)) {
            $this->debugLog("ERROR: Empty metadata for image {$image->ID}: {$image->post_title}");
        } else {
            $updated = \wp_update_attachment_metadata($image->ID, $metadata);
            $isSuccess = $updated !== false
                || \get_post_meta($image->ID, '_wp_attachment_metadata', true) === $metadata;
            if ($isSuccess) {
                $this->debugLog(
                    $updated !== false
                        ? "SUCCESS: Processed image {$image->ID}: {$image->post_title}"
                        : "INFO: Metadata unchanged for {$image->ID}, treating as success."
                );
                $result = $successResult;
            } else {
                $this->debugLog("ERROR: Failed to update metadata for image {$image->ID}: {$image->post_title}");
            }
        }

        return $result;
    }

    /**
     * Ensure required WordPress image functions are available
     *
     * @return void
     */
    private function ensureImageFunctionsLoaded()
    {
        if (
            !function_exists('wp_generate_attachment_metadata')
            || !function_exists('wp_read_image_metadata')
            || !function_exists('wp_get_image_editor')
        ) {
            require_once ABSPATH . 'wp-admin/includes/image.php';
        }

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

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

    /**
     * Get total image count
     *
     * @return int Total number of images
     */
    public function getImageCount()
    {
        $count = $this->wpdb->get_var("
            SELECT COUNT(*)
            FROM {$this->wpdb->posts}
            WHERE post_type = 'attachment'
            AND post_mime_type LIKE 'image%'
        ");

        return (int) $count;
    }

    /**
     * Get or create regeneration status
     *
     * @return array Status data
     */
    public function getRegenerationStatus()
    {
        $status = \get_transient('fleekdash_thumbnail_regeneration_status');

        if (!$status || !is_array($status)) {
            return ['status' => 'idle'];
        }

        return $status;
    }

    /**
     * Set regeneration status
     *
     * @param array $status Status data
     * @return bool Success status
     */
    public function setRegenerationStatus($status)
    {
        return \set_transient('fleekdash_thumbnail_regeneration_status', $status, HOUR_IN_SECONDS);
    }

    /**
     * Cancel ongoing regeneration
     *
     * @return bool Success status
     */
    public function cancelRegeneration()
    {
        $status = $this->getRegenerationStatus();

        if (($status['status'] ?? 'idle') === 'running') {
            $this->setRegenerationStatus([
                'status' => 'cancelled',
                'cancelled_at' => \current_time('mysql'),
                'processed' => $status['processed'] ?? 0,
                'total' => $status['total'] ?? 0,
            ]);
            return true;
        }

        return false;
    }

    /**
     * Debug log helper
     *
     * @param string $message Log message
     */
    private function debugLog($message)
    {
        fleekdash_log_info('[FleekDash Performance] ' . $message);
    }
}
