<?php
/**
 * Auto Processor — Handles automatic image processing on upload
 *
 * Resize runs synchronously (fast, before user sees result).
 * WebP + AI run asynchronously via wp_schedule_single_event.
 *
 * @package PackshotPhotoAI
 */

namespace PackshotPhotoAI\Core;
 
use PackshotPhotoAI\Core\Logger;
 
defined('ABSPATH') || exit;

class UploadCoordinator {

    private static array $pending = [];

    public static function register_hooks(): void {
        add_action('add_attachment', [static::class, 'queue_attachment'], 20);
        add_action('shutdown', [static::class, 'process_queue']);
        add_action('packshotphoto_async_chain', [static::class, 'process_chained_queue']);
        add_action('packshotphoto_cleanup_trash', [static::class, 'cleanup_old_backups']);
        add_action('packshotphoto_keep_alive_event', ['\PackshotPhotoAI\Core\CreditManager', 'keep_alive_ping']);
        
        // Schedule daily cleanup if not already scheduled
        if (!wp_next_scheduled('packshotphoto_cleanup_trash')) {
            wp_schedule_event(time(), 'daily', 'packshotphoto_cleanup_trash');
        }
    }

    public static function queue_attachment(int $attachment_id): void {
        $mime_type = get_post_mime_type($attachment_id);
        if (!$mime_type || strpos($mime_type, 'image/') !== 0) {
            return;
        }

        $opts = [];

        // 1. Prioritize live REQUEST parameters (Plupload multipart or browser upload)
        if (isset($_REQUEST['packshotphoto_session_auto_ai']) || isset($_REQUEST['packshotphoto_session_auto_eu_ai']) || isset($_REQUEST['packshotphoto_upload_context'])) {
            $opts = [
                'auto_ai'      => sanitize_text_field(wp_unslash($_REQUEST['packshotphoto_session_auto_ai']     ?? '0')),
                'auto_eu_ai'   => sanitize_text_field(wp_unslash($_REQUEST['packshotphoto_session_auto_eu_ai']  ?? '0')),
                'auto_webp'    => sanitize_text_field(wp_unslash($_REQUEST['packshotphoto_session_auto_webp']   ?? '0')),
                'auto_avif'    => sanitize_text_field(wp_unslash($_REQUEST['packshotphoto_session_auto_avif']   ?? '0')),
                'auto_resize'  => sanitize_text_field(wp_unslash($_REQUEST['packshotphoto_session_auto_resize'] ?? '0')),
                'resize_width' => absint(wp_unslash($_REQUEST['packshotphoto_session_resize_width']              ?? 0)),
                'context'      => sanitize_textarea_field(wp_unslash($_REQUEST['packshotphoto_upload_context']  ?? '')),
            ];
            Logger::info('UploadCoordinator: saved live REQUEST session opts for #' . $attachment_id, $opts);
        } else {
            // 2. Fallback to transient options saved via AJAX "Apply Settings"
            $user_id      = get_current_user_id();
            $session_opts = $user_id ? get_transient('packshotphoto_upload_session_opts_' . $user_id) : false;
            if (is_array($session_opts)) {
                $opts = $session_opts;
                Logger::info('UploadCoordinator: saved transient session opts for #' . $attachment_id, $opts);
            }
        }

        if (empty($opts)) {
            $opts = [
                'auto_ai'      => '1' === get_option('packshotphoto_auto_process', '1') ? '1' : '0',
                'auto_eu_ai'   => '1' === get_option('packshotphoto_auto_eu_ai', '0') ? '1' : '0',
                'auto_webp'    => '1' === get_option('packshotphoto_auto_webp', '1') ? '1' : '0',
                'auto_avif'    => '1' === get_option('packshotphoto_auto_avif', '0') ? '1' : '0',
                'auto_resize'  => (get_option('packshotphoto_max_image_size', 0) > 0) ? '1' : '0',
                'resize_width' => (int) get_option('packshotphoto_max_image_size', 0),
                'context'      => '',
            ];
            Logger::info('UploadCoordinator: saved default global opts for #' . $attachment_id, $opts);
        }

        $opts['queued_at'] = time();
        update_post_meta($attachment_id, '_pmm_upload_opts', $opts);

        // Execute synchronous tasks (Resize & EU AI Stamping) immediately while the file is handled
        self::process_attachment($attachment_id);

        self::$pending[] = $attachment_id;
    }

    public static function process_queue(): void {
        if (empty(self::$pending)) {
            return;
        }

        foreach (self::$pending as $post_id) {
            // Already processed synchronously in queue_attachment, but verify
            self::process_attachment($post_id);
        }
        self::$pending = [];

        // Schedule chain worker immediately
        if (!wp_next_scheduled('packshotphoto_async_chain')) {
            wp_schedule_single_event(time() + 1, 'packshotphoto_async_chain');
            spawn_cron(time());
            Logger::info('UploadCoordinator: Spawning chain execution worker');
        }
    }

    private static function process_attachment(int $post_id): void {
        $file_path = get_attached_file($post_id);
        $mime_type = get_post_mime_type($post_id);

        if (!$file_path || !file_exists($file_path) || !$mime_type) {
            return;
        }

        if (strpos($mime_type, 'image/') !== 0) {
            return;
        }

        Logger::info('UploadCoordinator: sync processing #' . $post_id . ' (' . $mime_type . ')');

        // SYNC: Resize — use session override if set, else fall back to global option
        $opts     = get_post_meta($post_id, '_pmm_upload_opts', true);
        $use_opts = is_array($opts);

        $do_resize  = $use_opts ? ($opts['auto_resize'] === '1') : (get_option('packshotphoto_max_image_size', 0) > 0);
        $max_size   = $use_opts ? (int) $opts['resize_width'] : (int) get_option('packshotphoto_max_image_size', 0);

        if ($do_resize && $max_size > 0) {
            $image_data = @getimagesize($file_path);
            if ($image_data) {
                $longest = max($image_data[0], $image_data[1]);
                if ($longest > $max_size) {
                    $processor = new ImageProcessor();
                    $processor->resize($post_id, $max_size);
                    Logger::info('UploadCoordinator: resize done for #' . $post_id);
                }
            }
        }

        // SYNC: EU AI Act Stamping (Instant on upload!)
        $do_eu_ai = $use_opts ? (($opts['auto_eu_ai'] ?? '0') === '1') : ('1' === get_option('packshotphoto_auto_eu_ai', '0'));
        if ($do_eu_ai) {
            $labeller = new \PackshotPhotoAI\Core\EuAiActLabeller();
            $res = $labeller->apply_label($post_id);
            Logger::info('UploadCoordinator: sync EU AI stamp for #' . $post_id, $res);
        }
    }

    /**
     * Executes the background chain queue. Processes exactly ONE pending attachment per execution cycle.
     */
    public static function process_chained_queue(): void {
        // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Discouraged
        set_time_limit(180);

        // Find the next attachment marked for auto-processing
        $query = new \WP_Query([
            'post_type'      => 'attachment',
            'post_status'    => 'inherit',
            'meta_key'       => '_pmm_upload_opts',
            'posts_per_page' => 1,
            'fields'         => 'ids',
            'orderby'        => 'ID',
            'order'          => 'ASC'
        ]);

        if (empty($query->posts)) {
            Logger::info('UploadCoordinator: Chain processing complete, no pending items');
            return;
        }

        $post_id = $query->posts[0];
        
        // Prevent concurrent duplicates
        $opts = get_post_meta($post_id, '_pmm_upload_opts', true);
        if (is_array($opts) && !empty($opts['is_processing'])) {
            $last_ping = (int) ($opts['queued_at'] ?? 0);
            if (time() - $last_ping < 120) {
                // Currently processing by another process, check back in 15 seconds
                if (!wp_next_scheduled('packshotphoto_async_chain')) {
                    wp_schedule_single_event(time() + 15, 'packshotphoto_async_chain');
                }
                return;
            }
        }

        // Lock processing
        if (is_array($opts)) {
            $opts['is_processing'] = true;
            $opts['queued_at'] = time();
            update_post_meta($post_id, '_pmm_upload_opts', $opts);
        }

        // Process this item
        self::async_process_attachment($post_id);

        // Check if there are more pending items and schedule the next chain step immediately
        $next_query = new \WP_Query([
            'post_type'      => 'attachment',
            'post_status'    => 'inherit',
            'meta_key'       => '_pmm_upload_opts',
            'posts_per_page' => 1,
            'fields'         => 'ids'
        ]);

        if (!empty($next_query->posts)) {
            wp_schedule_single_event(time(), 'packshotphoto_async_chain');
            spawn_cron(time());
            Logger::info('UploadCoordinator: Chained next background task');
        }
    }

    private static function async_process_attachment(int $post_id): void {
        try {
            $file_path = get_attached_file($post_id);
            $mime_type = get_post_mime_type($post_id);

            if (!$file_path || !file_exists($file_path) || !$mime_type) {
                Logger::warning('UploadCoordinator: async skipped, file not found #' . $post_id);
                return;
            }

            Logger::info('UploadCoordinator: async processing #' . $post_id);

            // Refresh file_path after possible resize
            $file_path = get_attached_file($post_id);

            // 1. Auto-AI (if enabled) — use session overrides if saved
            $opts     = get_post_meta($post_id, '_pmm_upload_opts', true);
            $use_opts = is_array($opts);

            $do_ai     = $use_opts ? ($opts['auto_ai']   === '1') : ('1' === get_option('packshotphoto_auto_process', '1'));
            $do_eu_ai  = $use_opts ? (($opts['auto_eu_ai'] ?? '0') === '1') : ('1' === get_option('packshotphoto_auto_eu_ai', '0'));
            $do_avif   = $use_opts ? ($opts['auto_avif'] === '1') : ('1' === get_option('packshotphoto_auto_avif', '0'));
            $do_webp   = $use_opts ? ($opts['auto_webp'] === '1') : ('1' === get_option('packshotphoto_auto_webp', '1'));
            $upload_context = $use_opts ? ($opts['context'] ?? '') : '';

            if ($do_eu_ai) {
                $labeller = new \PackshotPhotoAI\Core\EuAiActLabeller();
                $labeller->apply_label($post_id);
            }

            if ($do_ai) {
                if (CreditManager::has_credits()) {
                    $router = new \PackshotPhotoAI\API\ApiRouter();
                    $settings = get_option('packshotphoto_settings', []);
                    $language = $settings['language'] ?? '';
                    $result = $router->generate_seo_description($file_path, $mime_type, $post_id, $language, $upload_context);

                    if ($result['success']) {
                        CreditManager::deduct_credit(1);
                        $data = $result['data'];

                        $existing_post = get_post($post_id);
                        $new_backup = [
                            'alt'         => get_post_meta($post_id, '_wp_attachment_image_alt', true) ?: '',
                            'caption'     => $existing_post ? ($existing_post->post_excerpt ?: '') : '',
                            'description' => $existing_post ? ($existing_post->post_content ?: '') : '',
                            'timestamp'   => time(),
                        ];
                        
                        $history = get_post_meta($post_id, '_pmm_ai_backup', true);
                        if (!is_array($history)) {
                            $history = [];
                        }
                        $history[] = $new_backup;
                        if (count($history) > 10) {
                            $history = array_slice($history, -10);
                        }
                        update_post_meta($post_id, '_pmm_ai_backup', $history);

                        if (!empty($data['alt'])) {
                            update_post_meta($post_id, '_wp_attachment_image_alt', sanitize_text_field($data['alt']));
                        }

                        $update_args = ['ID' => $post_id];
                        if (!empty($data['caption'])) {
                            $update_args['post_excerpt'] = wp_kses_post($data['caption']);
                        }
                        if (!empty($data['desc'])) {
                            $update_args['post_content'] = wp_kses_post($data['desc']);
                        }
                        if (!empty($data['slug']) && '1' === get_option('packshotphoto_auto_rename', '1')) {
                            $update_args['post_name'] = sanitize_title($data['slug']);
                            $current_filename = pathinfo($file_path, PATHINFO_FILENAME);
                            $new_slug_clean = sanitize_title($data['slug']);
                            if ($current_filename !== $new_slug_clean) {
                                $renamer = new FileRenamer();
                                $ext = pathinfo($file_path, PATHINFO_EXTENSION);
                                $renamer->rename_file($post_id, $new_slug_clean . '.' . $ext);
                                $file_path = get_attached_file($post_id);
                            }
                        }
                        if (count($update_args) > 1) {
                            wp_update_post($update_args);
                        }

                        // Save opener to recent memory (prevents repetitive description openings)
                        if (!empty($data['desc'])) {
                            $openers   = (array) get_option('packshotphoto_recent_openers', []);
                            $openers[] = implode(' ', array_slice(explode(' ', $data['desc']), 0, 8));
                            update_option('packshotphoto_recent_openers', array_slice($openers, -30), false);
                        }

                        Logger::info('UploadCoordinator: async AI done for #' . $post_id);
                    } else {
                        Logger::error('UploadCoordinator async AI error: ' . ($result['message'] ?? 'unknown'));
                    }
                }
            }

            // 2. Auto-AVIF (if enabled, prioritize over WebP)
            if ($do_avif) {
                $current_mime = get_post_mime_type($post_id);
                if ($current_mime && 'image/avif' !== $current_mime) {
                    $avif = new AvifConverter();
                    $result = $avif->convert($post_id, true);
                    if ($result['success']) {
                        Logger::info('UploadCoordinator: async AVIF done for #' . $post_id);
                    } else {
                        Logger::error('UploadCoordinator async AVIF error: ' . ($result['message'] ?? 'unknown'));
                    }
                }
            }

            // 3. Auto-WebP (if enabled)
            if ($do_webp) {
                $current_mime = get_post_mime_type($post_id);
                if ($current_mime && 'image/webp' !== $current_mime) {
                    $webp = new WebPConverter();
                    $result = $webp->convert($post_id, true);
                    if ($result['success']) {
                        Logger::info('UploadCoordinator: async WebP done for #' . $post_id);
                    } else {
                        Logger::error('UploadCoordinator async WebP error: ' . ($result['message'] ?? 'unknown'));
                    }
                }
            }
        } catch (\Throwable $e) {
            Logger::error('UploadCoordinator: async_process_attachment exception for #' . $post_id . ': ' . $e->getMessage());
        } finally {
            // Clean up session opts after processing (guaranteed execution)
            delete_post_meta($post_id, '_pmm_upload_opts');
            Logger::info('UploadCoordinator: async processing complete for #' . $post_id);
        }
    }

    /**
     * Clean up old backup files from packshotphoto-trash folder
     * Removes files older than 30 days
     */
    public static function cleanup_old_backups(): void {
        $upload_dir = wp_upload_dir();
        $trash_dir = $upload_dir['basedir'] . '/packshotphoto-trash';
        
        if (!is_dir($trash_dir)) {
            return;
        }
        
        $cutoff_time = time() - (30 * DAY_IN_SECONDS);
        $files = glob($trash_dir . '/*');
        
        if (!$files) {
            return;
        }
        
        global $wp_filesystem;
        if (empty($wp_filesystem)) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
            WP_Filesystem();
        }

        $deleted = 0;
        if (!empty($wp_filesystem)) {
            foreach ($files as $file) {
                if (is_file($file) && filemtime($file) < $cutoff_time) {
                    if ($wp_filesystem->delete($file)) {
                        $deleted++;
                    }
                }
            }
            
            // Remove trash dir if empty
            $remaining_files = glob($trash_dir . '/*');
            if (empty($remaining_files)) {
                $wp_filesystem->delete($trash_dir, true);
            }
        }
        
        if ($deleted > 0) {
            Logger::info('Trash cleanup: removed ' . $deleted . ' old backup files');
        }
    }
}
