<?php

use Lightscale\LaralightAssets\Assets;
use Lightscale\LaralightAssets\Manifest;
use Lightscale\LaralightAssets\FileString;

describe('instance', function() {
    it('instantiates', function() {
        new Assets();
    })->throwsNoExceptions();

    it('instantiates from container', function() {
        app(Assets::class);
    })->throwsNoExceptions();

    it('is singleton', function() {
        expect(app(Assets::class))->toBe(app(Assets::class));
    });
});

$newManifest = fn() => new Manifest(
    public_path('dist/manifest.json'),
    '/dist',
);

describe('manages manifests', function() use ($newManifest) {
    it('adds manifests', function() use ($newManifest) {
        app(Assets::class)->addManifest('main', $newManifest(), isDefault: true);
    })->throwsNoExceptions();

    it('registers manifests', function() {
        app(Assets::class)->registerManifest(
            'main', public_path('dist/manifest.json'), '/dist', isDefault: true,
        );
    })->throwsNoExceptions();

    it('gets manifests', function() {
        $assets = app(Assets::class);
        $assets->registerManifest(
            'main', public_path('dist/manifest.json'), '/dist', isDefault: true,
        );

        expect($assets->getManifests())
            ->toHaveLength(1)
            ->toContainOnlyInstancesOf(Manifest::class);
    });

    it('gets manifest', function() use ($newManifest){
        $assets = app(Assets::class);
        $manifest = $newManifest();
        $name = 'main';
        $assets->addManifest($name, $manifest, true);

        expect($assets->getManifest($name))->toBe($manifest);
    });

    it('gets default manifest', function() use ($newManifest) {
        $assets = app(Assets::class);
        $manifest = $newManifest();
        $name = 'main';
        $assets->addManifest($name, $manifest, true);

        expect($assets->getDefaultManifest())->toBe($manifest);
    });

    it('throws exception missing manifest', function() {
        $assets = app(Assets::class);
        $assets->getManifest('main');
    })->throws(Exception::class);

    it('has null default manifest')
        ->expect(fn() => app(Assets::class)->getDefaultManifest())
        ->toBeNull();

    it('throws exception setting default to missing manifest', function() {
        $assets = app(Assets::class);
        $assets->setDefaultManifest('testing');
    })->throws(Exception::class);

    test('get manifest from FileString', function() use($newManifest) {
        $assets = app(Assets::class);
        $manifest = $newManifest();
        $assets->addManifest('main', $manifest, true);
        $file = new FileString('main::test.css');
        $result = $assets->getFileManifest($file);
        expect($result)->toBe($manifest);
    });

    test('default manifest from FileString', function() use($newManifest) {
        $assets = app(Assets::class);
        $manifest = $newManifest();
        $assets->addManifest('main', $manifest, true);
        $file = new FileString('test.css');
        $result = $assets->getFileManifest($file);
        expect($result)->toBe($manifest);
    });
});

describe('queuing files', function() use ($newManifest) {
    test('queue script', function() use ($newManifest) {
        $assets = app(Assets::class);
        $manifest = $newManifest();
        $assets->addManifest('main', $manifest, true);
        $assets->queueScript('main::main.js');

        expect($assets->getQueuedFooterFiles())->toBeArray()->toHaveLength(1);
    });

    test('queue style', function() use ($newManifest) {
        $assets = app(Assets::class);
        $manifest = $newManifest();
        $assets->addManifest('main', $manifest, true);
        $assets->queueStyle('main::main.css');

        expect($assets->getQueuedHeadFiles())->toBeArray()->toHaveLength(1);
    });

    test('queue file not in manifest', function() use ($newManifest) {
        $assets = app(Assets::class);
        $url = 'https://lightscale.co.uk/test.css';
        $assets->queueStyle($url);
        $results = $assets->getQueuedHeadFiles();
        expect($results)->toBeArray()->toHaveLength(1);
        expect($results[0]->getUrl())->toBe($url);
    });
});