<?php

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

/**
 * Document management (§17, §17A).
 *
 * Documents belong to any owner — applicant, agent, employer, job demand — and
 * keep every version. A verified file is never overwritten silently.
 */
return new class extends Migration
{
    public function up(): void
    {
        Schema::create('document_types', function (Blueprint $table) {
            $table->id();
            $table->uuid('uuid')->unique();
            $table->foreignId('company_id')->constrained()->cascadeOnUpdate()->restrictOnDelete();
            $table->string('code', 60);
            $table->string('name');
            // Identity, photo, education, medical, visa, travel … (§17A).
            $table->string('category', 40);
            $table->text('description')->nullable();

            // Sensitive documents need a separate permission to download (§17.3).
            $table->boolean('is_sensitive')->default(false);
            $table->boolean('requires_number')->default(false);
            $table->boolean('requires_issue_date')->default(false);
            $table->boolean('requires_expiry_date')->default(false);
            // Expiry reminders in days before lapse, e.g. [90, 60, 30, 7].
            $table->json('reminder_days')->nullable();

            $table->json('allowed_mime_types')->nullable();
            $table->unsignedInteger('max_file_size_kb')->default(10240);
            $table->boolean('allows_multiple')->default(false);
            $table->boolean('is_active')->default(true);
            $table->unsignedSmallInteger('sort_order')->default(100);
            $table->timestamps();
            $table->softDeletes();

            $table->unique(['company_id', 'code']);
            $table->index(['company_id', 'category', 'is_active']);
        });

        Schema::create('documents', function (Blueprint $table) {
            $table->id();
            $table->uuid('uuid')->unique();
            $table->foreignId('company_id')->constrained()->cascadeOnUpdate()->restrictOnDelete();
            $table->foreignId('document_type_id')->constrained()->restrictOnDelete();

            // Applicant, agent, employer or job demand.
            $table->morphs('owner');

            $table->string('file_path');
            $table->string('original_name');
            $table->string('mime_type', 120);
            $table->unsignedBigInteger('size_bytes');
            // SHA-256 of the stored file, for integrity and duplicate detection.
            $table->string('checksum', 64);

            $table->string('document_number', 100)->nullable();
            $table->date('issue_date')->nullable();
            $table->date('expiry_date')->nullable();
            $table->string('issuing_country', 2)->nullable();
            $table->string('issuer')->nullable();

            $table->string('verification_status', 30)->default('uploaded');
            $table->foreignId('verified_by')->nullable()->constrained('users')->nullOnDelete();
            $table->timestamp('verified_at')->nullable();
            $table->text('rejection_reason')->nullable();
            $table->text('internal_notes')->nullable();

            // Version chain: a replacement points back at what it replaced.
            $table->unsignedSmallInteger('version')->default(1);
            $table->foreignId('replaces_document_id')->nullable()->constrained('documents')->nullOnDelete();
            $table->boolean('is_current')->default(true);

            $table->foreignId('uploaded_by')->nullable()->constrained('users')->nullOnDelete();
            $table->timestamps();
            $table->softDeletes();

            $table->index(['owner_type', 'owner_id', 'is_current']);
            $table->index(['company_id', 'verification_status']);
            $table->index(['document_type_id', 'verification_status']);
            $table->index('expiry_date');
            $table->index('checksum');
        });

        /**
         * Which document types are required, for whom. Rules match on any
         * combination of country, employer, job demand and occupation; the most
         * specific matching rules build an applicant's checklist (§17A).
         */
        Schema::create('document_requirements', function (Blueprint $table) {
            $table->id();
            $table->uuid('uuid')->unique();
            $table->foreignId('company_id')->constrained()->cascadeOnUpdate()->restrictOnDelete();
            $table->foreignId('document_type_id')->constrained()->cascadeOnDelete();

            $table->string('destination_country', 2)->nullable();
            $table->foreignId('employer_id')->nullable()->constrained()->cascadeOnDelete();
            $table->foreignId('job_demand_id')->nullable()->constrained()->cascadeOnDelete();
            $table->string('occupation', 120)->nullable();
            // Stage by which the document must be present, if any.
            $table->foreignId('required_by_stage_id')->nullable()->constrained('pipeline_stages')->nullOnDelete();

            $table->boolean('is_mandatory')->default(true);
            $table->text('notes')->nullable();
            $table->boolean('is_active')->default(true);
            $table->timestamps();

            $table->index(['company_id', 'is_active']);
            $table->index(['destination_country', 'is_active']);
        });

        // Every view and download of a document is recorded (§17.3, §65).
        Schema::create('document_access_logs', function (Blueprint $table) {
            $table->id();
            $table->foreignId('document_id')->constrained()->cascadeOnDelete();
            $table->foreignId('user_id')->nullable()->constrained()->nullOnDelete();
            $table->string('action', 20);
            $table->string('ip_address', 45)->nullable();
            $table->string('user_agent', 512)->nullable();
            $table->timestamp('accessed_at');

            $table->index(['document_id', 'accessed_at']);
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('document_access_logs');
        Schema::dropIfExists('document_requirements');
        Schema::dropIfExists('documents');
        Schema::dropIfExists('document_types');
    }
};
