<?php

declare(strict_types=1);

use Builder\Core\Foundation\Dashboard\Widgets\CounterWidget;
use Builder\Core\Foundation\Dashboard\Widgets\Widget;
use Builder\Core\Foundation\Registry;
use Builder\Core\Foundation\Resources\Extension;
use Builder\Core\Foundation\Resources\Resource;
use Illuminate\Database\Eloquent\Model;

// ── Anonymous concrete Widget for testing with configurable order ──────────────

function makeWidget(string $key, int $order = 0): Widget
{
    return new class($key, $order) extends Widget
    {
        public function __construct(private readonly string $k, int $o)
        {
            $this->order = $o;
        }

        public function getKey(): string
        {
            return $this->k;
        }

        public function getLabel(): string
        {
            return $this->k;
        }

        public function getComponent(): string
        {
            return 'CounterWidget';
        }

        /** @return array<string, mixed> */
        public function getData(): array
        {
            return [];
        }
    };
}

final class WidgetResource extends Resource
{
    public static function getSlug(): string
    {
        return 'widget-items';
    }

    public static function getLabel(): string
    {
        return 'Widget Items';
    }

    /** @return class-string<Model> */
    public static function getModel(): string
    {
        return Model::class;
    }

    /** @return list<Widget> */
    public function widgets(): array
    {
        return [new CounterWidget('item-count', 'Item Count', fn () => 0)];
    }
}

final class WidgetExtension extends Extension
{
    /** @return class-string<resource> */
    public static function getExtends(): string
    {
        return WidgetResource::class;
    }

    /** @return list<Widget> */
    public function widgets(): array
    {
        return [new CounterWidget('ext-widget', 'Ext Widget', fn () => 0)];
    }
}

it('widget() directly registers a widget', function (): void {
    $registry = new Registry;
    $registry->widget(new CounterWidget('my-widget', 'My Widget', fn () => 0));

    expect($registry->widgets())->toHaveCount(1)
        ->and($registry->widgets()[0]->getKey())->toBe('my-widget');
});

it('resource registration auto-collects resource widgets', function (): void {
    $registry = new Registry;
    $registry->resource(WidgetResource::class);

    expect($registry->widgets())->toHaveCount(1)
        ->and($registry->widgets()[0]->getKey())->toBe('item-count');
});

it('extend registration auto-collects extension widgets', function (): void {
    $registry = new Registry;
    $registry->extend(WidgetExtension::class);

    expect($registry->widgets())->toHaveCount(1)
        ->and($registry->widgets()[0]->getKey())->toBe('ext-widget');
});

it('widgets() returns all widgets sorted by order', function (): void {
    $registry = new Registry;
    $registry->widget(makeWidget('c', 3));
    $registry->widget(makeWidget('a', 1));
    $registry->widget(makeWidget('b', 2));

    $keys = array_map(fn (Widget $w) => $w->getKey(), $registry->widgets());

    expect($keys)->toBe(['a', 'b', 'c']);
});

it('widgets() returns empty array when none registered', function (): void {
    $registry = new Registry;

    expect($registry->widgets())->toBe([]);
});
