<?php

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

/**
 * The data-processing agreement, and the proof that a customer has it.
 *
 * Art. 28(3) GDPR requires one wherever personal data is processed on somebody
 * else's behalf, which is the whole of what this product does. "In writing"
 * there explicitly includes electronic form, so a document the customer can read
 * and a recorded acceptance is enough — a signature on paper is not required.
 *
 * Two tables, because they answer two different questions:
 *
 *  - `dpa_versions` is the DOCUMENT. The operator uploads it (the text is a
 *    lawyer's, not this application's), gives it a version, and publishes. The
 *    technical and organisational measures are a second file rather than a
 *    second concept: they are an annex to the agreement and are versioned with
 *    it, so "which TOMs applied when they accepted" has one answer.
 *  - `dpa_acceptances` is the EVIDENCE: which customer accepted which version,
 *    when, from where, and which login did it. One row per acceptance and never
 *    an update — a new version is a new row, and the history is the point.
 *
 * The file lives on the private disk. An agreement is not a public asset, and a
 * guessable URL to it would be a list of who our customers are.
 */
return new class extends Migration
{
    public function up(): void
    {
        Schema::create('dpa_versions', function (Blueprint $table) {
            $table->id();
            $table->uuid()->unique();
            // What the operator calls it — "1.0", "2026-08", whatever the
            // document itself says. Unique, because two documents with one name
            // makes every acceptance ambiguous.
            $table->string('version', 64)->unique();
            $table->string('agreement_path');
            $table->string('measures_path')->nullable();
            $table->text('note')->nullable();
            // Null while it is being prepared. Only a published version is
            // shown to anybody, and only the newest published one is current.
            $table->timestamp('published_at')->nullable();
            $table->foreignId('created_by')->nullable()->constrained('operators')->nullOnDelete();
            $table->timestamps();

            $table->index('published_at');
        });

        Schema::create('dpa_acceptances', function (Blueprint $table) {
            $table->id();
            $table->uuid()->unique();
            $table->foreignId('customer_id')->constrained('customers')->cascadeOnDelete();
            $table->foreignId('dpa_version_id')->constrained('dpa_versions')->cascadeOnDelete();
            // The login that pressed it, kept as evidence even when that user is
            // later removed — the acceptance was still made.
            $table->foreignId('user_id')->nullable()->constrained('users')->nullOnDelete();
            $table->string('ip', 45)->nullable();
            $table->timestamp('accepted_at');
            $table->timestamps();

            // One acceptance per customer per version. Pressing twice is not two
            // agreements, and the unique index is what makes that true rather
            // than a check somebody can forget.
            $table->unique(['customer_id', 'dpa_version_id']);
        });
    }

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