<?php

namespace FleekDash\API\Performance;

/**
 * Image Stats Calculator
 *
 * Handles calculation of image statistics and thumbnail coverage
 * Extracted from PerformanceController for better organization
 *
 * @package FleekDash\API\Performance
 * @since 2.2.0
 */
class ImageStatsCalculator
{
    private $wpdb;

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

    /**
     * Calculate image statistics
     *
     * @param bool $exact Whether to calculate exact stats (slower) or estimate (faster)
     * @param int $total_images Total image count (optional, will query if not provided)
     * @return array Statistics array
     */
    public function calculateStats($exact = false, $total_images = null)
    {
        if ($total_images === null) {
            $total_images = $this->getImageCount();
        }

        if ($exact) {
            return $this->calculateExactStats($total_images);
        }

        return $this->calculateEstimatedStats($total_images);
    }

    /**
     * Calculate exact statistics (slower, iterates all images)
     *
     * @param int $total_images Total image count
     * @return array Exact statistics
     */
    private function calculateExactStats($total_images)
    {
        $images = $this->wpdb->get_results("
            SELECT ID
            FROM {$this->wpdb->posts}
            WHERE post_type = 'attachment'
            AND post_mime_type LIKE 'image%'
            ORDER BY ID DESC
        ");

        $with = 0;
        $without = 0;
        $total_size = 0;

        foreach ($images as $image) {
            $metadata = \wp_get_attachment_metadata($image->ID);
            $tally = $this->classifyImageFromMetadata($metadata);
            $with += $tally['with'];
            $without += $tally['without'];
            $total_size += $tally['size'];
        }

        return [
            'total_images' => (int) $total_images,
            'images_with_thumbnails' => (int) $with,
            'images_without_thumbnails' => (int) $without,
            'completion_percentage' => $total_images > 0 ? round(($with / $total_images) * 100, 1) : 0,
            'estimated_total_size' => $this->formatBytes($total_size),
            'thumbnail_sizes' => [
                'fleekdash-thumbnail' => '48x48px',
                'fleekdash-preview' => '397x224px'
            ],
            'is_exact' => true,
        ];
    }

    /**
     * Calculate estimated statistics (faster, uses sampling)
     *
     * @param int $total_images Total image count
     * @return array Estimated statistics
     */
    private function calculateEstimatedStats($total_images)
    {
        $images_with_thumbnails = 0;
        $images_without_thumbnails = 0;
        $total_size = 0;

        // Get sample of images (random for better accuracy)
        $sample_size = min(500, $total_images);
        $sample_images = $this->wpdb->get_results($this->wpdb->prepare("
            SELECT ID
            FROM {$this->wpdb->posts}
            WHERE post_type = 'attachment'
            AND post_mime_type LIKE 'image%'
            ORDER BY RAND()
            LIMIT %d
        ", $sample_size));

        foreach ($sample_images as $image) {
            $metadata = \wp_get_attachment_metadata($image->ID);
            $tally = $this->classifyImageFromMetadata($metadata);
            $images_with_thumbnails += $tally['with'];
            $images_without_thumbnails += $tally['without'];
            $total_size += $tally['size'];
        }

        // Extrapolate to total
        $actual_sample_size = count($sample_images);
        
        if ($actual_sample_size > 0) {
            $ratio_with_thumbnails = $images_with_thumbnails / $actual_sample_size;
            $ratio_without_thumbnails = $images_without_thumbnails / $actual_sample_size;
            $estimated_with_thumbnails = round($total_images * $ratio_with_thumbnails);
            $estimated_without_thumbnails = round($total_images * $ratio_without_thumbnails);
            // Validate sample: with + without must equal sample size (each image is either)
            if ($images_with_thumbnails + $images_without_thumbnails !== $actual_sample_size) {
                $estimated_without_thumbnails = max(0, $total_images - $estimated_with_thumbnails);
            }
        } else {
            $estimated_with_thumbnails = 0;
            $estimated_without_thumbnails = $total_images;
        }

        return [
            'total_images' => $total_images,
            'images_with_thumbnails' => $estimated_with_thumbnails,
            'images_without_thumbnails' => $estimated_without_thumbnails,
            'completion_percentage' => $total_images > 0 ? round(($estimated_with_thumbnails / $total_images) * 100, 1) : 0,
            'estimated_total_size' => $this->formatBytes($total_size * ($total_images / max($actual_sample_size, 1))),
            'thumbnail_sizes' => [
                'fleekdash-thumbnail' => '48x48px',
                'fleekdash-preview' => '397x224px'
            ],
            'is_exact' => false,
        ];
    }

    /**
     * Classify image metadata for thumbnail stats (reduces cognitive complexity)
     *
     * @param array|false $metadata Attachment metadata
     * @return array{with: int, without: int, size: int}
     */
    private function classifyImageFromMetadata($metadata)
    {
        $base = ['with' => 0, 'without' => 1, 'size' => 0];
        if (!$metadata || !isset($metadata['sizes'])) {
            return $base;
        }
        $has_sizes = isset($metadata['sizes']['fleekdash-thumbnail'])
            || isset($metadata['sizes']['fleekdash-preview']);
        $base['with'] = $has_sizes ? 1 : 0;
        $base['without'] = $has_sizes ? 0 : 1;
        $base['size'] = (int) ($metadata['filesize'] ?? 0);
        return $base;
    }

    /**
     * Get total image count
     *
     * @return int Image count
     */
    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;
    }

    /**
     * Format bytes to human-readable format
     *
     * @param int $bytes Bytes to format
     * @return string Formatted string
     */
    private function formatBytes($bytes)
    {
        $bytes = (int) $bytes;
        $result = $bytes . ' B';
        if ($bytes >= 1073741824) {
            $result = round($bytes / 1073741824, 2) . ' GB';
        } elseif ($bytes >= 1048576) {
            $result = round($bytes / 1048576, 2) . ' MB';
        } elseif ($bytes >= 1024) {
            $result = round($bytes / 1024, 2) . ' KB';
        }
        return $result;
    }
}

