<?php

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

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('warehouses', function (Blueprint $table) {
            $table->smallIncrements('id');

            $table->unsignedSmallInteger('store_id')->index(); // Relación con sucursal
            $table->unsignedSmallInteger('work_center_id')->nullable()->index();

            $table->string('code', 16)->unique();
            $table->string('name', 96)->index();

            $table->mediumText('description')->nullable();

            $table->unsignedMediumInteger('manager_id')->nullable()->index(); // sat_codigo_postal.

            $table->string('tel')->nullable();
            $table->string('tel2')->nullable();

            $table->unsignedTinyInteger('priority')->nullable();

            $table->boolean('status')->default(true)->index();

            $table->timestamps();

            // Indices
            $table->unique(['store_id', 'name']);

            $table->foreign('store_id')->references('id')->on('stores')->onDelete('cascade');
            $table->foreign('work_center_id')->references('id')->on('store_work_centers')->onDelete('cascade');
            $table->foreign('manager_id')->references('id')->on('users')->onUpdate('restrict')->onDelete('restrict');
        });

        Schema::create('warehouse_movements', function (Blueprint $table) {
            $table->mediumIncrements('id');

            $table->unsignedSmallInteger('store_id')->index();
            $table->unsignedSmallInteger('warehouse_id')->index(); // Almacén involucrado

            // Tipo de ajuste (ajuste de inventario o traspaso)
            $table->unsignedTinyInteger('movement_type')->index(); // Tipo de movimiento: ajuste o traspaso
            $table->unsignedMediumInteger('movement_id')->nullable(); // UID específico por sucursal

            $table->unsignedMediumInteger('created_by')->index(); // Usuario que registró el movimiento
            $table->unsignedMediumInteger('approved_by')->nullable()->index(); // Usuario que autorizó el movimiento

            // Cantidad ajustada
            $table->decimal('adjusted_quantity', 13, 6); // Cantidad ajustada para el ajuste o transferencia

            // Costo asociado
            $table->decimal('cost', 9, 2)->unsigned()->default(0); // Costo de la operación

            // Notas sobre el ajuste
            $table->mediumText('notes')->nullable(); // Notas adicionales

            // Campos para el traspaso
            $table->unsignedSmallInteger('to_warehouse_id')->nullable()->index(); // Almacén de destino (solo para traspasos)

            $table->unsignedTinyInteger('status')->index();  // Estatus de la orden ('pending', 'approved', 'received', 'cancelled')

            $table->softDeletes();
            $table->timestamps();


            // Claves foráneas
            $table->foreign('store_id')->references('id')->on('stores')->onDelete('restrict');
            $table->foreign('warehouse_id')->references('id')->on('warehouses')->onDelete('restrict');
            $table->foreign('to_warehouse_id')->references('id')->on('warehouses')->onDelete('restrict');
            $table->foreign('created_by')->references('id')->on('users')->onDelete('restrict');
            $table->foreign('approved_by')->references('id')->on('users')->onDelete('restrict');

        });

        Schema::create('lot_numbers', function (Blueprint $table) {
            $table->mediumIncrements('id');

            $table->unsignedMediumInteger('product_id')->index();
            $table->unsignedSmallInteger('store_id')->index();
            $table->unsignedSmallInteger('warehouse_id')->index();

            $table->string('lot_number', 50)->unique()->comment('Número único del lote');
            $table->date('production_date')->nullable();
            $table->date('expiry_date')->nullable();
            $table->decimal('initial_quantity', 13, 6)->unsigned()->default(0);
            $table->decimal('remaining_quantity', 13, 6)->unsigned()->default(0);
            $table->decimal('cost', 9, 2)->unsigned()->default(0);

            $table->timestamps();

            $table->foreign('product_id')->references('id')->on('products')->onDelete('restrict');
            $table->foreign('store_id')->references('id')->on('stores')->onDelete('restrict');
            $table->foreign('warehouse_id')->references('id')->on('warehouses')->onDelete('restrict');
        });

        Schema::create('inventory_stock_levels', function (Blueprint $table) {
            $table->mediumIncrements('id');

            $table->unsignedMediumInteger('product_id')->index();
            $table->unsignedSmallInteger('store_id')->nullable()->index();
            $table->unsignedSmallInteger('warehouse_id')->index();

            $table->decimal('quantity', 13, 6)->unsigned()->comment('Stock total disponible en el almacén');

            // Stock separado por área
            $table->decimal('pos_stock', 13, 6)->unsigned()->default(0)->comment('Stock destinado a ventas en POS');
            $table->decimal('ecommerce_stock', 13, 6)->unsigned()->default(0)->comment('Stock destinado a eCommerce');
            $table->decimal('purchase_reserved_stock', 13, 6)->unsigned()->default(0)->comment('Stock reservado para órdenes de compra');
            $table->decimal('asset_stock', 13, 6)->unsigned()->default(0)->comment('Stock reservado para uso interno');

            // Alertas de Stock mínimo y máximo
            $table->unsignedTinyInteger('alert_minimum_stock')->nullable()->index();
            $table->decimal('minimum_stock', 13, 6)->unsigned()->nullable();
            $table->unsignedTinyInteger('alert_maximum_stock')->nullable()->index();
            $table->decimal('maximum_stock', 13, 6)->unsigned()->nullable();

            // Costos asociados
            $table->decimal('last_cost', 9, 2)->unsigned()->default(0); // Último costo registrado
            $table->decimal('average_cost', 9, 2)->unsigned()->default(0); // Costo promedio ponderado
            $table->decimal('total_last_cost', 11, 2)->unsigned()->default(0); // Costo total último costo registrado
            $table->decimal('total_average_cost', 11, 2)->unsigned()->default(0); // Costo total promedio ponderado
            $table->decimal('total_identified_cost', 11, 2)->unsigned()->default(0); // Costo total identificado

            $table->unsignedTinyInteger('costing_method')->index(); // Método de costeo: 'average', 'last', 'identified'

            $table->timestamps();

            $table->unique(['warehouse_id', 'product_id']);

            $table->foreign('product_id')->references('id')->on('products')->onDelete('restrict');
            $table->foreign('store_id')->references('id')->on('stores')->onDelete('restrict');
            $table->foreign('warehouse_id')->references('id')->on('warehouses')->onDelete('restrict');
        });

        Schema::create('inventory_movements', function (Blueprint $table) {
            $table->integerIncrements('id');

            $table->unsignedMediumInteger('product_id')->index();
            $table->unsignedSmallInteger('store_id')->index();
            $table->unsignedSmallInteger('warehouse_id')->index();

            $table->enum('movement_type', ['in', 'out'])->index(); // Tipo de movimiento (entrada/salida)

            $table->decimal('quantity', 13, 6)->unsigned();

            $table->decimal('cost', 9, 2)->unsigned(); // Costo asociado a la transacción
            $table->decimal('cost_before', 9, 2)->unsigned()->nullable();
            $table->decimal('cost_after', 9, 2)->unsigned()->nullable();
            $table->enum('cost_type', ['average', 'last', 'specific'])->default('last');

            $table->text('notes')->nullable(); // Notas sobre el movimiento

            // Define el campo para la relación polimórfica manualmente
            $table->unsignedMediumInteger('transactionable_id')->index();
            $table->string('transactionable_type')->index();

            $table->unsignedMediumInteger('created_by')->index(); // Usuario que registró el movimiento

            $table->timestamps();

            // Agrega el índice con un nombre específico para evitar el problema de longitud
            $table->index(['transactionable_type', 'transactionable_id'], 'inventory_movements_transactionable_index');

            $table->foreign('product_id')->references('id')->on('products')->onDelete('restrict');
            $table->foreign('store_id')->references('id')->on('stores')->onDelete('restrict');
            $table->foreign('warehouse_id')->references('id')->on('warehouses')->onDelete('restrict');
            $table->foreign('created_by')->references('id')->on('users')->onDelete('restrict');
        });


    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('warehouses');
        Schema::dropIfExists('warehouse_movements');
        Schema::dropIfExists('lot_numbers');
        Schema::dropIfExists('inventory_stock_levels');
        Schema::dropIfExists('inventory_movements');
    }
};