<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use Symfony\Component\Process\Process;

class MakeCrudCommand extends Command
{
  /**
   * Nama dan signature dari perintah konsol.
   *
   * @var string
   */
  protected $signature = 'make:crud {migration_file} {--label=} {--rollback} {--prefix_url=} {--format} {--icon=} {--custom_validation=} {--custom_labels=}';

  /**
   * Deskripsi dari perintah konsol.
   *
   * @var string
   */
  protected $description = 'Generate a controller and React views, and append resource routes. Use --rollback to reverse.';

  /**
   * Lokasi template (stubs).
   *
   * @var string
   */
  protected $stubsPath = __DIR__ . '/../../../stubs/';

  /**
   * Kamus validasi untuk memetakan nama kolom ke aturan.
   *
   * @var array
   */
  protected $validationDictionary;

  /**
   * Kamus ikon untuk memetakan nama tabel ke kelas ikon.
   *
   * @var array
   */
  protected $iconDictionary;

  /**
   * Jalankan perintah konsol.
   *
   * @return int
   */
  public function handle()
  {
    $this->validationDictionary = require $this->stubsPath . 'Databases/validation.php';
    $this->iconDictionary = require $this->stubsPath . 'Databases/icon.php';

    $migrationFile = $this->argument('migration_file');
    $migrationPath = database_path('migrations/' . $migrationFile . '.php');

    if (!File::exists($migrationPath)) {
      $this->error("Migration file not found at: {$migrationPath}");
      return 1;
    }

    $content = File::get($migrationPath);

    if (!preg_match("/Schema::create\('(?<table>\w+)'/", $content, $matches)) {
      $this->error("Could not find table name in migration file.");
      return 1;
    }
    $tableName = $matches['table'];

    preg_match_all("/->(?<type>\w+)\('(?<column>\w+)'\)(?<options>.*?);/", $content, $columnMatches, PREG_SET_ORDER);

    $modelName = Str::studly(Str::singular($tableName));
    $modelNameCamel = Str::camel($modelName);
    $modelNamePlural = Str::plural($modelName);
    $modelNameCamelPlural = Str::camel($modelNamePlural);
    $subNamespace = 'Admin';
    $adminPath = 'Admin';
    $pageLabel = $this->option('label') ?? Str::headline($modelName);

    $prefixUrl = $this->option('prefix_url');
    $basePageUrl = Str::kebab($tableName);
    if ($prefixUrl) {
      $pageUrl = Str::of($prefixUrl)->trim('/') . '/' . $basePageUrl;
    } else {
      $pageUrl = "admin/" . $basePageUrl;
    }

    $placeholders = [
      '{{ SubNamespace }}' => $subNamespace,
      '{{ AdminPath }}' => $adminPath,
      '{{ ModelName }}' => $modelName,
      '{{ modelNameCamel }}' => $modelNameCamel,
      '{{ modelNamePlural }}' => $modelNamePlural,
      '{{ modelNameCamelPlural }}' => $modelNameCamelPlural,
      '{{ tableName }}' => $tableName,
      '{{ pageLabel }}' => $pageLabel,
      '{{ pageUrl }}' => $pageUrl,
    ];

    $customLabels = $this->option('custom_labels') ? json_decode($this->option('custom_labels'), true) : [];
    $customValidation = $this->option('custom_validation') ? json_decode($this->option('custom_validation'), true) : [];

    if ($this->option('rollback')) {
      $this->info("Starting rollback for '{$tableName}'...");
      $this->rollbackController($placeholders);
      $this->rollbackReactViews($placeholders);
      $this->rollbackRoute($placeholders);
      $this->rollbackSidebarMenuEntry($placeholders);

      $this->info("Rollback complete.");
      return 0;
    }

    $tableHeaderEntries = [];
    $validationRules = '';
    $formFieldsData = '';
    $formProperties = [];
    $useEffectHooks = '';

    $tableHeaderEntries[] = [
      'label' => '#',
      'value' => 'id',
      'type' => 'numbering',
    ];

    foreach ($columnMatches as $match) {
      $column = $match['column'];
      $type = $match['type'];
      $options = $match['options'];

      if (in_array($column, ['id', 'created_at', 'updated_at', 'user_id', 'deleted_at'])) {
        continue;
      }

      $label = $customLabels[$column] ?? Str::headline($column);

      $formType = 'input';
      $formProps = [];
      $isTextEditor = false;

      if (Str::endsWith($column, '_id')) {
        $formType = 'select';
        $formProps['options'] = "props." . Str::plural(Str::beforeLast($column, '_id'));
      } elseif ($column === 'status') {
        $formType = 'select';
        $formProps['options'] = "props.status";
      } elseif (Str::contains($column, ['description', 'content', 'body'])) {
        $formType = 'textarea';
      } elseif (Str::endsWith($column, '_at')) {
        $formType = 'DatePicker';
      } elseif (Str::contains($column, ['image', 'avatar', 'thumbnail', 'file'])) {
        $formType = 'FileUploader';
      }

      $header = [
        'label' => $label,
        'value' => $column,
      ];

      if (Str::contains($column, ['name', 'title', 'slug', 'description', 'content'])) {
        $header['isSearchable'] = true;
      }

      if (in_array($column, ['thumbnail', 'description', 'seo_keyword', 'seo_description', 'content'])) {
        $header['isDetail'] = true;
      }

      if (Str::endsWith($column, '_at')) {
        $header['type'] = 'date';
      } elseif ($column === 'status') {
        $header['type'] = 'status';
      }

      $tableHeaderEntries[] = $header;

      if ($column === 'slug') {
        $useEffectHooks .= "
    useEffect(() => {
        let filteredSlug = '';
        if (data.name && !isEdit) {
            const slug = slugify(data.name);
            filteredSlug = slug;
        }
        if (!isEdit) {
            setData('slug', filteredSlug);
        }
    }, [data.name]);
";
      }

      if ($column === 'seo_description') {
        $useEffectHooks .= "
    useEffect(() => {
        const desc = data?.seo_description;
        if (desc && desc.length > 160) {
            const truncated = desc.substring(0, 160);
            if (desc !== truncated) {
                setData('seo_description', truncated);
            }
        }
    }, [data?.seo_description]);
";
      }

      $properties = [
        'form' => $formType,
        'props' => array_merge([
          'name' => $column,
          'label' => $label,
        ], $formProps)
      ];

      $formProperties[] = $properties;

      $rule = $customValidation[$column] ?? $this->getValidationRule($column, $options, $tableName);
      $validationRules .= "            \"{$column}\" => \"{$rule}\"," . "\n";
      $formFieldsData .= "        {$column}: ''," . "\n";
    }

    $tableHeaderEntries[] = ['label' => 'Status', 'value' => 'status', 'type' => 'status'];
    $tableHeaderEntries[] = ['label' => 'Dibuat', 'value' => 'created_at', 'type' => 'date', 'isSearchable' => true];
    $tableHeaderEntries[] = ['label' => 'Diperbarui', 'value' => 'updated_at', 'type' => 'date', 'isSearchable' => true];
    $tableHeaderEntries[] = [
      'label' => 'Dihapus',
      'value' => 'deleted_at',
      'type' => 'date',
      'isHidden' => "params.get('deleted_at') != 'show'",
    ];
    $tableHeaderEntries[] = ['label' => 'Aksi', 'value' => 'id', 'type' => 'action'];

    $jsTableHeaders = '';
    foreach ($tableHeaderEntries as $entry) {
      $jsTableHeaders .= '      ' . $this->convertArrayToJsObjectString($entry, 6) . ",\n";
    }

    $validationRules = rtrim($validationRules, ",\n");
    $placeholders['{{ tableHeaderReactArray }}'] = rtrim($jsTableHeaders, ",\n");
    $placeholders['{{ validationRules }}'] = $validationRules;
    $placeholders['{{ formFieldsData }}'] = rtrim($formFieldsData, ",\n");
    $placeholders['{{ useEffectHooks }}'] = $useEffectHooks;
    $placeholders['{{ formProperties }}'] = $this->convertFormPropertiesArrayToJsString($formProperties);

    $this->createController($placeholders);
    $this->createReactView('Index', $placeholders);
    $this->createReactView('Create', $placeholders);
    $this->createReactView('Edit', $placeholders);
    $this->createReactView('MainForm', $placeholders);

    $this->appendRouteToWebPhp($placeholders);
    $this->appendSidebarMenuEntry($placeholders);

    if ($this->option('format')) {
      $this->runFormatter($modelName);
    }

    $this->info('CRUD files generated successfully, and routes appended laravel routes and AuthenticatedLayout.jsx!');

    return 0;
  }

  protected function createController(array $placeholders)
  {
    $stub = File::get($this->stubsPath . 'Controller/DefaultController.stub');
    $content = str_replace(array_keys($placeholders), array_values($placeholders), $stub);
    $controllerDir = app_path('Http/Controllers/' . $placeholders['{{ SubNamespace }}']);
    if (!File::exists($controllerDir)) {
      File::makeDirectory($controllerDir, 0755, true);
    }
    $controllerPath = $controllerDir . '/' . $placeholders['{{ ModelName }}'] . 'Controller.php';
    File::put($controllerPath, $content);
    $this->info("Controller created: {$controllerPath}");
  }

  protected function createReactView(string $viewType, array $placeholders)
  {
    $stub = File::get($this->stubsPath . "View/$viewType.React.stub");
    $content = str_replace(array_keys($placeholders), array_values($placeholders), $stub);

    $viewDir = resource_path('js/Pages/' . $placeholders['{{ AdminPath }}'] . '/' . $placeholders['{{ ModelName }}']);

    if ($viewType == 'MainForm') {
      $viewDir = resource_path('js/Pages/' . $placeholders['{{ AdminPath }}'] . '/' . $placeholders['{{ ModelName }}'] . '/Form');
    }

    if (!File::exists($viewDir)) {
      File::makeDirectory($viewDir, 0755, true);
    }

    $viewPath = $viewDir . '/' . $viewType . '.jsx';
    File::put($viewPath, $content);
    $this->info("React view created: {$viewPath}");
  }

  protected function appendRouteToWebPhp(array $placeholders)
  {
    $backofficeRoutePath = base_path('routes/backoffice.php');
    $webRoutePath = base_path('routes/web.php');

    $targetRoutePath = File::exists($backofficeRoutePath) ? $backofficeRoutePath : $webRoutePath;
    $targetRouteFileName = Str::afterLast($targetRoutePath, '/');

    $controllerClass = "App\Http\Controllers\\"
      . $placeholders['{{ SubNamespace }}']
      . "\\"
      . $placeholders['{{ ModelName }}']
      . "Controller";

    $newRoute = "    Route::resource('"
      . substr($placeholders['{{ pageUrl }}'], 5)
      . "', \\{$controllerClass}::class)->only('index', 'create', 'edit', 'store', 'update', 'destroy');";

    if (!File::exists($targetRoutePath)) {
      $this->warn("Route file not found, skipping route append.");
      return;
    }

    $routeFileContent = File::get($targetRoutePath);

    // Cegah duplikasi
    if (Str::contains($routeFileContent, $newRoute)) {
      $this->warn("Route for '" . $placeholders['{{ pageUrl }}'] . "' already exists in routes/{$targetRouteFileName}. Skipping.");
      return;
    }

    $updatedFileContent = $routeFileContent;

    // 1️⃣ Cek blok admin group
    if (preg_match('/Route::middleware\(\s*\[\'auth\',\s*\'role:admin\'\]\s*\)\s*->prefix\(\'admin\'\)\s*->name\(\'admin\.' . '\'\)\s*->group\(function\s*\(\)\s*\{([\s\S]*?)\}\);/m', $routeFileContent, $matches)) {
      $adminGroupContent = $matches[0];
      $newAdminGroupContent = substr($adminGroupContent, 0, -3) // buang "});"
        . $newRoute . "\n});";
      $updatedFileContent = str_replace($adminGroupContent, $newAdminGroupContent, $routeFileContent);

      // 2️⃣ Kalau tidak ada admin group, cek middleware auth group
    } elseif (preg_match('/Route::middleware\(\'auth\'\)->group\(function\s*\(\)\s*\{[\s\S]*?\};/m', $routeFileContent, $matches)) {
      $authGroupContent = $matches[0];
      $newAuthGroupContent = substr($authGroupContent, 0, -3)
        . "\n    " . $newRoute . "\n});";
      $updatedFileContent = str_replace($authGroupContent, $newAuthGroupContent, $routeFileContent);

      // 3️⃣ Kalau tidak ada group sama sekali, append di akhir file
    } else {
      $updatedFileContent = rtrim($routeFileContent) . "\n\n" . $newRoute . "\n";
    }

    File::put($targetRoutePath, $updatedFileContent);
    $this->info("Route '{$newRoute}' appended to routes/{$targetRouteFileName}");
  }


  protected function appendSidebarMenuEntry(array $placeholders)
  {
    $sidebarPath = resource_path('js/Layouts/AuthenticatedLayout.jsx');
    if (!File::exists($sidebarPath)) {
      $this->error("AuthenticatedLayout.jsx not found. Skipping sidebar menu update.");
      return;
    }

    $sidebarContent = File::get($sidebarPath);

    $pageUrl   = $placeholders['{{ pageUrl }}'];
    $pageLabel = $placeholders['{{ pageLabel }}'];
    $iconClass = $this->option('icon') ?? $this->iconDictionary[$placeholders['{{ tableName }}']] ?? 'fas fa-cube fa-fw';
    $prefix    = $this->option('prefix_url') ? Str::of($this->option('prefix_url'))->after('admin/')->before('/') : null;
    $isDropdown = !empty($prefix);

    // ====== Ambil sidebarMenu via regex to JSON ======
    if (!preg_match('/let\s+sidebarMenu\s*=\s*(\[.*?\]);/s', $sidebarContent, $menuMatch)) {
      $this->error("sidebarMenu not found in AuthenticatedLayout.jsx");
      return;
    }

    $arrayJs = $menuMatch[1];
    $arrayJson = preg_replace('/(\s*)(\w+)\s*:/', '$1"$2":', $arrayJs);
    $arrayJson = preg_replace('/,(\s*[\]}])/', '$1', $arrayJson);

    $menu = json_decode($arrayJson, true);
    if (json_last_error() !== JSON_ERROR_NONE) {
      $this->error("JSON Decode Error (menu): " . $menuMatch[1]);
      return;
    }

    foreach ($menu as $item) {
      if (isset($item['link']) && $item['link'] === "/{$pageUrl}") {
        $this->warn("Sidebar menu entry for '{$pageLabel}' already exists. Skipping.");
        return;
      }
      if (isset($item['dropdown'])) {
        foreach ($item['dropdown'] as $child) {
          if (isset($child['link']) && $child['link'] === "/{$pageUrl}") {
            $this->warn("Sidebar dropdown entry for '{$pageLabel}' already exists. Skipping.");
            return;
          }
        }
      }
    }

    if ($isDropdown) {
      $parentTitle = Str::of($prefix)->headline();
      $parentIcon = $this->iconDictionary[Str::plural($prefix)] ?? 'fas fa-cube fa-fw';
      $childMenuItem = [
        'title' => $pageLabel,
        'link'  => "/{$pageUrl}"
      ];

      $foundParent = false;
      foreach ($menu as &$item) {
        if ($item['title'] === $parentTitle && isset($item['dropdown'])) {
          $item['dropdown'][] = $childMenuItem;
          $foundParent = true;
          break;
        }
      }
      if (!$foundParent) {
        $menu[] = [
          'title'    => $parentTitle,
          'src'      => $parentIcon,
          'dropdown' => [$childMenuItem]
        ];
      }
    } else {
      $menu[] = [
        'title' => $pageLabel,
        'src'   => $iconClass,
        'link'  => "/{$pageUrl}"
      ];
    }

    if (preg_match('/^(\s*)routes\s*=\s*(\[[^\]]*\]);/m', $sidebarContent, $routesMatch)) {
      $routesArrayJs = $routesMatch[2];

      // Ubah ke JSON valid
      $routesJson = preg_replace('/(\s*)(\w+)\s*:/', '$1"$2":', $routesArrayJs);
      $routesJson = preg_replace('/,(\s*[\]}])/', '$1', $routesJson);

      $routesArr = json_decode($routesJson, true);

      if (json_last_error() === JSON_ERROR_NONE) {
        if (!in_array("/{$pageUrl}", $routesArr)) {
          $routesArr[] = "/{$pageUrl}";
        }

        $routesNew = json_encode($routesArr, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
        $routesNew = preg_replace_callback('/^ +/m', function ($m) {
          return str_repeat(' ', strlen($m[0]) / 2);
        }, $routesNew);
        $routesNew = preg_replace('/"([^"]+)"\s*:/', '$1:', $routesNew);


        if (preg_match('/routes\s*=\s*\[(.*?)\]/s', $sidebarContent, $match)) {
          $inside = trim($match[1]);
          if ($inside !== '') { // hanya replace kalau tidak kosong
            $sidebarContent = preg_replace(
              '/(routes\s*=\s*)\[[^\]]*\]/s',
              '$1' . $routesNew,
              $sidebarContent
            );
          }
        }
      }
    }

    // ====== Update sidebarMenu ======
    $menuJson = json_encode($menu, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
    $menuJson = preg_replace_callback('/^ +/m', function ($m) {
      return str_repeat(' ', strlen($m[0]) / 2);
    }, $menuJson);
    $menuJson = preg_replace('/"([^"]+)"\s*:/', '$1:', $menuJson);

    $sidebarContent = preg_replace(
      '/let\s+sidebarMenu\s*=\s*\[.*?\];/s',
      "let sidebarMenu = {$menuJson};",
      $sidebarContent
    );

    File::put($sidebarPath, $sidebarContent);
    $this->info("Sidebar menu entry for '{$pageLabel}' appended to AuthenticatedLayout.jsx");
  }



  protected function runFormatter(string $modelName)
  {
    $filesToFormat = [
      app_path("Http/Controllers/Admin/{$modelName}Controller.php"),
      resource_path("js/Pages/Admin/{$modelName}/Index.jsx"),
      resource_path("js/Pages/Admin/{$modelName}/Create.jsx"),
      resource_path("js/Pages/Admin/{$modelName}/Edit.jsx"),
      resource_path("js/Pages/Admin/{$modelName}/Form/MainForm.jsx"),
      // resource_path("js/Layouts/AuthenticatedLayout.jsx"),
    ];

    $this->info("Menjalankan Prettier untuk merapikan file...");

    $command = ['npx', 'prettier', '--write', ...$filesToFormat];

    $process = new Process($command);
    $process->run();

    if (!$process->isSuccessful()) {
      $this->error("Gagal menjalankan Prettier. Pastikan Prettier terinstal dan file-file yang dihasilkan sudah ada.");
      $this->error($process->getErrorOutput());
    } else {
      $this->info("File-file berhasil dirapikan.");
    }
  }

  protected function rollbackController(array $placeholders)
  {
    $controllerDir = app_path('Http/Controllers/' . $placeholders['{{ SubNamespace }}']);
    $controllerPath = $controllerDir . '/' . $placeholders['{{ ModelName }}'] . 'Controller.php';

    if (File::exists($controllerPath)) {
      File::delete($controllerPath);
      $this->info("Controller deleted: {$controllerPath}");

      if (File::isDirectory($controllerDir) && count(File::files($controllerDir)) === 0) {
        File::deleteDirectory($controllerDir);
        $this->info("Controller directory deleted: {$controllerDir}");
      }
    } else {
      $this->warn("Controller not found, skipping rollback: {$controllerPath}");
    }
  }

  protected function rollbackReactViews(array $placeholders)
  {
    $adminPath = $placeholders['{{ AdminPath }}'];
    $modelName = $placeholders['{{ ModelName }}'];

    $baseViewDir = resource_path("js/Pages/{$adminPath}/{$modelName}");
    $formViewDir = resource_path("js/Pages/{$adminPath}/{$modelName}/Form");

    $filesToDelete = [
      "{$baseViewDir}/Index.jsx",
      "{$baseViewDir}/Create.jsx",
      "{$baseViewDir}/Edit.jsx",
      "{$formViewDir}/MainForm.jsx",
    ];

    foreach ($filesToDelete as $file) {
      if (File::exists($file)) {
        File::delete($file);
        $this->info("React view deleted: {$file}");
      } else {
        $this->warn("React view not found, skipping rollback: {$file}");
      }
    }

    if (File::isDirectory($formViewDir) && count(File::allFiles($formViewDir)) === 0) {
      File::deleteDirectory($formViewDir);
      $this->info("React view directory deleted: {$formViewDir}");
    }

    if (File::isDirectory($baseViewDir) && count(File::allFiles($baseViewDir)) === 0) {
      File::deleteDirectory($baseViewDir);
      $this->info("React view directory deleted: {$baseViewDir}");
    }
  }

  protected function rollbackRoute(array $placeholders)
  {
    $backofficeRoutePath = base_path('routes/backoffice.php');
    $webRoutePath = base_path('routes/web.php');

    $targetRoutePath = File::exists($backofficeRoutePath) ? $backofficeRoutePath : $webRoutePath;
    $targetRouteFileName = Str::afterLast($targetRoutePath, '/');

    $controllerClass = "App\Http\Controllers\\" . $placeholders['{{ SubNamespace }}'] . "\\" . $placeholders['{{ ModelName }}'] . "Controller";
    $newRoute = "Route::resource('" . substr($placeholders['{{ pageUrl }}'], 5) . "', \\{$controllerClass}::class)->only('index', 'create', 'edit', 'store', 'update', 'destroy');";

    if (File::exists($targetRoutePath)) {
      $routeFileContent = File::get($targetRoutePath);
      $updatedFileContent = preg_replace('/\s*' . preg_quote($newRoute, '/') . '/', "", $routeFileContent);
      File::put($targetRoutePath, $updatedFileContent);
      $this->info("Route for '" . $placeholders['{{ pageUrl }}'] . "' rolled back from routes/{$targetRouteFileName}");
    } else {
      $this->warn("Route file not found, skipping route rollback.");
    }
  }

  /**
   * Menghapus entri menu sidebar dari AuthenticatedLayout.jsx.
   *
   * @param array $placeholders
   * @return void
   */
  protected function rollbackSidebarMenuEntry(array $placeholders)
  {
    $sidebarPath = resource_path('js/Layouts/AuthenticatedLayout.jsx');
    if (!File::exists($sidebarPath)) {
      $this->warn("AuthenticatedLayout.jsx not found, skipping sidebar menu rollback.");
      return;
    }

    $sidebarContent = File::get($sidebarPath);

    $pageUrl   = $placeholders['{{ pageUrl }}'];
    $pageLabel = $placeholders['{{ pageLabel }}'];

    if (preg_match('/let\s+sidebarMenu\s*=\s*(\[[\s\S]*?\]);/m', $sidebarContent, $matches)) {
      $arrayStr = $matches[1];

      $jsonStr = preg_replace('/(\w+):/m', '"$1":', $arrayStr);
      $jsonStr = str_replace("'", '"', $jsonStr);
      $jsonStr = preg_replace('/,\s*([\]}])/m', '$1', $jsonStr);
      $jsonStr = trim($jsonStr);

      $menu = json_decode($jsonStr, true);
      if (json_last_error() !== JSON_ERROR_NONE) {
        $this->error("JSON Decode Error (sidebarMenu): " . json_last_error_msg());
        return;
      }

      $targetLink = "/{$pageUrl}";

      foreach ($menu as &$item) {
        if (isset($item['dropdown']) && is_array($item['dropdown'])) {
          $item['dropdown'] = array_filter($item['dropdown'], function ($child) use ($targetLink) {
            return !isset($child['link']) || $child['link'] !== $targetLink;
          });
        }
      }
      unset($item);

      $menu = array_filter($menu, function ($item) use ($targetLink) {
        if (isset($item['link']) && $item['link'] === $targetLink) {
          return false;
        }
        if (isset($item['dropdown']) && is_array($item['dropdown']) && count($item['dropdown']) === 0) {
          return false;
        }
        return true;
      });

      $menu = array_values($menu);
      $newMenuJson = json_encode($menu, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
      $newMenuJs = preg_replace('/"(\w+)":/m', '$1:', $newMenuJson);

      $escapedPageUrl = preg_quote($pageUrl, '/');
      $sidebarContent = preg_replace(
        '/let\s+sidebarMenu\s*=\s*\[[\s\S]*?\];/m',
        "let sidebarMenu = {$newMenuJs};",
        $sidebarContent
      );

      $routeEntryPattern = "/(^\s*\"\/{$escapedPageUrl}\"\s*,?|,\s*\"\/{$escapedPageUrl}\")/m";
      $sidebarContent = preg_replace($routeEntryPattern, "", $sidebarContent);

      File::put($sidebarPath, $sidebarContent);
      $this->info("Sidebar menu entry for '{$pageLabel}' rolled back from AuthenticatedLayout.jsx");
    } else {
      $this->warn("sidebarMenu variable not found in AuthenticatedLayout.jsx");
    }
  }

  protected function getValidationRule(string $column, string $options, string $tableName): string
  {
    $baseRule = Str::contains($options, '->nullable()') ? 'nullable' : 'required';
    $typeRule = $this->validationDictionary[$column] ?? $this->validationDictionary['_default'];
    $typeRule = str_replace('{{ tableName }}', $tableName, $typeRule);

    return "{$baseRule}|{$typeRule}";
  }

  protected function convertArrayToJsObjectString(array $array, int $indent = 0): string
  {
    $space = str_repeat(' ', $indent);
    $jsString = "{\n";
    $entries = [];
    foreach ($array as $key => $value) {
      $entry = $space . "  '{$key}': ";
      if (is_array($value)) {
        $entry .= $this->convertArrayToJsObjectString($value, $indent + 2);
      } elseif (is_string($value)) {
        if ($value === 'true' || $value === 'false' || is_numeric($value) || Str::startsWith($value, 'props.') || Str::startsWith($value, 'params.get')) {
          $entry .= $value;
        } else {
          $entry .= "'{$value}'";
        }
      } elseif (is_bool($value)) {
        $entry .= $value ? 'true' : 'false';
      } elseif (is_numeric($value)) {
        $entry .= $value;
      } else {
        $entry .= "'{$value}'";
      }
      $entries[] = $entry;
    }
    $jsString .= implode(",\n", $entries);
    $jsString .= "\n" . $space . "}";
    return $jsString;
  }

  protected function convertFormPropertiesArrayToJsString(array $properties): string
  {
    $jsString = "[\n";
    foreach ($properties as $property) {
      $jsString .= "  [\n";
      $jsString .= "    " . $this->convertArrayToJsObjectString($property, 4) . "\n";
      $jsString .= "  ],\n";
    }
    $jsString .= "]";
    return $jsString;
  }
}
