<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;

class ApplyAuditableToModels extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'auditable:apply {--model= : Nombre del modelo específico al cual aplicar Auditable}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Aplica el trait Auditable a todos los modelos del sistema o a un modelo específico';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $specificModel = $this->option('model');

        if ($specificModel) {
            $this->applyAuditableToModel($specificModel);
        } else {
            $this->applyAuditableToAllModels();
        }

        return 0;
    }

    /**
     * Aplica el trait Auditable a un modelo específico
     * 
     * @param string $modelName
     * @return void
     */
    protected function applyAuditableToModel($modelName)
    {
        $modelPath = app_path('Models/' . $modelName . '.php');

        if (!File::exists($modelPath)) {
            $this->error("El modelo {$modelName} no existe.");
            return;
        }

        $this->modifyModelFile($modelPath, $modelName);
    }

    /**
     * Aplica el trait Auditable a todos los modelos
     * 
     * @return void
     */
    protected function applyAuditableToAllModels()
    {
        $modelFiles = File::files(app_path('Models'));
        $count = 0;

        foreach ($modelFiles as $file) {
            $filename = $file->getFilename();
            
            // Ignorar archivos que no sean modelos PHP
            if (!Str::endsWith($filename, '.php')) {
                continue;
            }

            // Obtener el nombre del modelo sin extensión
            $modelName = Str::before($filename, '.php');

            // Ignorar modelos específicos que no deberían ser auditables
            if (in_array($modelName, ['Audit'])) {
                $this->info("Ignorando modelo {$modelName}");
                continue;
            }

            $this->modifyModelFile($file->getPathname(), $modelName);
            $count++;
        }

        $this->info("Se ha aplicado el trait Auditable a {$count} modelos.");
    }

    /**
     * Modifica un archivo de modelo para añadir el trait Auditable
     * 
     * @param string $filePath
     * @param string $modelName
     * @return void
     */
    protected function modifyModelFile($filePath, $modelName)
    {
        $content = File::get($filePath);

        // Verificar si ya tiene el trait
        if (Str::contains($content, 'use Auditable;') || Str::contains($content, 'use App\Traits\Auditable;')) {
            $this->info("El modelo {$modelName} ya tiene el trait Auditable.");
            return;
        }

        // Añadir el import
        if (!Str::contains($content, 'use App\Traits\Auditable;')) {
            $content = preg_replace(
                '/namespace App\\\\Models;/',
                "namespace App\\Models;\n\nuse App\Traits\Auditable;",
                $content
            );
        }

        // Añadir el trait a la clase
        $content = preg_replace(
            '/class ' . $modelName . ' extends Model\s*{/',
            "class {$modelName} extends Model\n{\n    use Auditable;",
            $content
        );

        // Guardar el archivo modificado
        File::put($filePath, $content);
        $this->info("Se ha añadido el trait Auditable al modelo {$modelName}");
    }
}
