<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    public function up(): void
    {
        /*
         | Append-only record of everything that happens.
         |
         | Only *changed* attributes are stored, not full row snapshots: full
         | snapshots would make this the largest table in the database within a
         | year, and the diff is what the UI renders.
         |
         | `description` is a pre-rendered human sentence. Reconstructing one at
         | read time would mean knowing every model's field labels forever,
         | including for models that later change; writing it once, while we
         | still have full context, keeps the log permanently readable.
         |
         | There is no `updated_at` and no `deleted_at`. Entries are never
         | modified or removed by the application; the retention pruner deletes
         | old rows wholesale and never touches custody events.
         */
        Schema::create('audit_logs', function (Blueprint $table): void {
            $table->id();

            // Null for console and system events.
            $table->foreignId('user_id')->nullable()->constrained('users')->nullOnDelete();

            $table->string('event', 40);

            // Null for authentication events, which describe no record.
            $table->string('auditable_type', 120)->nullable();
            $table->unsignedBigInteger('auditable_id')->nullable();

            $table->string('description', 255);

            $table->json('old_values')->nullable();
            $table->json('new_values')->nullable();

            $table->string('ip_address', 45)->nullable();
            $table->string('user_agent', 255)->nullable();
            $table->string('url', 255)->nullable();

            $table->timestamp('created_at')->nullable();

            // Per-record timeline on an asset or employee detail page.
            $table->index(['auditable_type', 'auditable_id']);

            // "What did this user do", and the audit log listing's default sort.
            $table->index(['user_id', 'created_at']);

            // Filtering by event type over a date range.
            $table->index(['event', 'created_at']);

            // Retention pruning.
            $table->index('created_at');
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('audit_logs');
    }
};
