<?php

declare(strict_types=1);

use FluxCms\Core\Models\CmsMedia;
use FluxCms\Core\Services\MediaConversionService;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

beforeEach(function () {
    Storage::fake('public');
});

test('CmsMedia model can be created', function () {
    $media = CmsMedia::create([
        'filename' => 'test-image.jpg',
        'disk' => 'public',
        'path' => 'cms/media/originals/test-image.jpg',
        'type' => 'image',
        'mime_type' => 'image/jpeg',
        'file_size' => 102400,
        'original_width' => 1920,
        'original_height' => 1080,
    ]);

    expect($media)->toBeInstanceOf(CmsMedia::class)
        ->and($media->filename)->toBe('test-image.jpg')
        ->and($media->isImage())->toBeTrue()
        ->and($media->isPdf())->toBeFalse()
        ->and($media->getHumanFileSize())->toBe('100 KB')
        ->and($media->getDimensionsLabel())->toBe('1920 × 1080');
});

test('CmsMedia scopes filter correctly', function () {
    CmsMedia::create(['filename' => 'photo.jpg', 'disk' => 'public', 'path' => 'a.jpg', 'type' => 'image', 'collection' => 'hero']);
    CmsMedia::create(['filename' => 'doc.pdf', 'disk' => 'public', 'path' => 'b.pdf', 'type' => 'pdf', 'collection' => 'downloads']);
    CmsMedia::create(['filename' => 'draft.jpg', 'disk' => 'public', 'path' => 'c.jpg', 'type' => 'image', 'is_published' => false]);

    expect(CmsMedia::images()->count())->toBe(2)
        ->and(CmsMedia::pdfs()->count())->toBe(1)
        ->and(CmsMedia::published()->count())->toBe(2)
        ->and(CmsMedia::inCollection('hero')->count())->toBe(1);
});

test('CmsMedia stores translatable alt_text and title', function () {
    $media = CmsMedia::create([
        'filename' => 'hero.jpg',
        'disk' => 'public',
        'path' => 'cms/media/originals/hero.jpg',
        'type' => 'image',
    ]);

    $media->setTranslation('alt_text', 'de', 'Heldenbild');
    $media->setTranslation('alt_text', 'en', 'Hero image');
    $media->setTranslation('title', 'de', 'Startseite Hero');
    $media->save();

    $media->refresh();

    expect($media->getTranslation('alt_text', 'de'))->toBe('Heldenbild')
        ->and($media->getTranslation('alt_text', 'en'))->toBe('Hero image')
        ->and($media->getTranslation('title', 'de'))->toBe('Startseite Hero');
});

test('CmsMedia conversions tracking works', function () {
    $media = CmsMedia::create([
        'filename' => 'test.jpg',
        'disk' => 'public',
        'path' => 'cms/media/originals/test.jpg',
        'type' => 'image',
        'conversions' => [],
    ]);

    expect($media->hasConversion('hero'))->toBeFalse()
        ->and($media->getExistingConversions())->toBe([]);

    $media->update(['conversions' => ['hero' => 'cms/media/conversions/hero/test-hero.webp']]);

    Storage::disk('public')->put('cms/media/conversions/hero/test-hero.webp', 'fake');

    $media->refresh();

    expect($media->hasConversion('hero'))->toBeTrue()
        ->and($media->getExistingConversions())->toHaveKey('hero');
});

test('MediaConversionService storeUpload creates media record', function () {
    $file = UploadedFile::fake()->image('photo.jpg', 800, 600);

    $service = app(MediaConversionService::class);
    $media = $service->storeUpload($file, 'test');

    expect($media)->toBeInstanceOf(CmsMedia::class)
        ->and($media->filename)->toBe('photo.jpg')
        ->and($media->type)->toBe('image')
        ->and($media->collection)->toBe('test')
        ->and($media->original_width)->toBe(800)
        ->and($media->original_height)->toBe(600)
        ->and(Storage::disk('public')->exists($media->path))->toBeTrue();
});

test('MediaConversionService generates thumbnail on upload', function () {
    $file = UploadedFile::fake()->image('big-photo.jpg', 1920, 1080);

    $service = app(MediaConversionService::class);
    $media = $service->storeUpload($file);

    $media->refresh();

    expect($media->hasConversion('thumb'))->toBeTrue();
});

test('MediaConversionService can generate specific profile conversion', function () {
    $file = UploadedFile::fake()->image('hero-bg.jpg', 2400, 1600);

    $service = app(MediaConversionService::class);
    $media = $service->storeUpload($file, generateThumbnail: false);

    $result = $service->convert($media, 'hero');

    expect($result)->not->toBeNull();

    $media->refresh();
    expect($media->hasConversion('hero'))->toBeTrue();
});

test('MediaConversionService deleteAll removes files', function () {
    $file = UploadedFile::fake()->image('delete-me.jpg', 400, 400);

    $service = app(MediaConversionService::class);
    $media = $service->storeUpload($file);

    $path = $media->path;

    expect(Storage::disk('public')->exists($path))->toBeTrue();

    $service->deleteAll($media);

    expect(Storage::disk('public')->exists($path))->toBeFalse();
});

test('MediaConversionService skips SVG files for conversions', function () {
    $file = UploadedFile::fake()->create('logo.svg', 5, 'image/svg+xml');

    $service = app(MediaConversionService::class);
    $media = $service->storeUpload($file, generateThumbnail: false);

    expect($media->type)->toBe('image')
        ->and($media->mime_type)->toBe('image/svg+xml');
});

test('media profiles are configured', function () {
    $profiles = config('flux-cms.media.profiles');

    expect($profiles)->toHaveKey('hero')
        ->and($profiles)->toHaveKey('thumb')
        ->and($profiles)->toHaveKey('avatar')
        ->and($profiles)->toHaveKey('news')
        ->and($profiles)->toHaveKey('thumbnail')
        ->and($profiles)->toHaveKey('service')
        ->and($profiles)->toHaveKey('og_image')
        ->and($profiles['hero']['width'])->toBe(1920)
        ->and($profiles['hero']['height'])->toBe(800)
        ->and($profiles['avatar']['width'])->toBe(400);
});

test('media library admin page loads', function () {
    $user = \App\Models\User::factory()->create();

    $this->actingAs($user)
        ->get(route('cms.media.index'))
        ->assertSuccessful();
});
