<?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;
use Builder\Core\Foundation\Settings\SettingsDefinition;
use Builder\Core\Foundation\Settings\SettingsExtension;

it('SettingsDefinition wraps sections from BuilderSettings', function (): void {
    $page = new GeneralSettings;
    $definition = SettingsDefinition::make($page);

    expect($definition->getSections())->toHaveCount(1);
});

it('SettingsDefinition wraps fields() in a default section when sections() is empty', 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 Page';
        }

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

    $definition = SettingsDefinition::make($page);
    $sections = $definition->getSections();

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

it('SettingsDefinition merges rules from page', function (): void {
    $definition = SettingsDefinition::make(new GeneralSettings);

    expect($definition->getRules())->toHaveKey('site_name')
        ->toHaveKey('admin_email');
});

it('SettingsDefinition sorts sections by priority', function (): void {
    $page = new class extends BuilderSettings
    {
        public static function group(): string
        {
            return 'multi';
        }

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

        public function fields(): FieldBuilder
        {
            return FieldBuilder::make()->add(
                Section::make('second')->label('Second')->priority(10),
                Section::make('first')->label('First')->priority(0),
            );
        }
    };

    $definition = SettingsDefinition::make($page);
    $sections = $definition->getSections();

    expect($sections[0]->getKey())->toBe('first');
});

it('SettingsDefinition toArray includes key, label, icon, sections', function (): void {
    $arr = SettingsDefinition::make(new GeneralSettings)->toArray();

    expect($arr)->toHaveKey('key', 'general')
        ->toHaveKey('label', 'General')
        ->toHaveKey('icon')
        ->toHaveKey('sections');
});

it('SettingsDefinition getCompositeKey returns the key', function (): void {
    $def = SettingsDefinition::make(new GeneralSettings);

    expect($def->getCompositeKey())->toBe('general');
});

it('SettingsDefinition getSettingsClass returns the FQCN', function (): void {
    $def = SettingsDefinition::make(new GeneralSettings);

    expect($def->getSettingsClass())->toBe(GeneralSettings::class);
});

it('SettingsDefinition make with sub-page derives composite key from parent.key', function (): void {
    $subPage = new class extends BuilderSettings
    {
        public static function group(): string
        {
            return 'advanced';
        }

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

        public function getParent(): ?string
        {
            return 'general';
        }
    };

    $def = SettingsDefinition::make($subPage);

    expect($def->getCompositeKey())->toBe('general.advanced');
});

it('SettingsDefinition::make merges sections and rules from extensions', function (): void {
    $page = new GeneralSettings;

    $extension = new class extends SettingsExtension
    {
        public static function getExtends(): string
        {
            return GeneralSettings::class;
        }

        public static function getSettingsClass(): string
        {
            return GeneralSettings::class;
        }

        public function fields(): FieldBuilder
        {
            return FieldBuilder::make()->add(Section::make('extra')->label('Extra'));
        }

        public function rules(): array
        {
            return ['extra_field' => ['nullable', 'string']];
        }
    };

    $def = SettingsDefinition::make($page, 'general', [$extension]);

    $sectionKeys = array_map(fn (Section $s): string => $s->getKey(), $def->getSections());
    expect($sectionKeys)->toContain('extra')
        ->and($def->getRules())->toHaveKey('extra_field');
});
