<?php

use App\Models\Application;
use App\Models\AuthenticationToken;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

describe('AuthenticationToken Model', function () {
    
    it('can create an authentication token', function () {
        $user = User::factory()->create();
        $app = Application::factory()->create();
        
        $token = AuthenticationToken::create([
            'user_id' => $user->id,
            'application_id' => $app->id,
            'token' => 'test-token-123',
            'issued_at' => now(),
            'expires_at' => now()->addHour(),
            'ip' => '192.168.1.1',
            'user_agent' => 'Test Browser'
        ]);

        expect($token->user_id)->toBe($user->id);
        expect($token->application_id)->toBe($app->id);
        expect($token->token)->toBe('test-token-123');
        expect($token->ip)->toBe('192.168.1.1');
        expect($token->user_agent)->toBe('Test Browser');
    });

    it('belongs to a user', function () {
        $user = User::factory()->create();
        $app = Application::factory()->create();
        $token = AuthenticationToken::factory()->create([
            'user_id' => $user->id,
            'application_id' => $app->id
        ]);

        expect($token->user)->toBeInstanceOf(User::class);
        expect($token->user->id)->toBe($user->id);
    });

    it('belongs to an application', function () {
        $user = User::factory()->create();
        $app = Application::factory()->create();
        $token = AuthenticationToken::factory()->create([
            'user_id' => $user->id,
            'application_id' => $app->id
        ]);

        expect($token->application)->toBeInstanceOf(Application::class);
        expect($token->application->id)->toBe($app->id);
    });

    it('casts dates properly', function () {
        $user = User::factory()->create();
        $app = Application::factory()->create();
        $token = AuthenticationToken::factory()->create([
            'user_id' => $user->id,
            'application_id' => $app->id,
            'issued_at' => '2024-01-01 12:00:00',
            'expires_at' => '2024-01-01 13:00:00'
        ]);

        expect($token->issued_at)->toBeInstanceOf(\Illuminate\Support\Carbon::class);
        expect($token->expires_at)->toBeInstanceOf(\Illuminate\Support\Carbon::class);
    });

    it('guards only id field', function () {
        $token = new AuthenticationToken();
        
        // Uses guarded instead of fillable, so check guarded
        expect($token->getGuarded())->toBe(['id']);
        
        // Can mass assign other fields
        $token->fill([
            'user_id' => 1,
            'application_id' => 1,
            'token' => 'test-token',
            'ip' => '127.0.0.1'
        ]);
        
        expect($token->user_id)->toBe(1);
        expect($token->application_id)->toBe(1);
        expect($token->token)->toBe('test-token');
    });

    it('uses HasFactory trait', function () {
        expect(method_exists(AuthenticationToken::class, 'factory'))->toBe(true);
        expect(in_array('Illuminate\Database\Eloquent\Factories\HasFactory', class_uses(AuthenticationToken::class)))->toBe(true);
    });

    it('can be found by token', function () {
        $user = User::factory()->create();
        $app = Application::factory()->create();
        $token = AuthenticationToken::factory()->create([
            'user_id' => $user->id,
            'application_id' => $app->id,
            'token' => 'unique-token-123'
        ]);

        $found = AuthenticationToken::where('token', 'unique-token-123')->first();
        
        expect($found)->not()->toBeNull();
        expect($found->id)->toBe($token->id);
    });

    it('can filter by user', function () {
        $user1 = User::factory()->create();
        $user2 = User::factory()->create();
        $app = Application::factory()->create();
        
        $token1 = AuthenticationToken::factory()->create([
            'user_id' => $user1->id,
            'application_id' => $app->id
        ]);
        
        $token2 = AuthenticationToken::factory()->create([
            'user_id' => $user2->id,
            'application_id' => $app->id
        ]);

        $user1Tokens = AuthenticationToken::where('user_id', $user1->id)->get();
        
        expect($user1Tokens->count())->toBe(1);
        expect($user1Tokens->first()->id)->toBe($token1->id);
    });

    it('can be deleted', function () {
        $user = User::factory()->create();
        $app = Application::factory()->create();
        $token = AuthenticationToken::factory()->create([
            'user_id' => $user->id,
            'application_id' => $app->id
        ]);
        
        $id = $token->id;
        $token->delete();
        
        expect(AuthenticationToken::find($id))->toBeNull();
    });
});