<?php

use App\Models\Attendance;
use App\Models\CashAccount;
use App\Models\Employee;
use App\Models\Expense;
use App\Models\Payroll;
use App\Models\PayrollPeriod;
use App\Models\Product;
use App\Models\User;
use App\Notifications\WebPushNotification;
use App\Services\Admin\Finance\Cash\CashTransactionService;
use App\Services\Admin\Finance\EmployeeAdvanceService;
use App\Services\Admin\Finance\ExpenseService;
use App\Services\Admin\Finance\Payroll\PayrollPeriodService;
use App\Services\Admin\HR\AttendanceService;
use App\Services\Admin\HR\LeaveRequestService;
use App\Services\Admin\Master\Product\ProductService;
use App\Services\NotificationService;
use Database\Seeders\RolePermissionSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Notification;
use Spatie\Permission\PermissionRegistrar;

uses(RefreshDatabase::class);

beforeEach(function () {
    app()[PermissionRegistrar::class]->forgetCachedPermissions();
    $this->seed(RolePermissionSeeder::class);
});

/*
|--------------------------------------------------------------------------
| HELPERS
|--------------------------------------------------------------------------
*/

function notifUserWithRole(string $role, bool $active = true): User
{
    $user = User::factory()->create(['is_active' => $active]);
    $user->assignRole($role);

    return $user;
}

function notifEmployeeWithRole(string $role = 'Kasir'): array
{
    $user = notifUserWithRole($role);
    $employee = Employee::factory()->create(['user_id' => $user->id]);

    return ['user' => $user, 'employee' => $employee];
}

/*
|--------------------------------------------------------------------------
| NOTIFICATION SERVICE — UNIT TESTS
|--------------------------------------------------------------------------
*/

test('NotificationService creates in-app notification for users with matching role', function () {
    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');
    notifUserWithRole('Kasir'); // should NOT receive

    NotificationService::notify(
        roles: ['Owner', 'Developer'],
        title: 'Test Title',
        body: 'Test Body.',
        url: '/test-url'
    );

    expect($developer->notifications()->count())->toBe(1);
    expect($owner->notifications()->count())->toBe(1);

    $notification = $developer->notifications()->first();
    expect($notification->title)->toBe('Test Title')
        ->and($notification->body)->toBe('Test Body.')
        ->and($notification->url)->toBe('/test-url')
        ->and($notification->is_read)->toBeFalse();
});

test('NotificationService does not notify inactive users', function () {
    notifUserWithRole('Developer', active: false);
    $active = notifUserWithRole('Developer');

    NotificationService::notify(
        roles: ['Developer'],
        title: 'Test',
        body: 'Body.',
        url: '/test'
    );

    expect($active->notifications()->count())->toBe(1);
    expect(User::where('is_active', false)->first()->notifications()->count())->toBe(0);
});

test('NotificationService dispatches WebPushNotification to each user', function () {
    Notification::fake();

    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');

    NotificationService::notify(
        roles: ['Developer', 'Owner'],
        title: 'Push Title',
        body: 'Push Body.',
        url: '/push'
    );

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($owner, WebPushNotification::class);
});

test('NotificationService includes additionalUser when not already in role-based list', function () {
    $kasir = notifUserWithRole('Kasir');
    $developer = notifUserWithRole('Developer');

    NotificationService::notify(
        roles: ['Developer'],
        title: 'Title',
        body: 'Body.',
        url: '/url',
        additionalUser: $kasir
    );

    expect($kasir->notifications()->count())->toBe(1);
    expect($developer->notifications()->count())->toBe(1);
});

test('NotificationService does not duplicate additionalUser already in role list', function () {
    $developer = notifUserWithRole('Developer');

    NotificationService::notify(
        roles: ['Developer'],
        title: 'Title',
        body: 'Body.',
        url: '/url',
        additionalUser: $developer
    );

    expect($developer->notifications()->count())->toBe(1);
});

test('NotificationService handles null additionalUser', function () {
    $developer = notifUserWithRole('Developer');

    NotificationService::notify(
        roles: ['Developer'],
        title: 'Title',
        body: 'Body.',
        url: '/url',
        additionalUser: null
    );

    expect($developer->notifications()->count())->toBe(1);
});

test('NotificationService notifies multiple users across multiple roles', function () {
    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');
    $direktur = notifUserWithRole('Direktur');
    $adminToko = notifUserWithRole('Admin Toko');
    notifUserWithRole('Kasir'); // should NOT receive

    NotificationService::notify(
        roles: ['Owner', 'Developer', 'Direktur', 'Admin Toko'],
        title: 'Multi Role',
        body: 'Body.',
        url: '/multi'
    );

    expect($developer->notifications()->count())->toBe(1);
    expect($owner->notifications()->count())->toBe(1);
    expect($direktur->notifications()->count())->toBe(1);
    expect($adminToko->notifications()->count())->toBe(1);
});

/*
|--------------------------------------------------------------------------
| PRODUCT NOTIFICATIONS
|--------------------------------------------------------------------------
*/

test('ProductService create sends notification to correct roles', function () {
    Notification::fake();

    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');
    $kasir = notifUserWithRole('Kasir');

    $this->actingAs($developer);

    $service = new ProductService;
    $product = $service->create([
        'name' => 'Test Product',
        'description' => 'A test product',
        'status' => 'active',
        'category_ids' => [],
        'use_same_price' => false,
        'variants' => [
            [
                'name' => 'Default',
                'stock' => 10,
                'reject_stock' => 0,
                'retail_stock' => 5,
                'prices' => [
                    ['type' => 'retail', 'price' => 50000],
                ],
            ],
        ],
    ]);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($owner, WebPushNotification::class);
    Notification::assertNothingSentTo($kasir);

    expect($developer->notifications()->count())->toBe(1);
    expect($developer->notifications()->first()->title)->toBe('Produk Baru');
});

test('ProductService update sends notification to correct roles', function () {
    Notification::fake();

    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');
    $adminToko = notifUserWithRole('Admin Toko');

    $this->actingAs($developer);

    $service = new ProductService;
    $product = $service->create([
        'name' => 'Original Product',
        'description' => 'Desc',
        'status' => 'active',
        'category_ids' => [],
        'use_same_price' => false,
        'variants' => [
            [
                'name' => 'Var 1',
                'stock' => 10,
                'reject_stock' => 0,
                'retail_stock' => 5,
                'prices' => [
                    ['type' => 'retail', 'price' => 50000],
                ],
            ],
        ],
    ]);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($owner, WebPushNotification::class);

    Notification::fake();

    $product = $service->update($product, [
        'name' => 'Updated Product',
        'description' => 'Desc updated',
        'status' => 'active',
        'category_ids' => [],
        'use_same_price' => false,
        'variants' => [
            [
                'id' => $product->productVariants->first()->id,
                'name' => 'Var 1',
                'stock' => 20,
                'reject_stock' => 0,
                'retail_stock' => 10,
                'prices' => [
                    ['type' => 'retail', 'price' => 60000],
                ],
            ],
        ],
    ]);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($owner, WebPushNotification::class);
    Notification::assertSentTo($adminToko, WebPushNotification::class);
});

/*
|--------------------------------------------------------------------------
| CASH ACCOUNT NOTIFICATIONS
|--------------------------------------------------------------------------
*/

test('CashTransactionService deposit sends notification to correct roles', function () {
    Notification::fake();

    $cashAccount = CashAccount::factory()->create(['balance' => 1000000]);
    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');
    $kasir = notifUserWithRole('Kasir');

    $this->actingAs($developer);

    $service = new CashTransactionService;
    $service->deposit([
        'amount' => 500000,
        'description' => 'Setoran modal',
    ]);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($owner, WebPushNotification::class);
    Notification::assertNothingSentTo($kasir);

    expect($developer->notifications()->first()->title)->toBe('Setoran Kas Toko');
});

test('CashTransactionService withdrawal sends notification to correct roles', function () {
    Notification::fake();

    $cashAccount = CashAccount::factory()->create(['balance' => 1000000]);
    $developer = notifUserWithRole('Developer');
    $direktur = notifUserWithRole('Direktur');

    $this->actingAs($developer);

    $service = new CashTransactionService;
    $service->withdrawal([
        'amount' => 200000,
        'description' => 'Penarikan kas',
    ]);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($direktur, WebPushNotification::class);

    expect($developer->notifications()->first()->title)->toBe('Penarikan Kas Toko');
});

test('CashTransactionService update sends notification to correct roles', function () {
    Notification::fake();

    $cashAccount = CashAccount::factory()->create(['balance' => 1000000]);
    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');

    $this->actingAs($developer);

    $service = new CashTransactionService;
    $transaction = $service->deposit([
        'amount' => 500000,
        'description' => 'Initial deposit',
    ]);

    Notification::fake();

    $service->update($transaction, [
        'amount' => 600000,
        'description' => 'Updated deposit',
    ]);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($owner, WebPushNotification::class);

    expect($developer->notifications()->where('title', 'Transaksi Kas Diperbarui')->count())->toBe(1);
});

test('CashTransactionService destroy sends notification to correct roles', function () {
    Notification::fake();

    $cashAccount = CashAccount::factory()->create(['balance' => 1000000]);
    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');

    $this->actingAs($developer);

    $service = new CashTransactionService;
    $transaction = $service->deposit([
        'amount' => 500000,
        'description' => 'To be deleted',
    ]);

    Notification::fake();

    $service->destroy($transaction);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($owner, WebPushNotification::class);

    expect($developer->notifications()->where('title', 'Transaksi Kas Dihapus')->count())->toBe(1);
});

/*
|--------------------------------------------------------------------------
| EXPENSE NOTIFICATIONS
|--------------------------------------------------------------------------
*/

test('ExpenseService create sends notification to correct roles', function () {
    Notification::fake();

    CashAccount::factory()->create(['balance' => 5000000]);
    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');
    $kasir = notifUserWithRole('Kasir');

    $this->actingAs($developer);

    $service = new ExpenseService;
    $expense = $service->create([
        'amount' => 100000,
        'description' => 'Office supplies',
    ]);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($owner, WebPushNotification::class);
    Notification::assertNothingSentTo($kasir);

    expect($developer->notifications()->first()->title)->toBe('Pengeluaran Baru');
});

test('ExpenseService update sends notification to correct roles', function () {
    Notification::fake();

    CashAccount::factory()->create(['balance' => 5000000]);
    $developer = notifUserWithRole('Developer');
    $adminToko = notifUserWithRole('Admin Toko');

    $this->actingAs($developer);

    $service = new ExpenseService;
    $expense = $service->create([
        'amount' => 100000,
        'description' => 'Original',
    ]);

    Notification::fake();

    $service->update($expense, [
        'amount' => 150000,
        'description' => 'Updated expense',
    ]);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($adminToko, WebPushNotification::class);

    expect($developer->notifications()->where('title', 'Pengeluaran Diperbarui')->count())->toBe(1);
});

test('ExpenseService delete sends notification to correct roles', function () {
    Notification::fake();

    CashAccount::factory()->create(['balance' => 5000000]);
    $developer = notifUserWithRole('Developer');
    $direktur = notifUserWithRole('Direktur');

    $this->actingAs($developer);

    $service = new ExpenseService;
    $expense = $service->create([
        'amount' => 100000,
        'description' => 'To delete',
    ]);

    Notification::fake();

    $service->delete($expense);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($direktur, WebPushNotification::class);

    expect($developer->notifications()->where('title', 'Pengeluaran Dihapus')->count())->toBe(1);
});

/*
|--------------------------------------------------------------------------
| EMPLOYEE ADVANCE (KASBON) NOTIFICATIONS
|--------------------------------------------------------------------------
*/

test('EmployeeAdvanceService create sends notification including the requesting employee', function () {
    Notification::fake();

    CashAccount::factory()->create(['balance' => 5000000]);
    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');
    $kasbonData = notifEmployeeWithRole('Kasir');
    $employee = $kasbonData['employee'];
    $kasbonUser = $kasbonData['user'];

    $this->actingAs($kasbonUser);

    $service = new EmployeeAdvanceService;
    $advance = $service->create([
        'amount' => 500000,
        'description' => 'Emergency need',
        'due_date' => now()->addDays(30)->toDateString(),
    ]);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($owner, WebPushNotification::class);
    Notification::assertSentTo($kasbonUser, WebPushNotification::class);

    expect($kasbonUser->notifications()->first()->title)->toBe('Kasbon Baru');
});

test('EmployeeAdvanceService approve sends notification including the employee', function () {
    Notification::fake();

    CashAccount::factory()->create(['balance' => 5000000]);
    $developer = notifUserWithRole('Developer');
    $kasbonData = notifEmployeeWithRole('Kasir');
    $employee = $kasbonData['employee'];
    $kasbonUser = $kasbonData['user'];

    $this->actingAs($kasbonUser);

    $service = new EmployeeAdvanceService;
    $advance = $service->create([
        'amount' => 300000,
        'description' => 'Advance',
        'due_date' => now()->addDays(14)->toDateString(),
    ]);

    Notification::fake();

    $admin = notifUserWithRole('Admin Toko');
    $this->actingAs($admin);

    $service->approve($advance);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($kasbonUser, WebPushNotification::class);

    expect($kasbonUser->notifications()->where('title', 'Kasbon Dikeluarkan')->count())->toBe(1);
});

test('EmployeeAdvanceService pay sends notification including the employee', function () {
    Notification::fake();

    CashAccount::factory()->create(['balance' => 5000000]);
    $developer = notifUserWithRole('Developer');
    $kasbonData = notifEmployeeWithRole('Kasir');
    $employee = $kasbonData['employee'];
    $kasbonUser = $kasbonData['user'];

    $this->actingAs($kasbonUser);

    $service = new EmployeeAdvanceService;
    $advance = $service->create([
        'amount' => 200000,
        'description' => 'To pay',
        'due_date' => now()->addDays(7)->toDateString(),
    ]);

    $admin = notifUserWithRole('Admin Toko');
    $this->actingAs($admin);

    $service->approve($advance);

    Notification::fake();

    $service->pay($advance);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($kasbonUser, WebPushNotification::class);

    expect($kasbonUser->notifications()->where('title', 'Kasbon Dikembalikan')->count())->toBe(1);
});

/*
|--------------------------------------------------------------------------
| PAYROLL NOTIFICATIONS
|--------------------------------------------------------------------------
*/

test('PayrollPeriodService pay sends notification including the employee', function () {
    Notification::fake();

    CashAccount::factory()->create(['balance' => 50000000]);
    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');
    $employeeData = notifEmployeeWithRole('Kasir');
    $employee = $employeeData['employee'];
    $employeeUser = $employeeData['user'];

    $period = PayrollPeriod::factory()->create(['year' => 2026, 'month' => 7, 'status' => 'open']);
    $payroll = Payroll::factory()->create([
        'payroll_period_id' => $period->id,
        'employee_id' => $employee->id,
        'base_salary' => 3000000,
        'bonus_amount' => 0,
        'deduction_amount' => 0,
        'total_amount' => 3000000,
        'status' => 'unpaid',
    ]);

    $this->actingAs($developer);

    $service = new PayrollPeriodService;
    $service->pay($payroll);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($owner, WebPushNotification::class);
    Notification::assertSentTo($employeeUser, WebPushNotification::class);

    expect($employeeUser->notifications()->where('title', 'Gaji Dibayar')->count())->toBe(1);
});

test('PayrollPeriodService cancel sends notification including the employee', function () {
    Notification::fake();

    $developer = notifUserWithRole('Developer');
    $direktur = notifUserWithRole('Direktur');
    $employeeData = notifEmployeeWithRole('Kasir');
    $employee = $employeeData['employee'];
    $employeeUser = $employeeData['user'];

    $period = PayrollPeriod::factory()->create(['year' => 2026, 'month' => 8, 'status' => 'open']);
    $payroll = Payroll::factory()->create([
        'payroll_period_id' => $period->id,
        'employee_id' => $employee->id,
        'base_salary' => 3000000,
        'bonus_amount' => 0,
        'deduction_amount' => 0,
        'total_amount' => 3000000,
        'status' => 'unpaid',
    ]);

    $this->actingAs($developer);

    $service = new PayrollPeriodService;
    $service->cancel($payroll);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($direktur, WebPushNotification::class);
    Notification::assertSentTo($employeeUser, WebPushNotification::class);

    expect($employeeUser->notifications()->where('title', 'Gaji Dibatalkan')->count())->toBe(1);
});

/*
|--------------------------------------------------------------------------
| LEAVE REQUEST NOTIFICATIONS
|--------------------------------------------------------------------------
*/

test('LeaveRequestService create sends notification including the requesting employee', function () {
    Notification::fake();

    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');
    $leaveData = notifEmployeeWithRole('Kasir');
    $employee = $leaveData['employee'];
    $leaveUser = $leaveData['user'];

    $this->actingAs($leaveUser);

    $service = new LeaveRequestService;
    $leaveRequest = $service->create([
        'start_date' => now()->addDays(5)->toDateString(),
        'end_date' => now()->addDays(7)->toDateString(),
    ]);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($owner, WebPushNotification::class);
    Notification::assertSentTo($leaveUser, WebPushNotification::class);

    expect($leaveUser->notifications()->first()->title)->toBe('Pengajuan Cuti Baru');
});

test('LeaveRequestService approve sends notification including the employee', function () {
    Notification::fake();

    $developer = notifUserWithRole('Developer');
    $leaveData = notifEmployeeWithRole('Kasir');
    $employee = $leaveData['employee'];
    $leaveUser = $leaveData['user'];

    $this->actingAs($leaveUser);

    $service = new LeaveRequestService;
    $leaveRequest = $service->create([
        'start_date' => now()->addDays(10)->toDateString(),
        'end_date' => now()->addDays(12)->toDateString(),
    ]);

    Notification::fake();

    $admin = notifUserWithRole('Admin Toko');
    $this->actingAs($admin);

    $service->approve($leaveRequest);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($leaveUser, WebPushNotification::class);

    expect($leaveUser->notifications()->where('title', 'Cuti Disetujui')->count())->toBe(1);
});

test('LeaveRequestService reject sends notification including the employee', function () {
    Notification::fake();

    $developer = notifUserWithRole('Developer');
    $leaveData = notifEmployeeWithRole('Kasir');
    $employee = $leaveData['employee'];
    $leaveUser = $leaveData['user'];

    $this->actingAs($leaveUser);

    $service = new LeaveRequestService;
    $leaveRequest = $service->create([
        'start_date' => now()->addDays(15)->toDateString(),
        'end_date' => now()->addDays(17)->toDateString(),
    ]);

    Notification::fake();

    $admin = notifUserWithRole('Admin Toko');
    $this->actingAs($admin);

    $service->reject($leaveRequest);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($leaveUser, WebPushNotification::class);

    expect($leaveUser->notifications()->where('title', 'Cuti Ditolak')->count())->toBe(1);
});

/*
|--------------------------------------------------------------------------
| ATTENDANCE NOTIFICATIONS
|--------------------------------------------------------------------------
*/

test('AttendanceService checkIn sends notification to Developer, Owner, Direktur', function () {
    Notification::fake();

    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');
    $direktur = notifUserWithRole('Direktur');
    $adminToko = notifUserWithRole('Admin Toko');

    $attData = notifEmployeeWithRole('Kasir');
    $employee = $attData['employee'];
    $attendant = $attData['user'];

    $this->actingAs($attendant);

    $service = new AttendanceService;
    $attendance = $service->checkIn([
        'latitude' => -6.200000,
        'longitude' => 106.816666,
    ]);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($owner, WebPushNotification::class);
    Notification::assertSentTo($direktur, WebPushNotification::class);
    Notification::assertNothingSentTo($adminToko);

    expect($developer->notifications()->first()->title)->toBe('Presensi Masuk');
});

test('AttendanceService checkOut sends notification to Developer, Owner, Direktur', function () {
    Notification::fake();

    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');
    $direktur = notifUserWithRole('Direktur');
    $adminToko = notifUserWithRole('Admin Toko');

    $attData = notifEmployeeWithRole('Kasir');
    $employee = $attData['employee'];
    $attendant = $attData['user'];

    $this->actingAs($attendant);

    $service = new AttendanceService;
    $attendance = $service->checkIn([
        'latitude' => -6.200000,
        'longitude' => 106.816666,
    ]);

    Notification::fake();

    $attendance = $service->checkOut($attendance, [
        'latitude' => -6.200100,
        'longitude' => 106.816700,
    ]);

    Notification::assertSentTo($developer, WebPushNotification::class);
    Notification::assertSentTo($owner, WebPushNotification::class);
    Notification::assertSentTo($direktur, WebPushNotification::class);
    Notification::assertNothingSentTo($adminToko);

    expect($developer->notifications()->where('title', 'Presensi Pulang')->count())->toBe(1);
});

/*
|--------------------------------------------------------------------------
| IN-APP NOTIFICATION RECORDS
|--------------------------------------------------------------------------
*/

test('services create in-app notification records in database', function () {
    $developer = notifUserWithRole('Developer');
    $owner = notifUserWithRole('Owner');

    NotificationService::notify(
        roles: ['Developer', 'Owner'],
        title: 'DB Test',
        body: 'Body here.',
        url: '/db-test'
    );

    $this->assertDatabaseHas('notifications', [
        'user_id' => $developer->id,
        'title' => 'DB Test',
        'body' => 'Body here.',
        'url' => '/db-test',
        'is_read' => false,
    ]);

    $this->assertDatabaseHas('notifications', [
        'user_id' => $owner->id,
        'title' => 'DB Test',
    ]);
});

test('ProductService create creates in-app notification record', function () {
    CashAccount::factory()->create(['balance' => 1000000]);
    $developer = notifUserWithRole('Developer');

    $this->actingAs($developer);

    $service = new ProductService;
    $product = $service->create([
        'name' => 'DB Notification Product',
        'description' => 'Test',
        'status' => 'active',
        'category_ids' => [],
        'use_same_price' => false,
        'variants' => [
            [
                'name' => 'Var',
                'stock' => 10,
                'reject_stock' => 0,
                'retail_stock' => 5,
                'prices' => [
                    ['type' => 'retail', 'price' => 50000],
                ],
            ],
        ],
    ]);

    $this->assertDatabaseHas('notifications', [
        'user_id' => $developer->id,
        'title' => 'Produk Baru',
    ]);
});

test('CashTransactionService deposit creates in-app notification record', function () {
    CashAccount::factory()->create(['balance' => 5000000]);
    $owner = notifUserWithRole('Owner');

    $this->actingAs($owner);

    $service = new CashTransactionService;
    $service->deposit([
        'amount' => 250000,
        'description' => 'Test deposit',
    ]);

    $this->assertDatabaseHas('notifications', [
        'user_id' => $owner->id,
        'title' => 'Setoran Kas Toko',
    ]);
});

test('AttendanceService checkIn creates in-app notification record', function () {
    $developer = notifUserWithRole('Developer');
    $attData = notifEmployeeWithRole('Kasir');
    $employee = $attData['employee'];
    $attendant = $attData['user'];

    $this->actingAs($attendant);

    $service = new AttendanceService;
    $service->checkIn([
        'latitude' => -6.2,
        'longitude' => 106.8,
    ]);

    $this->assertDatabaseHas('notifications', [
        'user_id' => $developer->id,
        'title' => 'Presensi Masuk',
    ]);
});
