<?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('tenants', function (Blueprint $table) {
            $table->id();
            $table->string('name', 180);
            $table->string('legal_name', 220)->nullable();
            $table->string('domain', 180)->nullable()->unique();
            $table->string('logo_path')->nullable();
            $table->enum('status', ['trial', 'active', 'suspended', 'expired'])->default('trial');
            $table->unsignedInteger('employee_limit')->default(0);
            $table->unsignedInteger('branch_limit')->default(0);
            $table->unsignedInteger('device_limit')->default(0);
            $table->string('timezone', 80)->default('UTC');
            $table->char('currency', 3)->default('USD');
            $table->timestamps();
        });

        Schema::create('modules', function (Blueprint $table) {
            $table->id();
            $table->string('module_key', 80)->unique();
            $table->string('name', 120);
            $table->boolean('globally_enabled')->default(true);
            $table->timestamps();
        });

        Schema::create('packages', function (Blueprint $table) {
            $table->id();
            $table->string('name', 120);
            $table->decimal('monthly_price', 12)->default(0);
            $table->decimal('yearly_price', 12)->default(0);
            $table->boolean('is_trial')->default(false);
            $table->unsignedInteger('employee_limit')->default(0);
            $table->unsignedInteger('branch_limit')->default(0);
            $table->unsignedInteger('device_limit')->default(0);
            $table->timestamps();
        });

        Schema::create('package_modules', function (Blueprint $table) {
            $table->foreignId('package_id')->constrained()->cascadeOnDelete();
            $table->string('module_key', 80);
            $table->primary(['package_id', 'module_key']);
        });

        Schema::create('tenant_modules', function (Blueprint $table) {
            $table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
            $table->string('module_key', 80);
            $table->boolean('enabled')->default(true);
            $table->primary(['tenant_id', 'module_key']);
        });

        Schema::create('subscriptions', function (Blueprint $table) {
            $table->id();
            $table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
            $table->foreignId('package_id')->constrained();
            $table->enum('status', ['trial', 'active', 'past_due', 'cancelled', 'expired'])->default('trial');
            $table->date('starts_at');
            $table->date('expires_at');
            $table->enum('billing_cycle', ['monthly', 'yearly', 'trial'])->default('trial');
            $table->timestamps();
            $table->index(['tenant_id', 'status', 'expires_at']);
        });

        Schema::create('branches', function (Blueprint $table) {
            $table->id();
            $table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
            $table->string('name', 160);
            $table->string('code', 60);
            $table->text('address')->nullable();
            $table->string('timezone', 80)->nullable();
            $table->enum('status', ['active', 'inactive'])->default('active');
            $table->timestamps();
            $table->unique(['tenant_id', 'code']);
        });

        Schema::create('departments', function (Blueprint $table) {
            $table->id();
            $table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
            $table->foreignId('parent_id')->nullable()->constrained('departments')->nullOnDelete();
            $table->string('name', 160);
            $table->string('code', 60)->nullable();
            $table->timestamps();
        });

        Schema::create('designations', function (Blueprint $table) {
            $table->id();
            $table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
            $table->string('name', 160);
            $table->string('grade', 80)->nullable();
            $table->timestamps();
        });

        Schema::create('employees', function (Blueprint $table) {
            $table->id();
            $table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
            $table->foreignId('branch_id')->constrained()->cascadeOnDelete();
            $table->foreignId('department_id')->nullable()->constrained()->nullOnDelete();
            $table->foreignId('designation_id')->nullable()->constrained()->nullOnDelete();
            $table->foreignId('manager_id')->nullable()->constrained('employees')->nullOnDelete();
            $table->string('employee_code', 80);
            $table->string('rfid_card_no', 80)->nullable();
            $table->string('fingerprint_id', 80)->nullable();
            $table->string('face_id', 80)->nullable();
            $table->string('name', 180);
            $table->string('email', 180)->nullable();
            $table->string('phone', 60)->nullable();
            $table->enum('employment_status', ['active', 'inactive', 'terminated', 'suspended'])->default('active');
            $table->enum('salary_type', ['monthly', 'daily', 'hourly'])->default('monthly');
            $table->decimal('basic_salary', 12)->default(0);
            $table->string('bank_name', 160)->nullable();
            $table->string('bank_account_no', 120)->nullable();
            $table->date('joined_at')->nullable();
            $table->timestamps();
            $table->unique(['tenant_id', 'employee_code']);
            $table->index(['tenant_id', 'branch_id']);
        });

        Schema::create('devices', function (Blueprint $table) {
            $table->id();
            $table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
            $table->foreignId('branch_id')->constrained()->cascadeOnDelete();
            $table->string('name', 160);
            $table->string('serial_no', 120);
            $table->string('model', 80);
            $table->string('ip_address', 80)->nullable();
            $table->unsignedInteger('port')->nullable();
            $table->enum('status', ['online', 'offline', 'disabled'])->default('offline');
            $table->timestamp('last_seen_at')->nullable();
            $table->timestamps();
            $table->unique(['tenant_id', 'serial_no']);
        });

        Schema::create('attendance_logs', function (Blueprint $table) {
            $table->id();
            $table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
            $table->foreignId('device_id')->nullable()->constrained()->nullOnDelete();
            $table->foreignId('employee_id')->nullable()->constrained()->nullOnDelete();
            $table->enum('punch_type', ['check_in', 'check_out', 'lunch_in', 'lunch_out', 'break_in', 'break_out', 'ot_in', 'ot_out']);
            $table->enum('auth_mode', ['fingerprint', 'face', 'rfid', 'pin', 'manual']);
            $table->timestamp('punched_at');
            $table->json('raw_payload')->nullable();
            $table->timestamps();
            $table->index(['tenant_id', 'punched_at']);
            $table->index(['employee_id', 'punched_at']);
        });

        Schema::create('attendance_summaries', function (Blueprint $table) {
            $table->id();
            $table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
            $table->foreignId('employee_id')->constrained()->cascadeOnDelete();
            $table->date('attendance_date');
            $table->enum('status', ['present', 'absent', 'leave', 'holiday', 'incomplete']);
            $table->unsignedInteger('working_minutes')->default(0);
            $table->unsignedInteger('late_minutes')->default(0);
            $table->unsignedInteger('early_out_minutes')->default(0);
            $table->unsignedInteger('overtime_minutes')->default(0);
            $table->decimal('penalty_amount', 12)->default(0);
            $table->timestamps();
            $table->unique(['tenant_id', 'employee_id', 'attendance_date']);
        });

        Schema::create('rules', function (Blueprint $table) {
            $table->id();
            $table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
            $table->string('rule_key', 120);
            $table->string('name', 160);
            $table->enum('domain', ['attendance', 'payroll', 'leave', 'holiday']);
            $table->integer('priority')->default(100);
            $table->json('conditions');
            $table->json('actions');
            $table->boolean('enabled')->default(true);
            $table->timestamps();
            $table->index(['tenant_id', 'domain', 'enabled', 'priority']);
        });

        Schema::create('payroll_periods', function (Blueprint $table) {
            $table->id();
            $table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
            $table->foreignId('branch_id')->nullable()->constrained()->nullOnDelete();
            $table->string('name', 120);
            $table->date('starts_at');
            $table->date('ends_at');
            $table->enum('status', ['draft', 'processing', 'approved', 'locked'])->default('draft');
            $table->timestamps();
        });

        Schema::create('payslips', function (Blueprint $table) {
            $table->id();
            $table->foreignId('tenant_id')->constrained()->cascadeOnDelete();
            $table->foreignId('payroll_period_id')->constrained()->cascadeOnDelete();
            $table->foreignId('employee_id')->constrained()->cascadeOnDelete();
            $table->decimal('gross_pay', 12)->default(0);
            $table->decimal('total_deductions', 12)->default(0);
            $table->decimal('net_pay', 12)->default(0);
            $table->json('components');
            $table->json('deductions');
            $table->timestamps();
            $table->unique(['payroll_period_id', 'employee_id']);
        });
    }

    public function down(): void
    {
        foreach (['payslips', 'payroll_periods', 'rules', 'attendance_summaries', 'attendance_logs', 'devices', 'employees', 'designations', 'departments', 'branches', 'subscriptions', 'tenant_modules', 'package_modules', 'packages', 'modules', 'tenants'] as $table) {
            Schema::dropIfExists($table);
        }
    }
};
