<?php

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

return new class extends Migration
{
    public function up(): void
    {
        // Status lookup for the return-GRN lifecycle. Deliberately the same
        // shape as grn_statuses (and also NOT BelongsToTenant): confirms and
        // reversals compare against the global DRAFT/CONFIRMED/DELETED ints
        // (see ReturnGrnStatus), so the three rows must be identical for every
        // tenant. Carries a `tenant_id` column like every other owned table
        // (blanket 2026_07_08 migration convention) but it is vestigial here.
        Schema::create('return_grn_statuses', function (Blueprint $table) {
            $table->tinyIncrements('id');
            $table->string('code', 30)->unique();
            $table->string('name', 100);
            $table->string('color', 20)->default('gray');
            $table->unsignedTinyInteger('sort_order')->default(0);
        });

        DB::table('return_grn_statuses')->insert([
            ['id' => 1, 'code' => 'draft',    'name' => 'Draft',    'color' => 'gray',  'sort_order' => 1],
            ['id' => 2, 'code' => 'confirmed', 'name' => 'Confirmed', 'color' => 'green', 'sort_order' => 2],
            ['id' => 3, 'code' => 'deleted',  'name' => 'Deleted',  'color' => 'red',   'sort_order' => 3],
        ]);

        Schema::create('return_grns', function (Blueprint $table) {
            $table->id();
            // Same shape as every other owned table (2026_07_08_000002):
            // nullable column + no DB-level FK — integrity comes from the
            // BelongsToTenant trait and the fail-closed TenantScope.
            $table->unsignedBigInteger('tenant_id')->nullable()->index();
            $table->string('return_grn_number', 30)->unique(); // RGRN-YYYY-NNNNN
            $table->foreignId('branch_id')->nullable()->constrained('warehouses')->cascadeOnUpdate()->nullOnDelete();
            $table->foreignId('supplier_id')->nullable()->constrained('suppliers')->cascadeOnUpdate()->nullOnDelete();
            $table->string('reference', 100)->nullable();
            $table->string('reason', 500)->nullable();
            $table->text('note')->nullable();
            $table->decimal('total_cost', 14, 2)->default(0);
            $table->unsignedTinyInteger('return_grn_status_id')->index();
            $table->foreign('return_grn_status_id', 'return_grns_status_id_foreign')->references('id')->on('return_grn_statuses')->restrictOnDelete();
            $table->foreignId('confirmed_by')->nullable()->constrained('users')->nullOnDelete();
            $table->timestamp('confirmed_at')->nullable();
            $table->foreignId('deleted_by')->nullable()->constrained('users')->nullOnDelete();
            $table->timestamp('deleted_at')->nullable();
            $table->foreignId('created_by')->nullable()->constrained('users')->nullOnDelete();
            $table->foreignId('updated_by')->nullable()->constrained('users')->nullOnDelete();
            $table->timestamps();
            $table->index(['branch_id', 'created_at']);
        });

        Schema::create('return_grn_items', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('tenant_id')->nullable()->index();
            $table->foreignId('return_grn_id')->constrained('return_grns')->cascadeOnUpdate()->cascadeOnDelete();
            $table->foreignId('product_id')->nullable()->constrained('products')->cascadeOnUpdate()->nullOnDelete();
            $table->foreignId('unit_id')->nullable()->constrained('unit_of_measures')->cascadeOnUpdate()->nullOnDelete();
            // Optional traceability back to the GRN line the goods arrived on —
            // when set, the unit(s) returning are matched against what was
            // actually received from this supplier (batch + serials follow).
            $table->foreignId('source_grn_item_id')->nullable()->constrained('grn_items')->cascadeOnUpdate()->nullOnDelete();
            $table->foreignId('stock_batch_id')->nullable()->constrained('stock_batches')->cascadeOnUpdate()->nullOnDelete();
            $table->string('serial_numbers', 1000)->nullable();
            $table->decimal('quantity', 12, 4);
            $table->decimal('unit_cost', 12, 2)->nullable();
            $table->decimal('total_cost', 14, 2)->default(0);
            $table->timestamps();
            $table->index('product_id');
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('return_grn_items');
        Schema::dropIfExists('return_grns');
        Schema::dropIfExists('return_grn_statuses');
    }
};
