<?php

use App\Models\AdminLog;
use App\Models\User;
use Livewire\Volt\Volt;

beforeEach(function () {
    $this->admin = User::factory()->admin()->create();
});

// ===========================================
// Authentication Tests
// ===========================================

test('audit log page requires admin authentication', function () {
    $this->get(route('admin.audit-logs'))
        ->assertRedirect(route('login'));
});

test('client cannot access audit logs page', function () {
    $client = User::factory()->individual()->create();

    $this->actingAs($client)
        ->get(route('admin.audit-logs'))
        ->assertForbidden();
});

test('audit log page loads for admin', function () {
    $this->actingAs($this->admin)
        ->get(route('admin.audit-logs'))
        ->assertOk()
        ->assertSeeLivewire('admin.audit-logs');
});

// ===========================================
// Display Tests
// ===========================================

test('audit logs display in table', function () {
    AdminLog::factory()->count(5)->create();

    $this->actingAs($this->admin);

    Volt::test('admin.audit-logs')
        ->assertSee(__('audit.timestamp'))
        ->assertSee(__('audit.admin'))
        ->assertSee(__('audit.action'));
});

test('displays empty state when no logs exist', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.audit-logs')
        ->assertSee(__('audit.no_logs_found'));
});

test('pagination works correctly with 25 items per page', function () {
    AdminLog::factory()->count(50)->create();

    $this->actingAs($this->admin);

    Volt::test('admin.audit-logs')
        ->assertViewHas('logs', fn ($logs) => $logs->count() === 25);
});

test('logs are sorted by created_at descending', function () {
    $oldLog = AdminLog::factory()->create(['created_at' => now()->subDays(5)]);
    $newLog = AdminLog::factory()->create(['created_at' => now()]);

    $this->actingAs($this->admin);

    $component = Volt::test('admin.audit-logs');

    $logs = $component->viewData('logs');
    expect($logs->first()->id)->toBe($newLog->id);
});

test('displays system for logs without admin', function () {
    AdminLog::factory()->create(['admin_id' => null]);

    $this->actingAs($this->admin);

    Volt::test('admin.audit-logs')
        ->assertSee(__('audit.system'));
});

// ===========================================
// Filter Tests
// ===========================================

test('can filter by action type', function () {
    AdminLog::factory()->create(['action' => 'create']);
    AdminLog::factory()->create(['action' => 'delete']);

    $this->actingAs($this->admin);

    Volt::test('admin.audit-logs')
        ->set('actionFilter', 'create')
        ->assertViewHas('logs', fn ($logs) => $logs->every(fn ($log) => $log->action === 'create'));
});

test('can filter by target type', function () {
    AdminLog::factory()->create(['target_type' => 'user']);
    AdminLog::factory()->create(['target_type' => 'consultation']);

    $this->actingAs($this->admin);

    Volt::test('admin.audit-logs')
        ->set('targetFilter', 'user')
        ->assertViewHas('logs', fn ($logs) => $logs->every(fn ($log) => $log->target_type === 'user'));
});

test('can filter by date range', function () {
    AdminLog::factory()->create(['created_at' => now()->subDays(10)]);
    AdminLog::factory()->create(['created_at' => now()]);

    $this->actingAs($this->admin);

    Volt::test('admin.audit-logs')
        ->set('dateFrom', now()->subDays(5)->format('Y-m-d'))
        ->set('dateTo', now()->format('Y-m-d'))
        ->assertViewHas('logs', fn ($logs) => $logs->count() === 1);
});

test('can search by target id', function () {
    AdminLog::factory()->create(['target_id' => 123]);
    AdminLog::factory()->create(['target_id' => 456]);

    $this->actingAs($this->admin);

    Volt::test('admin.audit-logs')
        ->set('search', '123')
        ->assertViewHas('logs', fn ($logs) => $logs->count() === 1 && $logs->first()->target_id === 123);
});

test('reset filters clears all filters', function () {
    $this->actingAs($this->admin);

    Volt::test('admin.audit-logs')
        ->set('actionFilter', 'create')
        ->set('targetFilter', 'user')
        ->set('dateFrom', '2024-01-01')
        ->set('dateTo', '2024-12-31')
        ->set('search', '123')
        ->call('resetFilters')
        ->assertSet('actionFilter', '')
        ->assertSet('targetFilter', '')
        ->assertSet('dateFrom', '')
        ->assertSet('dateTo', '')
        ->assertSet('search', '');
});

test('filters reset pagination', function () {
    AdminLog::factory()->count(30)->create(['action' => 'create']);
    AdminLog::factory()->count(30)->create(['action' => 'delete']);

    $this->actingAs($this->admin);

    $component = Volt::test('admin.audit-logs')
        ->call('gotoPage', 2)
        ->set('actionFilter', 'create');

    // After setting filter, should be back to page 1
    $logs = $component->viewData('logs');
    expect($logs->currentPage())->toBe(1);
});

test('displays empty state when filters return no results', function () {
    AdminLog::factory()->create(['action' => 'create']);

    $this->actingAs($this->admin);

    Volt::test('admin.audit-logs')
        ->set('actionFilter', 'delete')
        ->assertSee(__('audit.no_results'));
});

// ===========================================
// Modal Tests
// ===========================================

test('can view log details in modal', function () {
    $log = AdminLog::factory()->create([
        'old_values' => ['name' => 'Old Name'],
        'new_values' => ['name' => 'New Name'],
    ]);

    $this->actingAs($this->admin);

    Volt::test('admin.audit-logs')
        ->call('showDetails', $log->id)
        ->assertSet('selectedLogId', $log->id)
        ->assertDispatched('open-modal', name: 'log-details');
});

test('selected log is loaded with admin relation', function () {
    $log = AdminLog::factory()->create();

    $this->actingAs($this->admin);

    $component = Volt::test('admin.audit-logs')
        ->call('showDetails', $log->id);

    $selectedLog = $component->viewData('selectedLog');
    expect($selectedLog)->not->toBeNull();
    expect($selectedLog->id)->toBe($log->id);
});

test('modal displays old and new values', function () {
    $log = AdminLog::factory()->create([
        'old_values' => ['status' => 'pending'],
        'new_values' => ['status' => 'approved'],
    ]);

    $this->actingAs($this->admin);

    $component = Volt::test('admin.audit-logs')
        ->call('showDetails', $log->id);

    $selectedLog = $component->viewData('selectedLog');
    expect($selectedLog->old_values)->toBe(['status' => 'pending']);
    expect($selectedLog->new_values)->toBe(['status' => 'approved']);
});

test('can close modal', function () {
    $log = AdminLog::factory()->create();

    $this->actingAs($this->admin);

    Volt::test('admin.audit-logs')
        ->call('showDetails', $log->id)
        ->assertSet('selectedLogId', $log->id)
        ->call('closeModal')
        ->assertSet('selectedLogId', null)
        ->assertDispatched('close-modal', name: 'log-details');
});

// ===========================================
// CSV Export Tests
// ===========================================

test('can export filtered logs to csv', function () {
    AdminLog::factory()->count(3)->create();

    $this->actingAs($this->admin);

    Volt::test('admin.audit-logs')
        ->call('exportCsv')
        ->assertFileDownloaded();
});

test('csv export respects filters', function () {
    AdminLog::factory()->count(3)->create(['action' => 'create']);
    AdminLog::factory()->count(2)->create(['action' => 'delete']);

    $this->actingAs($this->admin);

    // Set filter before export
    $component = Volt::test('admin.audit-logs')
        ->set('actionFilter', 'create');

    // Export is tested by checking it doesn't error and downloads
    $component->call('exportCsv')
        ->assertFileDownloaded();
});

test('csv filename includes current date', function () {
    AdminLog::factory()->create();

    $this->actingAs($this->admin);

    $response = Volt::test('admin.audit-logs')
        ->call('exportCsv');

    // The response should be a StreamedResponse
    $response->assertFileDownloaded('audit-log-'.now()->format('Y-m-d').'.csv');
});

// ===========================================
// Action Types and Target Types
// ===========================================

test('action types are populated from database', function () {
    AdminLog::factory()->create(['action' => 'create']);
    AdminLog::factory()->create(['action' => 'update']);
    AdminLog::factory()->create(['action' => 'delete']);

    $this->actingAs($this->admin);

    $component = Volt::test('admin.audit-logs');

    $actionTypes = $component->viewData('actionTypes');
    expect($actionTypes)->toContain('create', 'update', 'delete');
});

test('target types are populated from database', function () {
    AdminLog::factory()->create(['target_type' => 'user']);
    AdminLog::factory()->create(['target_type' => 'consultation']);

    $this->actingAs($this->admin);

    $component = Volt::test('admin.audit-logs');

    $targetTypes = $component->viewData('targetTypes');
    expect($targetTypes)->toContain('user', 'consultation');
});

// ===========================================
// Locale-specific Tests
// ===========================================

test('timestamp format changes based on locale', function () {
    $log = AdminLog::factory()->create(['created_at' => '2024-06-15 10:30:00']);

    $this->actingAs($this->admin);

    // English locale shows m/d/Y format
    app()->setLocale('en');
    Volt::test('admin.audit-logs')
        ->assertSee('06/15/2024');

    // Arabic locale shows d/m/Y format
    app()->setLocale('ar');
    Volt::test('admin.audit-logs')
        ->assertSee('15/06/2024');
});
