<?php

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

return new class extends Migration
{
    public function up(): void
    {
        Schema::table('roles', function (Blueprint $table): void {
            $table->uuid('uuid')->nullable()->after('id');
            $table->string('slug')->nullable()->after('name');
            $table->string('status', 30)->default('active')->index()->after('is_system');
        });

        DB::table('roles')->select(['id', 'name'])->orderBy('id')->each(function (object $role): void {
            DB::table('roles')->where('id', $role->id)->update([
                'uuid' => (string) Str::uuid(),
                'slug' => Str::slug($role->name),
            ]);
        });

        Schema::table('roles', function (Blueprint $table): void {
            $table->unique('uuid');
            $table->unique('slug');
        });

        Schema::table('permissions', function (Blueprint $table): void {
            $table->uuid('uuid')->nullable()->after('id');
            $table->string('permission_name')->nullable()->after('module');
            $table->string('slug')->nullable()->after('permission_name');
        });

        DB::table('permissions')->select(['id', 'name', 'display_name'])->orderBy('id')->each(function (object $permission): void {
            DB::table('permissions')->where('id', $permission->id)->update([
                'uuid' => (string) Str::uuid(),
                'permission_name' => $permission->display_name,
                'slug' => $permission->name,
            ]);
        });

        Schema::table('permissions', function (Blueprint $table): void {
            $table->unique('uuid');
            $table->unique('slug');
            $table->index(['module', 'slug']);
        });

        Schema::table('role_permission', function (Blueprint $table): void {
            $table->timestamp('created_at')->nullable();
            $table->timestamp('updated_at')->nullable();
        });

        Schema::table('admin_role', function (Blueprint $table): void {
            $table->timestamp('created_at')->nullable();
            $table->timestamp('updated_at')->nullable();
        });

        Schema::create('system_settings', function (Blueprint $table): void {
            $table->id();
            $table->uuid('uuid')->unique();
            $table->string('setting_group', 50)->index();
            $table->string('setting_key', 100);
            $table->longText('setting_value')->nullable();
            $table->string('setting_type', 30)->default('string');
            $table->text('description')->nullable();
            $table->boolean('is_public')->default(false)->index();
            $table->boolean('is_encrypted')->default(false)->index();
            $table->foreignId('updated_by')->nullable()->constrained('admins')->nullOnDelete();
            $table->timestamp('updated_at')->nullable();

            $table->unique(['setting_group', 'setting_key']);
        });

        Schema::create('general_settings', function (Blueprint $table): void {
            $table->id();
            $table->string('company_name');
            $table->string('company_email')->nullable();
            $table->string('company_phone', 30)->nullable();
            $table->text('address')->nullable();
            $table->string('website')->nullable();
            $table->string('timezone', 64)->default('UTC');
            $table->string('currency', 3)->default('INR');
            $table->string('language', 12)->default('en');
            $table->string('date_format', 30)->default('Y-m-d');
            $table->string('time_format', 30)->default('H:i');
            $table->string('logo')->nullable();
            $table->string('favicon')->nullable();
            $table->string('primary_color', 20)->nullable();
            $table->string('secondary_color', 20)->nullable();
            $table->json('contact_information')->nullable();
            $table->timestamps();
        });

        Schema::create('security_settings', function (Blueprint $table): void {
            $table->id();
            $table->unsignedSmallInteger('login_attempts')->default(5);
            $table->unsignedInteger('lockout_duration')->default(900);
            $table->unsignedSmallInteger('password_expiry')->default(90);
            $table->unsignedTinyInteger('minimum_password_length')->default(12);
            $table->boolean('require_uppercase')->default(true);
            $table->boolean('require_lowercase')->default(true);
            $table->boolean('require_number')->default(true);
            $table->boolean('require_symbol')->default(true);
            $table->boolean('two_factor_enabled')->default(true);
            $table->unsignedInteger('session_timeout')->default(1800);
            $table->boolean('force_https')->default(true);
            $table->unsignedInteger('jwt_expiry')->default(3600);
            $table->unsignedInteger('api_rate_limit')->default(60);
            $table->json('ip_whitelist')->nullable();
            $table->boolean('captcha_enabled')->default(false);
            $table->unsignedSmallInteger('trusted_device_days')->default(30);
            $table->foreignId('updated_by')->nullable()->constrained('admins')->nullOnDelete();
            $table->timestamps();
        });

        Schema::create('api_keys', function (Blueprint $table): void {
            $table->id();
            $table->uuid('uuid')->unique();
            $table->string('name');
            $table->string('key_prefix', 20)->index();
            $table->string('key_hash', 64)->unique();
            $table->text('encrypted_secret')->nullable();
            $table->json('abilities')->nullable();
            $table->json('allowed_ips')->nullable();
            $table->unsignedInteger('rate_limit')->default(60);
            $table->foreignId('created_by')->nullable()->constrained('admins')->nullOnDelete();
            $table->timestamp('last_used_at')->nullable()->index();
            $table->timestamp('expires_at')->nullable()->index();
            $table->timestamp('revoked_at')->nullable()->index();
            $table->string('status', 30)->default('active')->index();
            $table->timestamps();

            $table->index(['status', 'expires_at']);
        });

        Schema::create('backup_records', function (Blueprint $table): void {
            $table->id();
            $table->uuid('uuid')->unique();
            $table->string('backup_name');
            $table->string('backup_type', 30)->index();
            $table->string('frequency', 30)->nullable();
            $table->string('disk', 30);
            $table->string('path')->nullable();
            $table->unsignedBigInteger('size')->nullable();
            $table->string('checksum', 64)->nullable();
            $table->string('status', 30)->default('queued')->index();
            $table->boolean('encrypted')->default(true);
            $table->foreignId('requested_by')->nullable()->constrained('admins')->nullOnDelete();
            $table->timestamp('started_at')->nullable();
            $table->timestamp('completed_at')->nullable();
            $table->timestamp('expires_at')->nullable()->index();
            $table->text('failure_reason')->nullable();
            $table->timestamps();

            $table->index(['backup_type', 'created_at']);
        });

        Schema::create('setting_change_logs', function (Blueprint $table): void {
            $table->id();
            $table->uuid('uuid')->unique();
            $table->string('setting_group', 50)->index();
            $table->string('setting_key', 100)->index();
            $table->longText('old_value')->nullable();
            $table->longText('new_value')->nullable();
            $table->boolean('values_encrypted')->default(false);
            $table->foreignId('changed_by')->nullable()->constrained('admins')->nullOnDelete();
            $table->ipAddress('ip_address')->nullable();
            $table->text('reason')->nullable();
            $table->timestamp('created_at')->useCurrent()->index();

            $table->index(['setting_group', 'setting_key', 'created_at']);
        });

        Schema::create('languages', function (Blueprint $table): void {
            $table->id();
            $table->string('name');
            $table->string('code', 12)->unique();
            $table->string('locale', 20)->unique();
            $table->string('direction', 3)->default('ltr');
            $table->boolean('is_default')->default(false)->index();
            $table->boolean('is_active')->default(true)->index();
            $table->timestamps();
        });

        Schema::create('translation_keys', function (Blueprint $table): void {
            $table->id();
            $table->foreignId('language_id')->constrained()->cascadeOnDelete();
            $table->string('group', 80)->default('messages');
            $table->string('key', 191);
            $table->text('value');
            $table->timestamps();

            $table->unique(['language_id', 'group', 'key']);
        });
    }

    public function down(): void
    {
        Schema::dropIfExists('translation_keys');
        Schema::dropIfExists('languages');
        Schema::dropIfExists('setting_change_logs');
        Schema::dropIfExists('backup_records');
        Schema::dropIfExists('api_keys');
        Schema::dropIfExists('security_settings');
        Schema::dropIfExists('general_settings');
        Schema::dropIfExists('system_settings');

        Schema::table('admin_role', function (Blueprint $table): void {
            $table->dropColumn(['created_at', 'updated_at']);
        });

        Schema::table('role_permission', function (Blueprint $table): void {
            $table->dropColumn(['created_at', 'updated_at']);
        });

        Schema::table('permissions', function (Blueprint $table): void {
            $table->dropUnique(['uuid']);
            $table->dropUnique(['slug']);
            $table->dropIndex(['module', 'slug']);
        });

        Schema::table('permissions', function (Blueprint $table): void {
            $table->dropColumn(['uuid', 'permission_name', 'slug']);
        });

        Schema::table('roles', function (Blueprint $table): void {
            $table->dropUnique(['uuid']);
            $table->dropUnique(['slug']);
            $table->dropIndex(['status']);
        });

        Schema::table('roles', function (Blueprint $table): void {
            $table->dropColumn(['uuid', 'slug', 'status']);
        });
    }
};
