<?php

declare(strict_types=1);

use App\Models\AI\AiUsageLog;
use App\Models\AiHealingLog;
use App\Models\MobileErrorLog;
use App\Models\MobileSyncLog;
use App\Models\Notification;
use App\Models\OtpCode;
use App\Models\PasswordHistory;
use App\Models\User;
use App\Models\UserTrustedDevice;
use Illuminate\Database\Eloquent\Builder;

// ── OtpCode ───────────────────────────────────────────────────────────────────

test('OtpCode prunable selects only expired records', function () {
    OtpCode::create(['identifier' => 'a@a.com', 'code' => '111111', 'expires_at' => now()->subMinute()]);
    OtpCode::create(['identifier' => 'b@b.com', 'code' => '222222', 'expires_at' => now()->addHour()]);

    $prunableIds = (new OtpCode)->prunable()->pluck('id');

    expect($prunableIds)->toHaveCount(1);
});

test('OtpCode prunable returns a Builder instance', function () {
    expect((new OtpCode)->prunable())->toBeInstanceOf(Builder::class);
});

// ── UserTrustedDevice ─────────────────────────────────────────────────────────

test('UserTrustedDevice prunable selects expired devices only', function () {
    $user = User::factory()->create();

    UserTrustedDevice::create([
        'user_id'    => $user->id,
        'device_id'  => 'old-device',
        'token'      => 'tok1',
        'expires_at' => now()->subDay(),
    ]);
    UserTrustedDevice::create([
        'user_id'    => $user->id,
        'device_id'  => 'fresh-device',
        'token'      => 'tok2',
        'expires_at' => now()->addDays(30),
    ]);

    $ids = (new UserTrustedDevice)->prunable()->pluck('id');

    expect($ids)->toHaveCount(1);
});

test('UserTrustedDevice prunable returns a Builder instance', function () {
    expect((new UserTrustedDevice)->prunable())->toBeInstanceOf(Builder::class);
});

// ── PasswordHistory ───────────────────────────────────────────────────────────

test('PasswordHistory prunable selects records older than 365 days', function () {
    $user = User::factory()->create();

    \DB::table('password_histories')->insert([
        ['user_id' => $user->id, 'password' => 'h1', 'created_at' => now()->subDays(400), 'updated_at' => now()],
        ['user_id' => $user->id, 'password' => 'h2', 'created_at' => now()->subDays(100), 'updated_at' => now()],
    ]);

    $ids = (new PasswordHistory)->prunable()->pluck('id');

    expect($ids)->toHaveCount(1);
});

test('PasswordHistory prunable returns a Builder instance', function () {
    expect((new PasswordHistory)->prunable())->toBeInstanceOf(Builder::class);
});

// ── MobileSyncLog ─────────────────────────────────────────────────────────────

test('MobileSyncLog prunable selects records older than 30 days', function () {
    \DB::table('mobile_sync_logs')->insert([
        ['synced_at' => now()->subDays(35)],
        ['synced_at' => now()->subDays(10)],
    ]);

    $ids = (new MobileSyncLog)->prunable()->pluck('id');

    expect($ids)->toHaveCount(1);
});

test('MobileSyncLog prunable returns a Builder instance', function () {
    expect((new MobileSyncLog)->prunable())->toBeInstanceOf(Builder::class);
});

// ── MobileErrorLog ────────────────────────────────────────────────────────────

test('MobileErrorLog prunable selects records older than 90 days', function () {
    \DB::table('mobile_error_logs')->insert([
        ['message' => 'old error', 'occurred_at' => now()->subDays(100)],
        ['message' => 'new error', 'occurred_at' => now()->subDays(5)],
    ]);

    $ids = (new MobileErrorLog)->prunable()->pluck('id');

    expect($ids)->toHaveCount(1);
});

test('MobileErrorLog prunable returns a Builder instance', function () {
    expect((new MobileErrorLog)->prunable())->toBeInstanceOf(Builder::class);
});

// ── Notification (system_notifications) ──────────────────────────────────────

test('Notification prunable selects records older than 30 days', function () {
    \DB::table('system_notifications')->insert([
        ['title' => 'old', 'message' => 'x', 'recipient' => 'all', 'type' => 'info', 'created_at' => now()->subDays(40), 'updated_at' => now()],
        ['title' => 'new', 'message' => 'y', 'recipient' => 'all', 'type' => 'info', 'created_at' => now()->subDays(5),  'updated_at' => now()],
    ]);

    $ids = (new Notification)->prunable()->pluck('id');

    expect($ids)->toHaveCount(1);
});

test('Notification prunable returns a Builder instance', function () {
    expect((new Notification)->prunable())->toBeInstanceOf(Builder::class);
});

// ── AiHealingLog ──────────────────────────────────────────────────────────────

test('AiHealingLog prunable selects records older than 90 days', function () {
    \DB::table('ai_healing_logs')->insert([
        ['error_message' => 'old', 'created_at' => now()->subDays(100), 'updated_at' => now()],
        ['error_message' => 'new', 'created_at' => now()->subDays(10),  'updated_at' => now()],
    ]);

    $ids = (new AiHealingLog)->prunable()->pluck('id');

    expect($ids)->toHaveCount(1);
});

test('AiHealingLog prunable returns a Builder instance', function () {
    expect((new AiHealingLog)->prunable())->toBeInstanceOf(Builder::class);
});

// ── AiUsageLog ────────────────────────────────────────────────────────────────

test('AiUsageLog prunable selects records older than 3 months', function () {
    \DB::table('ai_usage_logs')->insert([
        ['provider' => 'openai', 'model' => 'gpt-4', 'status' => 'success', 'created_at' => now()->subMonths(4), 'updated_at' => now()],
        ['provider' => 'openai', 'model' => 'gpt-4', 'status' => 'success', 'created_at' => now()->subWeek(),    'updated_at' => now()],
    ]);

    $ids = (new AiUsageLog)->prunable()->pluck('id');

    expect($ids)->toHaveCount(1);
});

// ── Edge cases ────────────────────────────────────────────────────────────────

test('OtpCode prunable returns empty when all codes are still valid', function () {
    OtpCode::create(['identifier' => 'c@c.com', 'code' => '333333', 'expires_at' => now()->addHour()]);

    $ids = (new OtpCode)->prunable()->pluck('id');

    expect($ids)->toBeEmpty();
});

test('UserTrustedDevice prunable returns empty when no devices are expired', function () {
    $user = User::factory()->create();
    UserTrustedDevice::create([
        'user_id'    => $user->id,
        'device_id'  => 'good-device',
        'token'      => 'tok3',
        'expires_at' => now()->addDays(7),
    ]);

    $ids = (new UserTrustedDevice)->prunable()->pluck('id');

    expect($ids)->toBeEmpty();
});
