<?php

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

/**
 * wa_messages — the durable record of every inbound and outbound message AND the
 * outbound work queue itself.
 *
 * Durability guarantee: an outbound message is persisted here with status
 * 'pending' BEFORE any queue job is dispatched. The job only flips it to 'sent'
 * after the provider confirms. If the channel is down, the row stays 'pending'
 * and is retried — so notifications are never lost across QR disconnects,
 * worker restarts or token failures.
 */
return new class extends Migration {
    public function up(): void
    {
        if (Schema::hasTable('wa_messages')) {
            return;
        }

        Schema::create('wa_messages', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedInteger('business_id')->index();
            $table->unsignedInteger('channel_id')->nullable()->index();
            $table->unsignedInteger('contact_id')->nullable();
            $table->string('wa_id', 30)->index()->comment('Other party E.164 (recipient for out, sender for in)');

            $table->enum('direction', ['out', 'in'])->default('out');
            $table->enum('type', ['text', 'template', 'image', 'document', 'audio', 'video', 'location', 'interactive'])
                  ->default('text');
            $table->unsignedInteger('template_id')->nullable();
            $table->text('body')->nullable();
            $table->json('payload')->nullable()->comment('Media url/path, template vars, buttons, raw provider payload');

            $table->enum('status', ['pending', 'queued', 'sent', 'delivered', 'read', 'failed', 'received'])
                  ->default('pending');
            $table->string('provider_message_id', 128)->nullable()->index();
            $table->text('error')->nullable();
            $table->unsignedInteger('attempts')->default(0);

            $table->string('source', 40)->nullable()->comment('invoice|reminder|manual|ai|...');
            $table->string('dedupe_key', 191)->nullable()->comment('Idempotency key for automated sends');

            $table->timestamp('available_at')->nullable()->comment('Throttle gate: not before this time');
            $table->timestamp('queued_at')->nullable();
            $table->timestamp('sent_at')->nullable();
            $table->timestamp('delivered_at')->nullable();
            $table->timestamp('read_at')->nullable();

            $table->unsignedInteger('created_by')->nullable();
            $table->timestamps();

            $table->index(['business_id', 'status']);
            $table->index(['channel_id', 'direction', 'status']);
            $table->unique(['business_id', 'dedupe_key']);
        });
    }

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