<?php

/**
 * Трейт для обработки загрузок
 * Общие методы для обработки загрузок файлов
 *
 * @package Flowaxy\Support\Traits
 * @version 1.0.0 Alpha prerelease
 */

declare(strict_types=1);

namespace Flowaxy\Support\Traits;

use Flowaxy\Support\Services\FileUploadService;
use Flowaxy\Support\Services\ArchiveExtractionService;
use Flowaxy\Support\Helpers\ResourceCleanupHelper;
use Flowaxy\Support\Facades\Log;
use Exception;
use Throwable;

trait UploadHandlerTrait
{
    /**
     * Получение экземпляра FileUploadService
     *
     * @return FileUploadService
     */
    protected function getUploadService(): FileUploadService
    {
        static $service = null;
        if ($service === null) {
            $service = new FileUploadService();
        }
        return $service;
    }

    /**
     * Получение экземпляра ArchiveExtractionService
     *
     * @return ArchiveExtractionService
     */
    protected function getArchiveService(): ArchiveExtractionService
    {
        static $service = null;
        if ($service === null) {
            $service = new ArchiveExtractionService();
        }
        return $service;
    }

    /**
     * Обработка загрузки файла
     *
     * @param array<string, mixed> $file Файл из $_FILES
     * @param array<string, mixed> $options Опции загрузки
     * @return array{success: bool, file?: string, path?: string, error?: string}
     */
    protected function handleUpload(array $file, array $options = []): array
    {
        try {
            $uploadService = $this->getUploadService();
            return $uploadService->upload($file, $options);
        } catch (Throwable $e) {
            try {
                Log::Error('Помилка завантаження файлу', [
                    'error' => $e->getMessage(),
                    'exception' => $e,
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
            return [
                'success' => false,
                'error' => $e->getMessage(),
            ];
        }
    }

    /**
     * Валидация загрузки
     *
     * @param array<string, mixed> $file Файл из $_FILES
     * @param array<string, mixed> $options Опции валидации
     * @return array{valid: bool, error?: string}
     */
    protected function validateUpload(array $file, array $options = []): array
    {
        try {
            $uploadService = $this->getUploadService();
            return $uploadService->validate($file, $options);
        } catch (Throwable $e) {
            return [
                'valid' => false,
                'error' => $e->getMessage(),
            ];
        }
    }

    /**
     * Обработка загрузки и извлечения архива
     *
     * @param array<string, mixed> $file Файл из $_FILES
     * @param string $destinationPath Путь назначения
     * @param string $configFileName Имя конфигурационного файла
     * @param array<string, mixed> $uploadOptions Опции загрузки
     * @return array{success: bool, slug?: string, extracted?: int, error?: string}
     */
    protected function processUpload(array $file, string $destinationPath, string $configFileName = 'Plugin.php', array $uploadOptions = []): array
    {
        $uploadedFile = null;
        $zip = null;

        try {
            // Загружаем файл
            $uploadResult = $this->handleUpload($file, $uploadOptions);
            if (!$uploadResult['success']) {
                return $uploadResult;
            }

            $uploadedFile = $uploadResult['file'] ?? null;
            if (!$uploadedFile || !file_exists($uploadedFile)) {
                return [
                    'success' => false,
                    'error' => 'Файл не знайдено після завантаження',
                ];
            }

            // Извлекаем архив
            $archiveService = $this->getArchiveService();
            $extractionResult = $archiveService->extractZip(
                $uploadedFile,
                $destinationPath,
                $configFileName,
                $uploadOptions['overwrite'] ?? false
            );

            // Очищаем загруженный файл
            ResourceCleanupHelper::cleanupTempFiles($uploadedFile);

            return $extractionResult;
        } catch (Throwable $e) {
            // Очищаем ресурсы при ошибке
            ResourceCleanupHelper::cleanupOnError($zip, $uploadedFile, $destinationPath);
            try {
                Log::Error('Помилка обробки завантаження', [
                    'error' => $e->getMessage(),
                    'exception' => $e,
                ]);
            } catch (Throwable $logError) {
                // Ignore logging errors
            }
            return [
                'success' => false,
                'error' => $e->getMessage(),
            ];
        }
    }
}
