<?php

namespace Console\Commands;

use App\Services\SettingsService;
use Exception;
use Openguru\OpenCartFramework\ImageTool\ImageFactory;
use Openguru\OpenCartFramework\ImageTool\ImageUtils;
use Openguru\OpenCartFramework\QueryBuilder\Builder;
use Openguru\OpenCartFramework\QueryBuilder\JoinClause;
use Openguru\OpenCartFramework\Support\Arr;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

class ImagesWarmupCacheCommand extends TeleCartCommand
{
    protected static $defaultName = 'images:warmup';
    protected static $defaultDescription = 'Прогрев кеша изображений товаров';

    private Builder $queryBuilder;
    private ImageFactory $image;
    private SettingsService $settings;
    private LoggerInterface $logger;

    public function __construct(
        Builder $queryBuilder,
        ImageFactory $image,
        SettingsService $settings,
        LoggerInterface $logger
    ) {
        parent::__construct();
        $this->queryBuilder = $queryBuilder;
        $this->image = $image;
        $this->settings = $settings;
        $this->logger = $logger;
    }

    protected function configure(): void
    {
        $this->addArgument(
            'product_id',
            InputArgument::OPTIONAL,
            'ID товара для прогрева кеша (если не указан, прогреваются все товары)'
        );
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $io = new SymfonyStyle($input, $output);
        $productId = $input->getArgument('product_id');

        $io->title('Прогрев кеша изображений товаров');

        // Получаем настройки
        $aspectRatio = $this->settings->get('app.image_aspect_ratio', '1:1');
        $cropAlgorithm = $this->settings->get('app.image_crop_algorithm', 'cover');
        [$imageWidth, $imageHeight] = ImageUtils::aspectRatioToSize($aspectRatio);
        $languageId = $this->settings->config()->getApp()->getLanguageId();

        $io->section('Настройки');
        $io->listing([
            "Соотношение сторон: {$aspectRatio}",
            "Алгоритм обрезки: {$cropAlgorithm}",
            "Размер изображения: {$imageWidth}x{$imageHeight}",
            "Размер миниатюры: 500x500",
            "Размер большого изображения: 1000x1000",
        ]);

        // Получаем список товаров
        $products = $this->getProducts($productId, $languageId);

        if (empty($products)) {
            $io->warning('Товары не найдены');
            return Command::SUCCESS;
        }

        $totalProducts = count($products);
        $io->section("Найдено товаров: {$totalProducts}");

        $stats = [
            'products' => 0,
            'main_images' => 0,
            'additional_images' => 0,
            'thumbnails' => 0,
            'large_images' => 0,
            'errors' => 0,
        ];

        $progressBar = $io->createProgressBar($totalProducts);
        $progressBar->setFormat(' %current%/%max% [%bar%] %percent:3s%% %message%');
        $progressBar->setMessage('Обработка товаров...');
        $progressBar->start();

        foreach ($products as $product) {
            $productId = $product['product_id'];
            $productName = $product['product_name'] ?? "ID: {$productId}";
            $progressBar->setMessage("Товар: {$productName}");

            try {
                // Прогреваем основное изображение товара
                if (!empty($product['product_image'])) {
                    try {
                        $this->image->make($product['product_image'])
                            ->crop($cropAlgorithm, $imageWidth, $imageHeight)
                            ->url();
                        $stats['main_images']++;
                    } catch (Exception $e) {
                        $this->logger->error("Ошибка при прогреве основного изображения товара {$productId}: " . $e->getMessage());
                        $stats['errors']++;
                    }
                }

                // Получаем дополнительные изображения товара
                $additionalImages = $this->getProductAdditionalImages($productId);
                $processedAdditional = 0;
                foreach ($additionalImages as $imagePath) {
                    if ($processedAdditional >= 2) {
                        break; // Ограничиваем до 2 дополнительных изображений, как в ProductsService
                    }
                    try {
                        $this->image->make($imagePath)
                            ->crop($cropAlgorithm, $imageWidth, $imageHeight)
                            ->url();
                        $stats['additional_images']++;
                        $processedAdditional++;
                    } catch (Exception $e) {
                        $this->logger->error("Ошибка при прогреве дополнительного изображения товара {$productId}: " . $e->getMessage());
                        $stats['errors']++;
                    }
                }

                // Прогреваем изображения для детальной страницы (миниатюры и большие)
                $allImages = [];
                if (!empty($product['product_image'])) {
                    $allImages[] = $product['product_image'];
                }
                $allImages = array_merge($allImages, $additionalImages);

                foreach ($allImages as $imagePath) {
                    try {
                        // Миниатюра
                        $this->image->make($imagePath)
                            ->contain(500, 500)
                            ->url();
                        $stats['thumbnails']++;

                        // Большое изображение
                        $this->image->make($imagePath)
                            ->resize(1000, 1000)
                            ->url();
                        $stats['large_images']++;
                    } catch (Exception $e) {
                        $this->logger->error("Ошибка при прогреве изображений для детальной страницы товара {$productId}: " . $e->getMessage());
                        $stats['errors']++;
                    }
                }

                $stats['products']++;
            } catch (Exception $e) {
                $this->logger->error("Ошибка при обработке товара {$productId}: " . $e->getMessage());
                $stats['errors']++;
            }

            $progressBar->advance();
        }

        $progressBar->setMessage('Завершено');
        $progressBar->finish();
        $io->newLine(2);

        // Выводим статистику
        $io->section('Статистика');
        $io->table(
            ['Метрика', 'Значение'],
            [
                ['Обработано товаров', $stats['products']],
                ['Основных изображений', $stats['main_images']],
                ['Дополнительных изображений', $stats['additional_images']],
                ['Миниатюр (500x500)', $stats['thumbnails']],
                ['Больших изображений (1000x1000)', $stats['large_images']],
                ['Ошибок', $stats['errors']],
            ]
        );

        if ($stats['errors'] > 0) {
            $io->warning("Обнаружено {$stats['errors']} ошибок. Проверьте логи для подробностей.");
        } else {
            $io->success('Кеш изображений успешно прогрет!');
        }

        return Command::SUCCESS;
    }

    /**
     * Получает список товаров для прогрева кеша
     */
    private function getProducts(?string $productId, int $languageId): array
    {
        $query = $this->queryBuilder->newQuery()
            ->select([
                'products.product_id' => 'product_id',
                'products.image' => 'product_image',
                'product_description.name' => 'product_name',
            ])
            ->from(db_table('product'), 'products')
            ->join(
                db_table('product_description') . ' AS product_description',
                function (JoinClause $join) use ($languageId) {
                    $join->on('products.product_id', '=', 'product_description.product_id')
                        ->where('product_description.language_id', '=', $languageId);
                }
            )
            ->where('products.status', '=', 1)
            ->whereRaw('products.date_available < NOW()');

        if ($productId !== null) {
            $query->where('products.product_id', '=', (int) $productId);
        }

        return $query->orderBy('products.product_id', 'ASC')->get();
    }

    /**
     * Получает дополнительные изображения товара
     */
    private function getProductAdditionalImages(int $productId): array
    {
        $images = $this->queryBuilder->newQuery()
            ->select(['products_images.image' => 'image'])
            ->from(db_table('product_image'), 'products_images')
            ->where('products_images.product_id', '=', $productId)
            ->orderBy('products_images.sort_order')
            ->get();

        return Arr::pluck($images, 'image');
    }
}

