<?php

declare(strict_types=1);

use App\Framework\Admin\ValueObjects\CrudConfig;

describe('CrudConfig', function () {
    it('creates config with basic resource information', function () {
        $config = CrudConfig::forResource(
            resource: 'campaigns',
            resourceName: 'Campaign',
            title: 'Campaigns'
        );

        expect($config->resource)->toBe('campaigns');
        expect($config->resourceName)->toBe('Campaign');
        expect($config->title)->toBe('Campaigns');
        expect($config->canCreate)->toBeTrue();
        expect($config->canEdit)->toBeTrue();
        expect($config->canView)->toBeTrue();
        expect($config->canDelete)->toBeTrue();
        expect($config->searchable)->toBeTrue();
    });

    it('creates config with columns', function () {
        $columns = [
            ['field' => 'name', 'label' => 'Name', 'sortable' => true],
            ['field' => 'status', 'label' => 'Status', 'sortable' => true],
        ];

        $config = CrudConfig::forResource('campaigns', 'Campaign', 'Campaigns')
            ->withColumns($columns);

        expect($config->columns)->toBe($columns);
        expect($config->resource)->toBe('campaigns');
    });

    it('creates config with custom permissions', function () {
        $config = CrudConfig::forResource('campaigns', 'Campaign', 'Campaigns')
            ->withPermissions(
                canCreate: true,
                canEdit: true,
                canView: false,
                canDelete: false
            );

        expect($config->canCreate)->toBeTrue();
        expect($config->canEdit)->toBeTrue();
        expect($config->canView)->toBeFalse();
        expect($config->canDelete)->toBeFalse();
    });

    it('creates config with filters', function () {
        $filters = [
            ['field' => 'status', 'type' => 'select', 'options' => ['active', 'draft']],
            ['field' => 'category', 'type' => 'select', 'options' => ['music', 'podcast']],
        ];

        $config = CrudConfig::forResource('campaigns', 'Campaign', 'Campaigns')
            ->withFilters($filters);

        expect($config->filters)->toBe($filters);
    });

    it('creates config with bulk actions', function () {
        $bulkActions = [
            ['name' => 'activate', 'label' => 'Activate Selected'],
            ['name' => 'archive', 'label' => 'Archive Selected'],
        ];

        $config = CrudConfig::forResource('campaigns', 'Campaign', 'Campaigns')
            ->withBulkActions($bulkActions);

        expect($config->bulkActions)->toBe($bulkActions);
    });

    it('converts to array with all properties', function () {
        $config = CrudConfig::forResource('campaigns', 'Campaign', 'Campaigns')
            ->withColumns([
                ['field' => 'name', 'label' => 'Name'],
            ])
            ->withPermissions(
                canCreate: true,
                canEdit: true,
                canView: true,
                canDelete: false
            );

        $array = $config->toArray();

        expect($array)->toHaveKey('resource');
        expect($array)->toHaveKey('resourceName');
        expect($array)->toHaveKey('title');
        expect($array)->toHaveKey('columns');
        expect($array)->toHaveKey('canCreate');
        expect($array)->toHaveKey('canEdit');
        expect($array)->toHaveKey('canView');
        expect($array)->toHaveKey('canDelete');
        expect($array)->toHaveKey('hasActions');
        expect($array)->toHaveKey('searchable');

        expect($array['resource'])->toBe('campaigns');
        expect($array['resourceName'])->toBe('Campaign');
        expect($array['hasActions'])->toBeTrue(); // canEdit is true
    });

    it('calculates hasActions correctly when no actions are allowed', function () {
        $config = CrudConfig::forResource('campaigns', 'Campaign', 'Campaigns')
            ->withPermissions(
                canCreate: false,
                canEdit: false,
                canView: false,
                canDelete: false
            );

        $array = $config->toArray();

        expect($array['hasActions'])->toBeFalse();
    });

    it('calculates hasActions correctly when any action is allowed', function () {
        $config1 = CrudConfig::forResource('campaigns', 'Campaign', 'Campaigns')
            ->withPermissions(canCreate: false, canEdit: true, canView: false, canDelete: false);

        $config2 = CrudConfig::forResource('campaigns', 'Campaign', 'Campaigns')
            ->withPermissions(canCreate: false, canEdit: false, canView: true, canDelete: false);

        $config3 = CrudConfig::forResource('campaigns', 'Campaign', 'Campaigns')
            ->withPermissions(canCreate: false, canEdit: false, canView: false, canDelete: true);

        expect($config1->toArray()['hasActions'])->toBeTrue();
        expect($config2->toArray()['hasActions'])->toBeTrue();
        expect($config3->toArray()['hasActions'])->toBeTrue();
    });

    it('chains multiple configuration methods', function () {
        $config = CrudConfig::forResource('campaigns', 'Campaign', 'Campaigns')
            ->withColumns([['field' => 'name', 'label' => 'Name']])
            ->withPermissions(canCreate: true, canEdit: true, canView: false, canDelete: false)
            ->withFilters([['field' => 'status', 'type' => 'select']])
            ->withBulkActions([['name' => 'activate', 'label' => 'Activate']]);

        expect($config->columns)->toHaveCount(1);
        expect($config->filters)->toHaveCount(1);
        expect($config->bulkActions)->toHaveCount(1);
        expect($config->canView)->toBeFalse();
        expect($config->canCreate)->toBeTrue();
    });

    it('creates immutable value objects', function () {
        $original = CrudConfig::forResource('campaigns', 'Campaign', 'Campaigns');
        $modified = $original->withColumns([['field' => 'name', 'label' => 'Name']]);

        // Original should not be modified
        expect($original->columns)->toBe([]);
        expect($modified->columns)->toHaveCount(1);

        // They should be different instances
        expect($original !== $modified)->toBeTrue();
    });

    it('preserves all properties when using with methods', function () {
        $filters = [['field' => 'status', 'type' => 'select']];
        $bulkActions = [['name' => 'activate', 'label' => 'Activate']];

        $original = CrudConfig::forResource('campaigns', 'Campaign', 'Campaigns')
            ->withFilters($filters)
            ->withBulkActions($bulkActions);

        $withColumns = $original->withColumns([['field' => 'name', 'label' => 'Name']]);

        // New config should have all previous properties
        expect($withColumns->filters)->toBe($filters);
        expect($withColumns->bulkActions)->toBe($bulkActions);
        expect($withColumns->columns)->toHaveCount(1);
    });
});
