<?php

namespace Tests\Property;

use Tests\PropertyTestCase;

/**
 * Authentication Property Tests
 * Tests universal properties of the authentication system
 */
class AuthenticationPropertyTest extends PropertyTestCase {
    
    /**
     * Feature: birthday-reminder-pwa, Property 1: Authentication grants access for valid credentials
     * 
     * For any valid username and password combination, when authentication is attempted,
     * the system should grant access and create a session.
     * 
     * Validates: Requirements 1.1
     * 
     * @test
     */
    public function testAuthenticationGrantsAccessForValidCredentials() {
        $this->runPropertyTest(function($iteration) {
            // Reset database for clean state
            resetTestDatabase();
            
            // Generate random valid credentials
            $username = 'user_' . randomString(8);
            $password = 'pass_' . randomString(10);
            $email = randomEmail();
            
            // Create user
            $userModel = new \User();
            $userId = $userModel->create([
                'username' => $username,
                'password' => $password,
                'email' => $email,
                'is_active' => 1
            ]);
            
            $this->assertNotFalse($userId, "User creation failed on iteration $iteration");
            
            // Attempt authentication with valid credentials
            $authenticatedUser = $userModel->authenticate($username, $password);
            
            // Assert authentication succeeded
            $this->assertNotFalse($authenticatedUser, "Authentication failed for valid credentials on iteration $iteration");
            $this->assertInstanceOf(\User::class, $authenticatedUser);
            $this->assertEquals($username, $authenticatedUser->username);
            
            // Assert session was created
            $this->assertTrue(isset($_SESSION['user_id']), "Session not created on iteration $iteration");
            $this->assertEquals($userId, $_SESSION['user_id']);
        });
    }
    
    /**
     * Feature: birthday-reminder-pwa, Property 3: Invalid credentials are rejected
     * 
     * For any invalid username or password combination, when authentication is attempted,
     * the system should reject access and return an error.
     * 
     * Validates: Requirements 1.3
     * 
     * @test
     */
    public function testInvalidCredentialsAreRejected() {
        $this->runPropertyTest(function($iteration) {
            // Reset database for clean state
            resetTestDatabase();
            
            // Create a valid user
            $validUsername = 'validuser_' . randomString(8);
            $validPassword = 'validpass_' . randomString(10);
            $email = randomEmail();
            
            $userModel = new \User();
            $userModel->create([
                'username' => $validUsername,
                'password' => $validPassword,
                'email' => $email,
                'is_active' => 1
            ]);
            
            // Test Case 1: Wrong password
            $wrongPassword = 'wrong_' . randomString(10);
            $result = $userModel->authenticate($validUsername, $wrongPassword);
            $this->assertFalse($result, "Authentication should fail with wrong password on iteration $iteration");
            
            // Test Case 2: Wrong username
            $wrongUsername = 'wrong_' . randomString(8);
            $result = $userModel->authenticate($wrongUsername, $validPassword);
            $this->assertFalse($result, "Authentication should fail with wrong username on iteration $iteration");
            
            // Test Case 3: Both wrong
            $result = $userModel->authenticate($wrongUsername, $wrongPassword);
            $this->assertFalse($result, "Authentication should fail with both wrong on iteration $iteration");
            
            // Test Case 4: Empty credentials
            $result = $userModel->authenticate('', '');
            $this->assertFalse($result, "Authentication should fail with empty credentials on iteration $iteration");
            
            // Assert no session was created
            $this->assertFalse(isset($_SESSION['user_id']), "Session should not be created for invalid credentials on iteration $iteration");
        });
    }
}
