<?php

declare(strict_types=1);

use Builder\Core\Extensions\Settings\Pages\GeneralSettings;
use Builder\Core\Foundation\Definition\Field;
use Builder\Core\Foundation\Definition\FieldBuilder;
use Builder\Core\Foundation\Definition\Section;
use Builder\Core\Foundation\Settings\BuilderSettings;

it('BuilderSettings subclass returns correct group, key and label', function (): void {
    $page = new GeneralSettings;

    expect(GeneralSettings::group())->toBe('general')
        ->and($page->getKey())->toBe('general')
        ->and($page->getLabel())->toBe('General');
});

it('BuilderSettings has icon, parent, priority defaults', function (): void {
    $page = new GeneralSettings;

    expect($page->getIcon())->toBe('Settings')
        ->and($page->getParent())->toBeNull()
        ->and($page->getPriority())->toBe(10);
});

it('BuilderSettings fields() returns a FieldBuilder with one section', function (): void {
    $sections = (new GeneralSettings)->fields()->toSections();

    expect($sections)->toHaveCount(1)
        ->and($sections[0])->toBeInstanceOf(Section::class);
});

it('BuilderSettings sections contain expected fields', function (): void {
    $sections = (new GeneralSettings)->fields()->toSections();
    $fields = $sections[0]->getFields();
    $names = array_map(fn (Field $f) => $f->getName(), $fields);

    expect($names)->toContain('site_name')
        ->toContain('admin_email');
});

it('BuilderSettings rules cover all fields', function (): void {
    $rules = (new GeneralSettings)->rules();

    expect($rules)->toHaveKey('site_name')
        ->toHaveKey('admin_email');

    expect($rules['site_name'])->toContain('required');
    expect($rules['admin_email'])->toContain('nullable');
});

it('BuilderSettings permission is null by default', function (): void {
    expect((new GeneralSettings)->getPermission())->toBeNull();
});

it('BuilderSettings navGroup returns settings by default', function (): void {
    expect((new GeneralSettings)->navGroup())->toBe('settings');
});

it('BuilderSettings navGroup can be overridden to opt out of settings nav', function (): void {
    $page = new class extends BuilderSettings
    {
        public static function group(): string
        {
            return 'custom';
        }

        public function getLabel(): string
        {
            return 'Custom';
        }

        public function navGroup(): string
        {
            return '';
        }
    };

    expect($page->navGroup())->toBe('');
});

it('BuilderSettings with permission returns it', function (): void {
    $page = new class extends BuilderSettings
    {
        public static function group(): string
        {
            return 'protected';
        }

        public function getLabel(): string
        {
            return 'Protected';
        }

        public function getPermission(): ?string
        {
            return 'manage-settings';
        }
    };

    expect($page->getPermission())->toBe('manage-settings');
});

it('BuilderSettings fields() wraps bare fields into a _fields section', function (): void {
    $page = new class extends BuilderSettings
    {
        public ?string $foo = null;

        public ?string $bar = null;

        public static function group(): string
        {
            return 'flat';
        }

        public function getLabel(): string
        {
            return 'Flat';
        }

        public function fields(): FieldBuilder
        {
            return FieldBuilder::make()->add(
                Field::text('foo')->label('Foo'),
                Field::text('bar')->label('Bar'),
            );
        }
    };

    $sections = $page->fields()->toSections();

    expect($sections)->toHaveCount(1)
        ->and($sections[0]->getKey())->toBe('_fields')
        ->and($sections[0]->getFields())->toHaveCount(2);
});

it('BuilderSettings getKey defaults to group()', function (): void {
    $page = new class extends BuilderSettings
    {
        public static function group(): string
        {
            return 'my_group';
        }

        public function getLabel(): string
        {
            return 'My Group';
        }
    };

    expect($page->getKey())->toBe('my_group');
});

// ── coerceData: null bool coercion ────────────────────────────────────────────

final class CoerceBoolSettings extends BuilderSettings
{
    public bool $is_active = false;

    public ?bool $nullable_flag = null;

    public static function group(): string
    {
        return 'coerce_bool';
    }

    public function getLabel(): string
    {
        return 'Coerce Bool';
    }
}

it('coerceData converts null to false for non-nullable bool properties', function (): void {
    $data = CoerceBoolSettings::coerceData(['is_active' => null]);

    expect($data['is_active'])->toBeFalse();
});

it('coerceData leaves null for nullable bool properties', function (): void {
    $data = CoerceBoolSettings::coerceData(['nullable_flag' => null]);

    expect($data['nullable_flag'])->toBeNull();
});

it('coerceData leaves non-null values untouched', function (): void {
    $data = CoerceBoolSettings::coerceData(['is_active' => true]);

    expect($data['is_active'])->toBeTrue();
});
