<?php

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

/**
 * What customers write to us, where it can be answered.
 *
 * The other half of `sent_mails`. Until now a customer who replied by mail
 * instead of using the portal form was invisible to this application: the
 * question sat in a mail client on somebody's desktop, the answer went out from
 * there, and the console — which knows who the customer is, what they bought
 * and what we already told them — knew nothing about any of it.
 *
 * A row is one message. `message_id` is the mail's own Message-ID and is
 * unique: the fetch runs every few minutes and must be able to run twice over
 * the same mailbox without producing two copies of the same question.
 *
 * `customer_id` is nullable ON PURPOSE. A mail from an address nobody
 * recognises is exactly the mail an operator must not miss — it is a new
 * enquiry, or a customer writing from their private address. Unassigned is a
 * state to work in, not an error to hide.
 *
 * ATTACHMENTS ARE NOT STORED. Only their names and sizes, so the operator knows
 * something was attached and can go and look in the mailbox if it matters.
 * Downloading and keeping every file an unknown sender attaches is a malware
 * store with a web interface in front of it, and this application has no reason
 * to be one.
 */
return new class extends Migration
{
    public function up(): void
    {
        Schema::create('inbound_mails', function (Blueprint $table) {
            $table->id();
            $table->uuid()->unique();

            // Who it belongs to, once we know. Null is the working state for
            // anything from an address we do not recognise.
            $table->foreignId('customer_id')->nullable()->constrained()->nullOnDelete();
            // The portal request this mail answers or became, where one exists.
            $table->foreignId('support_request_id')->nullable()->constrained()->nullOnDelete();

            $table->string('message_id')->unique();
            $table->string('from_email')->index();
            $table->string('from_name')->nullable();
            $table->string('subject')->nullable();
            $table->longText('body')->nullable();

            // Names and sizes only — never the files themselves.
            $table->json('attachments')->nullable();

            $table->timestamp('received_at')->index();
            // Read and archived are the operator's two states. Neither touches
            // the mailbox: the copy on the mail server is not ours to change,
            // and an application that deletes somebody's mail on their server
            // is an application nobody trusts with a password.
            $table->timestamp('read_at')->nullable();
            $table->timestamp('archived_at')->nullable();
            $table->timestamps();

            $table->index(['archived_at', 'received_at']);
        });
    }

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