<?php

use App\Models\Application;
use App\Models\User;
use App\Policies\ApplicationPolicy;
use App\Policies\UserPolicy;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

beforeEach(function () {
    $this->admin = User::factory()->create(['is_admin' => true]);
    $this->user = User::factory()->create(['is_admin' => false]);
    $this->otherUser = User::factory()->create(['is_admin' => false]);
});

describe('UserPolicy', function () {
    
    it('allows admins to view any users', function () {
        $policy = new UserPolicy();
        
        expect($policy->viewAny($this->admin))->toBe(true);
        expect($policy->viewAny($this->user))->toBe(false);
    });

    it('allows users to view their own profile and admins to view any user', function () {
        $policy = new UserPolicy();
        
        // Users can view their own profile
        expect($policy->view($this->user, $this->user))->toBe(true);
        expect($policy->view($this->user, $this->otherUser))->toBe(false);
        
        // Admins can view any user
        expect($policy->view($this->admin, $this->user))->toBe(true);
        expect($policy->view($this->admin, $this->otherUser))->toBe(true);
    });

    it('allows only admins to create users', function () {
        $policy = new UserPolicy();
        
        expect($policy->create($this->admin))->toBe(true);
        expect($policy->create($this->user))->toBe(false);
    });

    it('allows users to update their own profile and admins to update any user', function () {
        $policy = new UserPolicy();
        
        // Users can update their own profile
        expect($policy->update($this->user, $this->user))->toBe(true);
        expect($policy->update($this->user, $this->otherUser))->toBe(false);
        
        // Admins can update any user
        expect($policy->update($this->admin, $this->user))->toBe(true);
        expect($policy->update($this->admin, $this->otherUser))->toBe(true);
    });

    it('allows admins to delete users but not themselves', function () {
        $policy = new UserPolicy();
        
        // Admins can delete other users
        expect($policy->delete($this->admin, $this->user))->toBe(true);
        expect($policy->delete($this->admin, $this->otherUser))->toBe(true);
        
        // Admins cannot delete themselves
        expect($policy->delete($this->admin, $this->admin))->toBe(false);
        
        // Regular users cannot delete anyone
        expect($policy->delete($this->user, $this->otherUser))->toBe(false);
        expect($policy->delete($this->user, $this->user))->toBe(false);
    });

    it('allows only admins to restore users', function () {
        $policy = new UserPolicy();
        
        expect($policy->restore($this->admin, $this->user))->toBe(true);
        expect($policy->restore($this->user, $this->user))->toBe(false);
    });

    it('allows admins to force delete users but not themselves', function () {
        $policy = new UserPolicy();
        
        // Admins can force delete other users
        expect($policy->forceDelete($this->admin, $this->user))->toBe(true);
        expect($policy->forceDelete($this->admin, $this->otherUser))->toBe(true);
        
        // Admins cannot force delete themselves
        expect($policy->forceDelete($this->admin, $this->admin))->toBe(false);
        
        // Regular users cannot force delete anyone
        expect($policy->forceDelete($this->user, $this->otherUser))->toBe(false);
    });

    it('allows only admins to invite users', function () {
        $policy = new UserPolicy();
        
        expect($policy->invite($this->admin))->toBe(true);
        expect($policy->invite($this->user))->toBe(false);
    });
});

describe('ApplicationPolicy', function () {
    
    it('allows only admins to view any applications', function () {
        $policy = new ApplicationPolicy();
        
        expect($policy->viewAny($this->admin))->toBe(true);
        expect($policy->viewAny($this->user))->toBe(false);
    });

    it('allows only admins to view specific applications', function () {
        $policy = new ApplicationPolicy();
        $app = Application::factory()->create();
        
        expect($policy->view($this->admin, $app))->toBe(true);
        expect($policy->view($this->user, $app))->toBe(false);
    });

    it('allows only admins to create applications', function () {
        $policy = new ApplicationPolicy();
        
        expect($policy->create($this->admin))->toBe(true);
        expect($policy->create($this->user))->toBe(false);
    });

    it('allows only admins to update applications', function () {
        $policy = new ApplicationPolicy();
        $app = Application::factory()->create();
        
        expect($policy->update($this->admin, $app))->toBe(true);
        expect($policy->update($this->user, $app))->toBe(false);
    });

    it('allows only admins to delete applications', function () {
        $policy = new ApplicationPolicy();
        $app = Application::factory()->create();
        
        expect($policy->delete($this->admin, $app))->toBe(true);
        expect($policy->delete($this->user, $app))->toBe(false);
    });

    it('allows only admins to restore applications', function () {
        $policy = new ApplicationPolicy();
        $app = Application::factory()->create();
        
        expect($policy->restore($this->admin, $app))->toBe(true);
        expect($policy->restore($this->user, $app))->toBe(false);
    });

    it('allows only admins to force delete applications', function () {
        $policy = new ApplicationPolicy();
        $app = Application::factory()->create();
        
        expect($policy->forceDelete($this->admin, $app))->toBe(true);
        expect($policy->forceDelete($this->user, $app))->toBe(false);
    });
});