<?php

namespace App\Services\Concerns;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

trait RegistersMedia
{
    private function registerMediaFromBase64(
        Model $model,
        string $base64Data,
        string $collectionName,
        string $folder,
    ): void {
        $dataUrl = $base64Data;
        $mime = 'image/jpeg';

        if (preg_match('/^data:(.+?);base64,/', $dataUrl, $matches)) {
            $mime = $matches[1];
            $dataUrl = preg_replace('/^data:.+?;base64,/', '', $dataUrl);
        }

        $binary = base64_decode($dataUrl, true);

        if ($binary === false) {
            return;
        }

        $extension = match ($mime) {
            'image/png' => 'png',
            'image/webp' => 'webp',
            'image/gif' => 'gif',
            default => 'jpg',
        };

        $date = now()->format('Y/m/d');
        $uuid = Str::uuid();
        $key = "{$folder}/{$date}/{$uuid}/photo.{$extension}";

        Storage::disk('s3')->put($key, $binary, [
            'ContentType' => $mime,
            'ACL' => 'public-read',
        ]);

        $this->registerMedia(
            model: $model,
            s3Key: $key,
            collectionName: $collectionName,
            mimeType: $mime,
            fileSize: strlen($binary),
            orderColumn: 1,
        );
    }

    private function registerMedia(
        Model $model,
        string $s3Key,
        string $collectionName,
        array $generatedConversions = [],
        ?int $fileSize = null,
        ?string $mimeType = null,
        ?int $orderColumn = null,
        ?string $name = null,
    ): void {
        $defaultName = pathinfo($s3Key, PATHINFO_FILENAME);

        Media::create([
            'model_type' => $model->getMorphClass(),
            'model_id' => $model->id,
            'uuid' => Str::uuid(),
            'collection_name' => $collectionName,
            'name' => $name ?? $defaultName,
            'file_name' => $s3Key,
            'mime_type' => $mimeType ?? 'image/jpeg',
            'disk' => 's3',
            'conversions_disk' => 's3',
            'size' => $fileSize ?? 0,
            'manipulations' => [],
            'custom_properties' => [],
            'generated_conversions' => $generatedConversions,
            'responsive_images' => [],
            'order_column' => $orderColumn ?? 1,
        ]);
    }

    private function syncPhoto(Model $model, array $data, string $collectionName = 'photos'): void
    {
        if (! array_key_exists('photo_key', $data)) {
            return;
        }

        $currentKey = $model->getFirstMedia($collectionName)?->file_name;

        if ($data['photo_key'] === $currentKey) {
            return;
        }

        $model->clearMediaCollection($collectionName);

        if (! empty($data['photo_key'])) {
            $this->registerMedia(
                model: $model,
                s3Key: $data['photo_key'],
                collectionName: $collectionName,
                orderColumn: 1,
            );
        }
    }

    private function syncReceipt(Model $model, ?string $newKey, string $collectionName = 'receipts', string $cachePrefix = 'receipt', ?int $fileSize = null, ?string $fileMimeType = null): void
    {
        $currentMedia = $model->getFirstMedia($collectionName);
        $currentKey = $currentMedia?->file_name;

        if ($currentMedia && ! str_contains($currentKey, '/')) {
            $currentKey = $currentMedia->getPath();
        }

        if ($newKey === $currentKey) {
            return;
        }

        if ($currentMedia) {
            Cache::forget("{$cachePrefix}_{$currentMedia->id}");
        }

        $model->clearMediaCollection($collectionName);

        if (! empty($newKey)) {
            $this->registerMedia(
                model: $model,
                s3Key: $newKey,
                collectionName: $collectionName,
                generatedConversions: ['thumb' => true],
                fileSize: $fileSize,
                mimeType: $fileMimeType,
            );
        }
    }
}
