<?php

declare(strict_types=1);

namespace App\Services;

use App\Models\Group;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class GroupMediaService
{
    private const ALLOWED_MIME_TYPES = [
        'image/jpeg',
        'image/png',
        'image/webp',
    ];

    public function storeUploadedImage(Group $group, UploadedFile $file, string $variant): string
    {
        return $this->storeUploadedEntityImage($group, $file, $variant === 'banner' ? 'banner' : 'avatar');
    }

    public function storeUploadedEntityImage(Group $group, UploadedFile $file, string $section): string
    {
        $mime = strtolower((string) ($file->getMimeType() ?: ''));
        $extension = $this->safeExtension($file, $mime);
        $path = sprintf(
            'groups/%d/%s/%s.%s',
            (int) $group->id,
            trim($section) !== '' ? trim($section) : 'media',
            (string) Str::uuid(),
            $extension,
        );

        $stream = fopen((string) ($file->getRealPath() ?: $file->getPathname()), 'rb');
        if ($stream === false) {
            throw new \RuntimeException('Unable to open uploaded group image.');
        }

        try {
            $written = Storage::disk($this->diskName())->put($path, $stream, [
                'visibility' => 'public',
                'CacheControl' => 'public, max-age=31536000, immutable',
                'ContentType' => $mime !== '' ? $mime : $this->mimeTypeForExtension($extension),
            ]);
        } finally {
            fclose($stream);
        }

        if ($written !== true) {
            throw new \RuntimeException('Unable to store uploaded group image.');
        }

        return $path;
    }

    public function deleteIfManaged(?string $path): void
    {
        $trimmed = trim((string) $path);

        if ($trimmed === '' || str_starts_with($trimmed, 'http://') || str_starts_with($trimmed, 'https://')) {
            return;
        }

        if (! str_starts_with($trimmed, 'groups/')) {
            return;
        }

        Storage::disk($this->diskName())->delete($trimmed);
    }

    private function diskName(): string
    {
        return (string) config('uploads.object_storage.disk', 's3');
    }

    private function safeExtension(UploadedFile $file, string $mime): string
    {
        $extension = strtolower((string) $file->getClientOriginalExtension());

        if (! in_array($mime, self::ALLOWED_MIME_TYPES, true)) {
            throw new \RuntimeException('Unsupported group image upload type.');
        }

        return match ($extension) {
            'jpg', 'jpeg' => 'jpg',
            'png' => 'png',
            default => 'webp',
        };
    }

    private function mimeTypeForExtension(string $extension): string
    {
        return match ($extension) {
            'jpg' => 'image/jpeg',
            'png' => 'image/png',
            default => 'image/webp',
        };
    }
}