<?php

use App\Livewire\Dashboard;
use App\Models\Customer;
use App\Models\Instance;
use App\Models\Order;
use App\Models\User;
use Illuminate\Support\Facades\DB;

it('redirects guests to the login page', function () {
    $this->get('/dashboard')->assertRedirect('/login');
});

it('shows the dashboard to authenticated users', function () {
    $user = User::factory()->create();

    $this->actingAs($user)->get('/dashboard')
        ->assertOk()
        ->assertSee('CluPilot')
        ->assertSee(__('dashboard.title'));
});

it('shows no next invoice once the customer has given notice', function () {
    // Cancelling leaves the subscription active until the term runs out, so
    // `current_period_end` becomes the day service ENDS rather than the day the
    // next charge falls. Billing a renewal that will never happen, on the sheet
    // a customer checks their invoices against, is the worst line this page
    // could carry.
    $user = App\Models\User::factory()->create();
    $customer = App\Models\Customer::factory()->create(['user_id' => $user->id]);

    $instance = App\Models\Instance::factory()->create([
        'customer_id' => $customer->id,
        'status' => 'cancellation_scheduled',
        'cancel_requested_at' => now(),
        'service_ends_at' => now()->addMonth(),
    ]);

    App\Models\Subscription::factory()->create([
        'customer_id' => $customer->id,
        'instance_id' => $instance->id,
        'status' => 'active',
        'price_cents' => 17900,
        'currency' => 'EUR',
        'term' => 'monthly',
        'current_period_end' => now()->addMonth(),
    ]);

    Livewire::actingAs($user)
        ->test(App\Livewire\Dashboard::class)
        ->assertViewHas('nextInvoice', null)
        // The price is still on the master record — they pay it until the end.
        ->assertViewHas('planPrice', fn (?array $p) => $p !== null && $p['cents'] === 17900)
        ->assertDontSee(__('dashboard.invoice.label'));
});

it('shows the credentials card, and lets acknowledging delete the password rather than just hide it', function () {
    $user = User::factory()->create(['email' => 'ack@cred.test']);
    $customer = Customer::factory()->create(['email' => 'ack@cred.test', 'user_id' => $user->id]);
    $order = Order::factory()->create(['customer_id' => $customer->id]);
    $instance = Instance::factory()->create([
        'customer_id' => $customer->id,
        'order_id' => $order->id,
        'status' => 'active',
        'nc_admin_ref' => 'admin',
        'admin_password' => 'my-secret-pw',
    ]);

    Livewire::actingAs($user)
        ->test(Dashboard::class)
        ->assertSee(__('dashboard.credentials.title'))
        ->assertSee('my-secret-pw')
        ->call('acknowledgeCredentials', $instance->uuid)
        ->assertDontSee('my-secret-pw')
        ->assertDontSee(__('dashboard.credentials.title'));

    // Not merely hidden from the card — actually gone, at the raw stored
    // column too, so a mutant that only toggled a "hide the card" flag
    // without clearing admin_password is caught here.
    expect($instance->fresh()->admin_password)->toBeNull()
        ->and($instance->fresh()->credentials_acknowledged_at)->not->toBeNull();

    $raw = DB::table('instances')->where('id', $instance->id)->value('admin_password');
    expect($raw)->toBeNull();
});

it("refuses to acknowledge — or leak — another customer's credentials", function () {
    $userA = User::factory()->create(['email' => 'a@cred.test']);
    $customerA = Customer::factory()->create(['email' => 'a@cred.test', 'user_id' => $userA->id]);
    $orderA = Order::factory()->create(['customer_id' => $customerA->id]);
    $instanceA = Instance::factory()->create([
        'customer_id' => $customerA->id,
        'order_id' => $orderA->id,
        'status' => 'active',
        'nc_admin_ref' => 'admin',
        'admin_password' => 'a-secret-pw',
    ]);

    $userB = User::factory()->create(['email' => 'b@cred.test']);
    $customerB = Customer::factory()->create(['email' => 'b@cred.test', 'user_id' => $userB->id]);
    $orderB = Order::factory()->create(['customer_id' => $customerB->id]);
    Instance::factory()->create([
        'customer_id' => $customerB->id,
        'order_id' => $orderB->id,
        'status' => 'active',
    ]);

    // B's own dashboard render must not show A's password — render() scopes
    // $instance to $customer's own instances, so this should hold already.
    Livewire::actingAs($userB)
        ->test(Dashboard::class)
        ->assertDontSee('a-secret-pw')
        // B posting A's instance uuid directly — exactly what an unchecked
        // Livewire action allows, since the card that would normally supply
        // this uuid is never rendered for B. acknowledgeCredentials() must
        // re-resolve the instance from B's own customer, not trust the uuid.
        ->call('acknowledgeCredentials', $instanceA->uuid);

    expect($instanceA->fresh()->admin_password)->not->toBeNull()
        ->and($instanceA->fresh()->credentials_acknowledged_at)->toBeNull();
});
