<?php

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

return new class extends Migration
{
    public function up(): void
    {
        Schema::create('cash_registers', function (Blueprint $table) {
            $table->id();
            $table->foreignId('branch_id')->constrained('branches');
            $table->string('name', 100);
            $table->string('device_id', 100)->nullable();
            $table->boolean('is_active')->default(true);
            $table->timestamps();

            $table->index('branch_id', 'idx_cr_branch');
        });

        Schema::create('shifts', function (Blueprint $table) {
            $table->id();
            $table->foreignId('branch_id')->constrained('branches');
            $table->foreignId('user_id')->constrained('users');
            $table->foreignId('cash_register_id')->nullable()->constrained('cash_registers');
            $table->timestamp('opened_at');
            $table->timestamp('closed_at')->nullable();
            $table->decimal('opening_float', 15, 2)->default(0);
            $table->decimal('closing_float', 15, 2)->nullable();
            $table->decimal('expected_cash', 15, 2)->nullable();
            $table->decimal('cash_variance', 15, 2)->nullable();
            $table->decimal('total_sales', 15, 2)->default(0);
            $table->unsignedInteger('total_orders')->default(0);
            $table->text('notes')->nullable();
            $table->enum('status', ['open', 'closed', 'suspended'])->default('open');
            $table->timestamps();

            $table->index('branch_id', 'idx_shifts_branch');
            $table->index('user_id', 'idx_shifts_user');
            $table->index('status', 'idx_shifts_status');
            $table->index('opened_at', 'idx_shifts_opened_at');
        });

        Schema::create('shift_activities', function (Blueprint $table) {
            $table->id();
            $table->foreignId('shift_id')->constrained('shifts');
            $table->foreignId('user_id')->constrained('users');
            $table->enum('activity_type', ['login', 'logout', 'sale', 'refund', 'expense', 'cash_in', 'cash_out', 'discount_applied', 'void']);
            $table->string('description', 500)->nullable();
            $table->decimal('amount', 15, 2)->nullable();
            $table->string('reference_type', 100)->nullable();
            $table->unsignedBigInteger('reference_id')->nullable();
            $table->timestamp('created_at')->nullable();

            $table->index('shift_id', 'idx_shift_act_shift');
            $table->index('user_id', 'idx_shift_act_user');
            $table->index('activity_type', 'idx_shift_act_type');
        });

        Schema::create('cash_drawer_transactions', function (Blueprint $table) {
            $table->id();
            $table->foreignId('shift_id')->constrained('shifts');
            $table->foreignId('cash_register_id')->nullable()->constrained('cash_registers');
            $table->foreignId('user_id')->constrained('users');
            $table->enum('type', ['float_in', 'float_out', 'sale', 'refund', 'expense', 'adjustment']);
            $table->decimal('amount', 15, 2);
            $table->decimal('running_balance', 15, 2);
            $table->string('notes', 500)->nullable();
            $table->string('reference_type', 100)->nullable();
            $table->unsignedBigInteger('reference_id')->nullable();
            $table->timestamp('created_at')->nullable();

            $table->index('shift_id', 'idx_cdt_shift');
            $table->index('type', 'idx_cdt_type');
        });

        Schema::create('orders', function (Blueprint $table) {
            $table->id();
            $table->foreignId('company_id')->constrained('companies');
            $table->foreignId('branch_id')->constrained('branches');
            $table->foreignId('shift_id')->nullable()->constrained('shifts');
            $table->foreignId('user_id')->constrained('users');
            $table->foreignId('customer_id')->nullable()->constrained('customers');
            $table->unsignedBigInteger('table_id')->nullable();
            $table->string('order_number', 50);
            $table->enum('type', ['sale', 'return', 'layaway', 'quotation'])->default('sale');
            $table->enum('status', ['pending', 'processing', 'completed', 'voided', 'refunded', 'partially_refunded'])->default('pending');
            $table->char('currency_code', 3)->default('KES');
            $table->decimal('exchange_rate', 15, 6)->default(1);
            $table->decimal('subtotal', 15, 4)->default(0);
            $table->decimal('discount_amount', 15, 4)->default(0);
            $table->enum('discount_type', ['percentage', 'fixed'])->nullable();
            $table->foreignId('promotion_id')->nullable()->constrained('promotions');
            $table->decimal('tax_amount', 15, 4)->default(0);
            $table->decimal('total_amount', 15, 4)->default(0);
            $table->decimal('amount_paid', 15, 4)->default(0);
            $table->decimal('change_amount', 15, 4)->default(0);
            $table->unsignedInteger('loyalty_points_earned')->default(0);
            $table->unsignedInteger('loyalty_points_redeemed')->default(0);
            $table->text('notes')->nullable();
            $table->timestamp('voided_at')->nullable();
            $table->unsignedBigInteger('voided_by')->nullable();
            $table->text('void_reason')->nullable();
            $table->string('device_id', 100)->nullable();
            $table->timestamp('synced_at')->nullable();
            $table->string('local_id', 100)->nullable();
            $table->timestamp('receipt_printed_at')->nullable();
            $table->timestamps();

            $table->unique(['company_id', 'order_number'], 'uq_orders_company_number');
            $table->unique(['device_id', 'local_id'], 'uq_orders_local_id');
            $table->index('branch_id', 'idx_orders_branch');
            $table->index('shift_id', 'idx_orders_shift');
            $table->index('customer_id', 'idx_orders_customer');
            $table->index('status', 'idx_orders_status');
            $table->index('created_at', 'idx_orders_created');
            $table->index('type', 'idx_orders_type');
            $table->foreign('voided_by', 'fk_orders_voided_by')->references('id')->on('users')->nullOnDelete();
        });

        Schema::create('order_items', function (Blueprint $table) {
            $table->id();
            $table->foreignId('order_id')->constrained('orders')->cascadeOnDelete();
            $table->foreignId('product_id')->constrained('products');
            $table->foreignId('variant_id')->nullable()->constrained('product_variants');
            $table->foreignId('batch_id')->nullable()->constrained('batches');
            $table->string('name');
            $table->string('sku', 100)->nullable();
            $table->decimal('quantity', 15, 4);
            $table->decimal('unit_price', 15, 4);
            $table->decimal('cost_price', 15, 4)->default(0);
            $table->decimal('discount_amount', 15, 4)->default(0);
            $table->decimal('tax_rate', 5, 2)->default(0);
            $table->decimal('tax_amount', 15, 4)->default(0);
            $table->decimal('total_amount', 15, 4);
            $table->boolean('is_returned')->default(false);
            $table->decimal('returned_quantity', 15, 4)->default(0);
            $table->string('notes', 500)->nullable();
            $table->timestamps();

            $table->index('order_id', 'idx_oi_order');
            $table->index('product_id', 'idx_oi_product');
        });

        Schema::create('payment_methods', function (Blueprint $table) {
            $table->id();
            $table->foreignId('company_id')->constrained('companies');
            $table->string('name', 100);
            $table->enum('type', ['cash', 'mpesa', 'card', 'bank_transfer', 'cheque', 'loyalty_points', 'credit', 'other']);
            $table->boolean('is_active')->default(true);
            $table->json('config')->nullable();
            $table->timestamps();

            $table->index('company_id', 'idx_pm_company');
        });

        Schema::create('payments', function (Blueprint $table) {
            $table->id();
            $table->foreignId('order_id')->constrained('orders');
            $table->foreignId('payment_method_id')->constrained('payment_methods');
            $table->decimal('amount', 15, 4);
            $table->char('currency_code', 3)->default('KES');
            $table->decimal('exchange_rate', 15, 6)->default(1);
            $table->decimal('amount_kes', 15, 4);
            $table->enum('status', ['pending', 'completed', 'failed', 'reversed'])->default('pending');
            $table->string('reference_number')->nullable();
            $table->string('notes', 500)->nullable();
            $table->timestamp('processed_at')->nullable();
            $table->timestamps();

            $table->index('order_id', 'idx_payments_order');
            $table->index('payment_method_id', 'idx_payments_method');
            $table->index('reference_number', 'idx_payments_reference');
            $table->index('status', 'idx_payments_status');
        });
    }

    public function down(): void
    {
        Schema::table('orders', function (Blueprint $table) {
            $table->dropForeign('fk_orders_voided_by');
        });

        Schema::dropIfExists('payments');
        Schema::dropIfExists('payment_methods');
        Schema::dropIfExists('order_items');
        Schema::dropIfExists('orders');
        Schema::dropIfExists('cash_drawer_transactions');
        Schema::dropIfExists('shift_activities');
        Schema::dropIfExists('shifts');
        Schema::dropIfExists('cash_registers');
    }
};
