<?php

namespace Tests\Feature;

use App\Models\ReminderNotificationLog;
use App\Models\User;
use Database\Seeders\SimulationSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Tests\TestCase;

class NotificationCenterTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        Storage::fake('local');
        config([
            'simulation.enabled' => true,
            'simulation.phase' => 'operations-surfaces',
            'simulation.anchor_date' => '2026-08-01',
            'simulation.as_of_date' => '2026-08-15',
            'simulation.user_password' => 'Simulation@2026',
        ]);
        $this->seed(SimulationSeeder::class);
    }

    public function test_admin_bell_links_to_center_and_center_aggregates_personal_alert_and_delivery_attention(): void
    {
        $admin = User::query()->where('username', 'admin')->firstOrFail();
        $notificationId = $this->insertNotification($admin, [
            'event' => 'system_review',
            'title' => 'System review required',
            'message' => 'A controlled staff notification needs attention.',
        ]);

        ReminderNotificationLog::query()->where('channel', 'in_system')->firstOrFail()->update([
            'status' => 'failed',
            'error' => 'Provider unavailable for notification-center test.',
        ]);

        $this->actingAs($admin)
            ->get(route('dashboard'))
            ->assertOk()
            ->assertSee(route('notification-center.index'), false)
            ->assertSee('items need attention');

        $this->actingAs($admin)
            ->get(route('notification-center.index'))
            ->assertOk()
            ->assertSee('Notification Center')
            ->assertSee('System review required')
            ->assertSee('Requires management attention')
            ->assertSee('Overdue threshold:')
            ->assertSee('Delivery failures')
            ->assertSee('Provider unavailable for notification-center test.');

        $this->assertNull(DB::table('notifications')->where('id', $notificationId)->value('read_at'));
    }

    public function test_personal_notification_actions_are_scoped_to_authenticated_owner(): void
    {
        $admin = User::query()->where('username', 'admin')->firstOrFail();
        $other = User::query()->where('username', 'sim.dar.manager')->firstOrFail();
        $ownId = $this->insertNotification($admin, ['event' => 'system_notice', 'message' => 'Admin notice']);
        $otherId = $this->insertNotification($other, ['event' => 'system_notice', 'message' => 'Other notice']);

        $this->actingAs($admin)->post(route('notification-center.read', $otherId))->assertNotFound();
        $this->actingAs($admin)->delete(route('notification-center.destroy', $otherId))->assertNotFound();
        $this->assertDatabaseHas('notifications', ['id' => $otherId, 'read_at' => null]);

        $this->actingAs($admin)->post(route('notification-center.read', $ownId))->assertRedirect();
        $this->assertNotNull(DB::table('notifications')->where('id', $ownId)->value('read_at'));

        $secondId = $this->insertNotification($admin, ['event' => 'system_notice', 'message' => 'Second notice']);
        $this->actingAs($admin)->post(route('notification-center.read-all'))->assertRedirect();
        $this->assertNotNull(DB::table('notifications')->where('id', $secondId)->value('read_at'));

        $this->actingAs($admin)->delete(route('notification-center.destroy', $ownId))->assertRedirect();
        $this->assertDatabaseMissing('notifications', ['id' => $ownId]);
    }

    private function insertNotification(User $user, array $data): string
    {
        $id = (string) Str::uuid();
        DB::table('notifications')->insert([
            'id' => $id,
            'type' => 'Tests\\SystemNotification',
            'notifiable_type' => User::class,
            'notifiable_id' => $user->id,
            'data' => json_encode($data, JSON_THROW_ON_ERROR),
            'read_at' => null,
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        return $id;
    }
}
