<?php

declare(strict_types=1);

use Builder\Core\Extensions\Account\AccountProfile;
use Builder\Core\Foundation\Definition\Field;
use Builder\Core\Foundation\Definition\Hook;
use Builder\Core\Foundation\Definition\Section;
use Builder\Core\Tests\BuilderTestUser;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Schema;

beforeEach(function (): void {
    Schema::create('users', function ($table): void {
        $table->id();
        $table->string('name')->nullable();
        $table->string('email')->nullable()->unique();
        $table->string('password')->nullable();
        $table->timestamps();
    });

    config(['auth.providers.users.model' => BuilderTestUser::class]);
});

it('AccountProfile has three sections', function (): void {
    $sections = (new AccountProfile)->fields()->toSections();

    expect($sections)->toHaveCount(3);
});

it('AccountProfile sections are profile, password, security', function (): void {
    $sections = (new AccountProfile)->fields()->toSections();
    $keys = array_map(fn (Section $s) => $s->getKey(), $sections);

    expect($keys)->toContain('profile')
        ->toContain('password')
        ->toContain('security');
});

it('AccountProfile sections are sorted by priority', function (): void {
    $sections = (new AccountProfile)->fields()->toSections();
    $priorities = array_map(fn (Section $s) => $s->getPriority(), $sections);
    $sorted = $priorities;
    sort($sorted);

    expect($priorities)->toEqual($sorted);
});

it('AccountProfile profile section has name and email fields', function (): void {
    $sections = (new AccountProfile)->fields()->toSections();
    $profile = array_values(array_filter($sections, fn (Section $s) => $s->getKey() === 'profile'))[0];
    $names = array_map(fn (Field $f) => $f->getName(), $profile->getFields());

    expect($names)->toContain('name')
        ->toContain('email');
});

it('AccountProfile password section has current_password, password, password_confirmation', function (): void {
    $sections = (new AccountProfile)->fields()->toSections();
    $password = array_values(array_filter($sections, fn (Section $s) => $s->getKey() === 'password'))[0];
    $names = array_map(fn (Field $f) => $f->getName(), $password->getFields());

    expect($names)->toContain('current_password')
        ->toContain('password')
        ->toContain('password_confirmation');
});

it('AccountProfile security section has mfa_settings field with MfaSettings component', function (): void {
    $sections = (new AccountProfile)->fields()->toSections();
    $security = array_values(array_filter($sections, fn (Section $s) => $s->getKey() === 'security'))[0];
    $field = $security->getFields()[0];

    expect($field->getName())->toBe('mfa_settings')
        ->and($field->getComponent())->toBe('MfaSettings');
});

it('AccountProfile rules cover name, email, and password fields', function (): void {
    $user = BuilderTestUser::create([
        'name' => 'Test',
        'email' => 'test@example.com',
        'password' => Hash::make('secret'),
    ]);
    $this->actingAs($user);

    $rules = (new AccountProfile)->rules();

    expect($rules)->toHaveKey('name')
        ->toHaveKey('email')
        ->toHaveKey('password')
        ->toHaveKey('current_password')
        ->toHaveKey('password_confirmation');

    expect($rules['password'])->toContain('nullable')
        ->toContain('min:8')
        ->toContain('confirmed');
});

it('AccountProfile hooks include saving events', function (): void {
    $hooks = (new AccountProfile)->hooks();
    $events = array_map(fn (Hook $h) => $h->getEvent(), $hooks);

    expect(array_count_values($events)['saving'])->toBeGreaterThanOrEqual(1);
});
