<?php

namespace FluxCms\Core\Tests\Unit;

use FluxCms\Core\FieldTypes\MediaField;
use FluxCms\Core\FieldTypes\TextField;
use FluxCms\Core\Services\ComponentRegistry;
use Livewire\Component;
use Mockery;
use Orchestra\Testbench\TestCase;

class ComponentRegistryTest extends TestCase
{
    protected ComponentRegistry $registry;

    protected function setUp(): void
    {
        parent::setUp();
        $this->registry = new ComponentRegistry;
    }

    public function test_can_detect_valid_component()
    {
        $componentClass = TestComponent::class;

        $this->assertTrue($this->registry->isValidComponent($componentClass));
    }

    public function test_can_get_component_config()
    {
        $componentClass = TestComponent::class;

        $config = $this->registry->getComponentConfig($componentClass);

        $this->assertIsArray($config);
        $this->assertEquals('Test Component', $config['name']);
        $this->assertEquals('Testing', $config['category']);
        $this->assertCount(2, $config['fields']);
    }

    public function test_can_validate_component_content()
    {
        $componentClass = TestComponent::class;

        // Valid content
        $validContent = [
            'title' => ['de' => 'Test Titel', 'en' => 'Test Title'],
            'image' => 123,
        ];

        $errors = $this->registry->validateComponentContent($componentClass, $validContent);
        $this->assertEmpty($errors);

        // Invalid content (missing required field)
        $invalidContent = [
            'image' => 123,
        ];

        $errors = $this->registry->validateComponentContent($componentClass, $invalidContent);
        $this->assertNotEmpty($errors);
    }

    public function test_can_search_components()
    {
        // Mock some components in registry
        $components = [
            TestComponent::class => [
                'name' => 'Test Component',
                'category' => 'Testing',
                'description' => 'A test component',
                'tags' => ['test', 'example'],
            ],
        ];

        $registry = Mockery::mock(ComponentRegistry::class)->makePartial();
        $registry->shouldReceive('getAvailableComponents')->andReturn($components);

        $results = $registry->searchComponents('test');

        $this->assertCount(1, $results);
        $this->assertArrayHasKey(TestComponent::class, $results);
    }

    public function test_can_get_components_by_category()
    {
        $components = [
            TestComponent::class => [
                'name' => 'Test Component',
                'category' => 'Testing',
            ],
            AnotherTestComponent::class => [
                'name' => 'Another Component',
                'category' => 'Layout',
            ],
        ];

        $registry = Mockery::mock(ComponentRegistry::class)->makePartial();
        $registry->shouldReceive('getAvailableComponents')->andReturn($components);

        $categorized = $registry->getComponentsByCategory();

        $this->assertArrayHasKey('Testing', $categorized);
        $this->assertArrayHasKey('Layout', $categorized);
        $this->assertCount(1, $categorized['Testing']);
        $this->assertCount(1, $categorized['Layout']);
    }

    protected function tearDown(): void
    {
        Mockery::close();
        parent::tearDown();
    }
}

// Test component classes
class TestComponent extends Component
{
    public static function getCmsName(): string
    {
        return 'Test Component';
    }

    public static function getCmsCategory(): string
    {
        return 'Testing';
    }

    public static function getCmsFields(): array
    {
        return [
            TextField::make('title', 'Title')->translatable()->required(),
            MediaField::make('image', 'Image')->images(),
        ];
    }

    public function render()
    {
        return '<div>Test Component</div>';
    }
}

class AnotherTestComponent extends Component
{
    public static function getCmsName(): string
    {
        return 'Another Component';
    }

    public static function getCmsCategory(): string
    {
        return 'Layout';
    }

    public static function getCmsFields(): array
    {
        return [
            TextField::make('content', 'Content'),
        ];
    }

    public function render()
    {
        return '<div>Another Component</div>';
    }
}
