<?php

declare(strict_types=1);

use App\Models\PasswordHistory;
use App\Models\Permission;
use App\Models\Role;
use App\Models\User;
use App\Models\UserConsent;
use App\Models\UserTrustedDevice;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;

test('force deleting a user cascades password_histories', function () {
    $user = User::factory()->create();
    PasswordHistory::create(['user_id' => $user->id, 'password' => Hash::make('a')]);
    PasswordHistory::create(['user_id' => $user->id, 'password' => Hash::make('b')]);

    expect(PasswordHistory::where('user_id', $user->id)->count())->toBe(2);

    $user->forceDelete();

    expect(PasswordHistory::where('user_id', $user->id)->count())->toBe(0);
});

test('force deleting a user cascades user_consents', function () {
    $user = User::factory()->create();
    UserConsent::create([
        'user_id' => $user->id,
        'consent_type' => 'tos',
        'version_id' => 1,
        'ip_address' => '127.0.0.1',
    ]);

    expect(UserConsent::where('user_id', $user->id)->count())->toBe(1);

    $user->forceDelete();

    expect(UserConsent::where('user_id', $user->id)->count())->toBe(0);
});

test('force deleting a user cascades user_trusted_devices', function () {
    $user = User::factory()->create();
    UserTrustedDevice::create([
        'user_id' => $user->id,
        'device_id' => 'dev-1',
        'token' => 'tok',
        'expires_at' => now()->addDays(30),
    ]);

    $user->forceDelete();

    expect(UserTrustedDevice::where('user_id', $user->id)->count())->toBe(0);
});

test('force deleting a user nulls system_settings audit columns', function () {
    $actor = User::factory()->create();
    DB::table('system_settings')->insert([
        'key' => 'cascade_test',
        'value' => 'x',
        'type' => 'string',
        'group' => 'branding',
        'is_public' => false,
        'created_by' => $actor->id,
        'updated_by' => $actor->id,
        'created_at' => now(),
        'updated_at' => now(),
    ]);

    $actor->forceDelete();

    $row = DB::table('system_settings')->where('key', 'cascade_test')->first();
    expect($row->created_by)->toBeNull();
    expect($row->updated_by)->toBeNull();
});

test('force deleting a user nulls system_setting_revisions.changed_by', function () {
    $actor = User::factory()->create();
    $settingId = DB::table('system_settings')->insertGetId([
        'key' => 'cascade_test_2',
        'value' => 'x',
        'type' => 'string',
        'group' => 'branding',
        'is_public' => false,
        'created_at' => now(),
        'updated_at' => now(),
    ]);
    DB::table('system_setting_revisions')->insert([
        'system_setting_id' => $settingId,
        'key' => 'cascade_test_2',
        'old_value' => null,
        'new_value' => '"x"',
        'changed_by' => $actor->id,
        'created_at' => now(),
    ]);

    $actor->forceDelete();

    expect(DB::table('system_setting_revisions')->where('key', 'cascade_test_2')->value('changed_by'))
        ->toBeNull();
});

test('deleting a role removes role_has_permissions linkage', function () {
    $role = Role::create(['name' => 'cascade-role', 'guard_name' => 'web']);
    $perm = Permission::firstOrCreate(['name' => 'cascade-perm', 'guard_name' => 'web']);
    $role->givePermissionTo($perm);

    expect(DB::table('role_has_permissions')->where('role_id', $role->id)->count())->toBe(1);

    $role->forceDelete();

    expect(DB::table('role_has_permissions')->where('role_id', $role->id)->count())->toBe(0);
});

test('deleting a permission removes role_has_permissions linkage', function () {
    $role = Role::create(['name' => 'host-role', 'guard_name' => 'web']);
    $perm = Permission::firstOrCreate(['name' => 'doomed-perm', 'guard_name' => 'web']);
    $role->givePermissionTo($perm);

    $perm->forceDelete();

    expect(DB::table('role_has_permissions')->where('permission_id', $perm->id)->count())->toBe(0);
});

test('roles audit columns null out when the actor is force-deleted', function () {
    $actor = User::factory()->create();
    $role = Role::create(['name' => 'audit-role', 'guard_name' => 'web']);
    DB::table('roles')->where('id', $role->id)->update([
        'created_by' => $actor->id,
        'updated_by' => $actor->id,
    ]);

    $actor->forceDelete();

    $row = DB::table('roles')->where('id', $role->id)->first();
    expect($row->created_by)->toBeNull();
    expect($row->updated_by)->toBeNull();
});

test('soft-deleting a user keeps related rows intact', function () {
    $user = User::factory()->create();
    PasswordHistory::create(['user_id' => $user->id, 'password' => Hash::make('a')]);

    $user->delete(); // soft

    expect(User::withTrashed()->find($user->id)->trashed())->toBeTrue();
    expect(PasswordHistory::where('user_id', $user->id)->count())->toBe(1);
});
