<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Intervention\Image\Facades\Image;

class OptimizeThemeImagesCommand extends Command
{
    protected $signature = 'images:optimize-theme
                            {--max-kb=200 : Target max file size in KB for each WebP output}
                            {--dry-run : List files without writing}';

    protected $description = 'Generate optimized WebP variants for theme hero/marketing images';

    /** @var int[] */
    protected $widths = [480, 768, 1200];

    /** @var string[] */
    protected $directories = [
        'assets/default/img/montessori-premium',
        'assets/imt/catalog/heroes/photo',
        'assets/default/img/home',
    ];

    public function handle(): int
    {
        if (!extension_loaded('gd') && !extension_loaded('imagick')) {
            $this->error('GD or Imagick extension required for image processing.');

            return 1;
        }

        $maxBytes = max(50, (int) $this->option('max-kb')) * 1024;
        $dryRun = (bool) $this->option('dry-run');
        $processed = 0;
        $savedBytes = 0;

        foreach ($this->directories as $relDir) {
            $absDir = public_path($relDir);
            if (!is_dir($absDir)) {
                $this->warn("Skipping missing directory: {$relDir}");

                continue;
            }

            $files = glob($absDir.DIRECTORY_SEPARATOR.'*.{jpg,jpeg,png,JPG,JPEG,PNG}', GLOB_BRACE) ?: [];

            foreach ($files as $filePath) {
                $size = filesize($filePath);
                if ($size < 50 * 1024) {
                    continue;
                }

                $baseName = pathinfo($filePath, PATHINFO_FILENAME);
                $this->line(sprintf('Processing %s (%.1f KB)', str_replace(public_path(), '', $filePath), $size / 1024));

                if ($dryRun) {
                    $processed++;

                    continue;
                }

                try {
                    $img = Image::make($filePath);
                    $origW = $img->width();

                    foreach ($this->widths as $targetW) {
                        if ($origW < $targetW && $targetW !== 1200) {
                            continue;
                        }

                        $outW = min($targetW, $origW);
                        $variant = Image::make($filePath);
                        if ($outW < $origW) {
                            $variant->resize($outW, null, function ($constraint) {
                                $constraint->aspectRatio();
                                $constraint->upsize();
                            });
                        }

                        $suffix = ($targetW === 1200 || $outW === $origW) ? '' : '-'.$outW.'w';
                        $webpPath = dirname($filePath).DIRECTORY_SEPARATOR.$baseName.$suffix.'.webp';

                        $this->writeWebpUnderBudget($variant, $webpPath, $maxBytes);
                        $savedBytes += max(0, $size - (is_file($webpPath) ? filesize($webpPath) : 0));
                    }

                    $processed++;
                } catch (\Throwable $e) {
                    $this->error('Failed '.$filePath.': '.$e->getMessage());
                }
            }
        }

        $this->info("Done. Processed {$processed} source image(s). Estimated savings vs originals: ".round($savedBytes / 1024).' KB');

        return 0;
    }

    protected function writeWebpUnderBudget($image, string $path, int $maxBytes): void
    {
        $quality = 85;

        while ($quality >= 55) {
            $image->encode('webp', $quality)->save($path);
            if (filesize($path) <= $maxBytes) {
                $this->info('  → '.basename($path).' ('.round(filesize($path) / 1024, 1).' KB, q='.$quality.')');

                return;
            }
            $quality -= 5;
        }

        $this->warn('  → '.basename($path).' still '.round(filesize($path) / 1024, 1).' KB at min quality');
    }
}
