<?php

use App\Livewire\NewSupportRequest;
use App\Livewire\Support;
use App\Models\Customer;
use App\Models\Instance;
use App\Models\SupportRequest;
use App\Models\User;
use Livewire\Livewire;

/**
 * Asking for help, and being able to see that you did.
 *
 * The page used to be a decorated placeholder: a button that raised a toast
 * saying the form was "only hinted at in the prototype", three invented ticket
 * titles sitting in the translation file, and no way to check what had become
 * of anything. It looked thin because nothing on it was real.
 */

function supportCustomer(): array
{
    $user = User::factory()->create(['name' => 'Dr. S. Berger']);
    $customer = Customer::factory()->create(['user_id' => $user->id, 'email' => $user->email]);

    return [$user, $customer];
}

it('records a request and shows it back to the customer', function () {
    [$user, $customer] = supportCustomer();

    Livewire::actingAs($user)
        ->test(NewSupportRequest::class)
        ->set('category', 'technical')
        ->set('subject', 'Kalendersynchronisation mit Outlook')
        ->set('body', 'Termine werden bei zwei Mitarbeitern nicht mehr übernommen.')
        ->call('save')
        ->assertHasNoErrors();

    $request = SupportRequest::query()->where('customer_id', $customer->id)->sole();

    expect($request->status)->toBe('open')
        // The person, not the account: on a shared login the account name says
        // nothing about who is actually asking.
        ->and($request->reported_by)->toBe('Dr. S. Berger');

    Livewire::actingAs($user)
        ->test(Support::class)
        ->assertSee('Kalendersynchronisation mit Outlook')
        ->assertSee(__('support.status_open'));
});

it('attaches the instance so nobody has to ask which server', function () {
    [$user, $customer] = supportCustomer();
    $instance = Instance::factory()->create(['customer_id' => $customer->id, 'status' => 'active']);

    Livewire::actingAs($user)
        ->test(NewSupportRequest::class)
        ->set('subject', 'Ein Betreff')
        ->set('body', 'Eine Nachricht, die lang genug ist.')
        ->call('save');

    expect(SupportRequest::query()->sole()->instance_id)->toBe($instance->id);
});

it('still takes a request from somebody whose cloud is not built yet', function () {
    // A question can arrive before provisioning finishes, and that is exactly
    // when somebody is most likely to have one.
    [$user] = supportCustomer();

    Livewire::actingAs($user)
        ->test(NewSupportRequest::class)
        ->set('subject', 'Wann geht es los?')
        ->set('body', 'Wir haben gestern bestellt und würden gerne planen.')
        ->call('save')
        ->assertHasNoErrors();

    expect(SupportRequest::query()->sole()->instance_id)->toBeNull();
});

it('refuses an empty or barely-written request', function () {
    [$user] = supportCustomer();

    Livewire::actingAs($user)
        ->test(NewSupportRequest::class)
        ->set('subject', '')
        ->set('body', 'kurz')
        ->call('save')
        ->assertHasErrors(['subject', 'body']);

    expect(SupportRequest::query()->count())->toBe(0);
});

it('refuses a category that is not on the form', function () {
    [$user] = supportCustomer();

    Livewire::actingAs($user)
        ->test(NewSupportRequest::class)
        ->set('category', 'urgent-vip')
        ->set('subject', 'Ein Betreff')
        ->set('body', 'Eine Nachricht, die lang genug ist.')
        ->call('save')
        ->assertHasErrors('category');
});

it('shows a customer only their own requests', function () {
    [$user] = supportCustomer();
    [, $other] = supportCustomer();

    SupportRequest::create([
        'customer_id' => $other->id,
        'subject' => 'Fremde Anfrage',
        'category' => 'billing',
        'body' => 'Gehört jemand anderem.',
        'status' => 'open',
    ]);

    Livewire::actingAs($user)
        ->test(Support::class)
        ->assertDontSee('Fremde Anfrage')
        ->assertSee(__('support.empty_title'));
});

it('counts only what is still open', function () {
    [$user, $customer] = supportCustomer();

    foreach (['open', 'in_progress', 'answered', 'closed'] as $status) {
        SupportRequest::create([
            'customer_id' => $customer->id,
            'subject' => 'Anfrage '.$status,
            'category' => 'other',
            'body' => 'Eine Nachricht, die lang genug ist.',
            'status' => $status,
        ]);
    }

    Livewire::actingAs($user)
        ->test(Support::class)
        // open + in_progress. Answered and closed are done with.
        ->assertViewHas('openCount', 2);
});

it('says something useful when there is nothing to show', function () {
    // An empty state that names the next step, rather than "no data".
    [$user] = supportCustomer();

    Livewire::actingAs($user)
        ->test(Support::class)
        ->assertSee(__('support.empty_title'))
        ->assertSee(__('support.empty_body'))
        ->assertSee(__('support.new'));
});

it('carries no invented ticket titles', function () {
    // Three fictional tickets used to live in the translation file and render
    // as though they were the customer's own.
    foreach (['de', 'en'] as $locale) {
        $keys = array_keys(include base_path("lang/{$locale}/support.php"));

        expect($keys)->not->toContain('ticket_migration')
            ->and($keys)->not->toContain('ticket_training')
            ->and($keys)->not->toContain('ticket_smtp')
            ->and($keys)->not->toContain('new_toast');
    }
});
