<?php

namespace App\Services\Support;

use CodeIgniter\HTTP\Files\UploadedFile;

/**
 * Handles profile photos, agency logos, and cover images — all "publicly
 * viewable image" uploads, as opposed to ResumeUploadService's documents
 * (which are access-controlled and streamed through a controller). Images
 * are stored directly under public/uploads/ so they can be referenced by
 * a plain <img src> without a PHP round-trip on every page view.
 */
class ImageUploadService
{
    private const ALLOWED_EXTENSIONS = ['jpg', 'jpeg', 'png', 'webp'];
    private const ALLOWED_MIME_TYPES = ['image/jpeg', 'image/png', 'image/webp'];
    private const MAX_SIZE_KB = 3072; // 3MB

    /**
     * @param string $subfolder e.g. 'photos', 'logos', 'covers' — keeps
     *               the different image types organized on disk.
     */
    public function validateAndStore(UploadedFile $file, string $subfolder): array
    {
        if (! $file->isValid()) {
            throw new \RuntimeException('Upload failed: ' . $file->getErrorString());
        }

        $extension = strtolower($file->getClientExtension());
        if (! in_array($extension, self::ALLOWED_EXTENSIONS, true)) {
            throw new \InvalidArgumentException('Only JPG, PNG, and WEBP images are accepted.');
        }

        $mime = $file->getMimeType();
        if (! in_array($mime, self::ALLOWED_MIME_TYPES, true)) {
            throw new \InvalidArgumentException('File content does not match an accepted image format.');
        }

        if ($file->getSizeByUnit('kb') > self::MAX_SIZE_KB) {
            throw new \InvalidArgumentException('Image exceeds the 3MB size limit.');
        }

        $storageDir = FCPATH . 'uploads/' . $subfolder;
        if (! is_dir($storageDir)) {
            mkdir($storageDir, 0755, true);
        }

        // Random filename — never trust the original name for the stored
        // path (same rule as ResumeUploadService, see security plan §3).
        $randomName = bin2hex(random_bytes(16)) . '.' . $extension;
        $file->move($storageDir, $randomName);

        return [
            'relative_path' => 'uploads/' . $subfolder . '/' . $randomName,
        ];
    }

    /**
     * Deletes a previously-uploaded image (e.g. when replacing an old
     * photo with a new one) — best-effort, doesn't throw if the file is
     * already gone.
     */
    public function delete(?string $relativePath): void
    {
        if (! $relativePath) {
            return;
        }
        $path = FCPATH . ltrim($relativePath, '/');
        if (is_file($path)) {
            @unlink($path);
        }
    }
}
