<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Str;

class MakeThrillWikiLivewire extends Command
{
    /**
     * The name and signature of the console command.
     */
    protected $signature = 'make:thrillwiki-livewire {name : The name of the component} 
                                                   {--reusable : Generate a reusable component with optimization traits}
                                                   {--with-tests : Generate test files for the component}
                                                   {--cached : Add caching optimization to the component}
                                                   {--paginated : Add pagination support to the component}
                                                   {--force : Overwrite existing files}';

    /**
     * The console command description.
     */
    protected $description = 'Create a ThrillWiki-optimized Livewire component with built-in patterns and performance optimization';

    protected Filesystem $files;

    public function __construct(Filesystem $files)
    {
        parent::__construct();
        $this->files = $files;
    }

    /**
     * Execute the console command.
     */
    public function handle(): int
    {
        $name = $this->argument('name');
        $className = Str::studly($name);
        $kebabName = Str::kebab($name);
        
        $this->info("🚀 Generating ThrillWiki Livewire Component: {$className}");

        // Generate the component class
        $this->generateComponent($className, $kebabName);
        
        // Generate the view file
        $this->generateView($className, $kebabName);
        
        // Generate tests if requested
        if ($this->option('with-tests')) {
            $this->generateTest($className);
        }

        $this->displaySummary($className, $kebabName);
        
        return Command::SUCCESS;
    }

    protected function generateComponent(string $className, string $kebabName): void
    {
        $componentPath = app_path("Livewire/{$className}.php");
        
        if ($this->files->exists($componentPath) && !$this->option('force')) {
            $this->error("Component {$className} already exists! Use --force to overwrite.");
            return;
        }

        $stub = $this->getComponentStub();
        $content = $this->replaceStubPlaceholders($stub, $className, $kebabName);
        
        $this->files->ensureDirectoryExists(dirname($componentPath));
        $this->files->put($componentPath, $content);
        
        $this->info("✅ Component created: app/Livewire/{$className}.php");
    }

    protected function generateView(string $className, string $kebabName): void
    {
        $viewPath = resource_path("views/livewire/{$kebabName}.blade.php");
        
        if ($this->files->exists($viewPath) && !$this->option('force')) {
            $this->error("View {$kebabName}.blade.php already exists! Use --force to overwrite.");
            return;
        }

        $stub = $this->getViewStub();
        $content = $this->replaceViewPlaceholders($stub, $className, $kebabName);
        
        $this->files->ensureDirectoryExists(dirname($viewPath));
        $this->files->put($viewPath, $content);
        
        $this->info("✅ View created: resources/views/livewire/{$kebabName}.blade.php");
    }

    protected function generateTest(string $className): void
    {
        $testPath = base_path("tests/Feature/Livewire/{$className}Test.php");
        
        if ($this->files->exists($testPath) && !$this->option('force')) {
            $this->error("Test {$className}Test already exists! Use --force to overwrite.");
            return;
        }

        $stub = $this->getTestStub();
        $content = $this->replaceTestPlaceholders($stub, $className);
        
        $this->files->ensureDirectoryExists(dirname($testPath));
        $this->files->put($testPath, $content);
        
        $this->info("✅ Test created: tests/Feature/Livewire/{$className}Test.php");
    }

    protected function getComponentStub(): string
    {
        $traits = [];
        $imports = ['use Livewire\Component;'];
        $properties = [];
        $methods = [];

        // Add pagination if requested
        if ($this->option('paginated')) {
            $imports[] = 'use Livewire\WithPagination;';
            $traits[] = 'WithPagination';
            $properties[] = '    protected $paginationTheme = \'tailwind\';';
        }

        // Add caching optimization if requested
        if ($this->option('cached') || $this->option('reusable')) {
            $imports[] = 'use Illuminate\Support\Facades\Cache;';
            $methods[] = $this->getCachingMethods();
        }

        // Build traits string
        $traitsString = empty($traits) ? '' : "\n    use " . implode(', ', $traits) . ";\n";
        
        // Build properties string
        $propertiesString = empty($properties) ? '' : "\n" . implode("\n", $properties) . "\n";
        
        // Build methods string
        $methodsString = implode("\n\n", $methods);

        return <<<PHP
<?php

namespace App\Livewire;

{IMPORTS}

class {CLASS_NAME} extends Component
{{TRAITS}{PROPERTIES}
    /**
     * Component initialization
     */
    public function mount(): void
    {
        // Initialize component state
    }

    /**
     * Render the component
     */
    public function render()
    {
        return view('livewire.{VIEW_NAME}');
    }{METHODS}
}
PHP;
    }

    protected function getViewStub(): string
    {
        if ($this->option('reusable')) {
            return <<<BLADE
{{-- ThrillWiki Reusable Component: {CLASS_NAME} --}}
<div class="thrillwiki-component" 
     x-data="{ loading: false }"
     wire:loading.class="opacity-50">
     
    {{-- Component Header --}}
    <div class="component-header mb-4">
        <h3 class="text-lg font-semibold text-gray-900 dark:text-white">
            {CLASS_NAME}
        </h3>
    </div>

    {{-- Component Content --}}
    <div class="component-content">
        <p class="text-gray-600 dark:text-gray-400">
            ThrillWiki component content goes here.
        </p>
        
        {{-- Example interactive element --}}
        <button wire:click="\$refresh"
                class="mt-4 px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors">
            Refresh Component
        </button>
    </div>

    {{-- Loading State --}}
    <div wire:loading wire:target="\$refresh" 
         class="absolute inset-0 bg-white bg-opacity-75 flex items-center justify-center">
        <div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div>
    </div>
</div>
BLADE;
        }

        return <<<BLADE
{{-- ThrillWiki Component: {CLASS_NAME} --}}
<div class="thrillwiki-component">
    <h3 class="text-lg font-semibold mb-4 text-gray-900 dark:text-white">
        {CLASS_NAME}
    </h3>
    
    <p class="text-gray-600 dark:text-gray-400">
        ThrillWiki component content goes here.
    </p>
</div>
BLADE;
    }

    protected function getTestStub(): string
    {
        return <<<PHP
<?php

namespace Tests\Feature\Livewire;

use App\Livewire\{CLASS_NAME};
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Tests\TestCase;

class {CLASS_NAME}Test extends TestCase
{
    use RefreshDatabase;

    /** @test */
    public function component_can_render(): void
    {
        Livewire::test({CLASS_NAME}::class)
            ->assertStatus(200)
            ->assertSee('{CLASS_NAME}');
    }

    /** @test */
    public function component_can_mount_successfully(): void
    {
        Livewire::test({CLASS_NAME}::class)
            ->assertStatus(200);
    }

    /** @test */
    public function component_follows_thrillwiki_patterns(): void
    {
        Livewire::test({CLASS_NAME}::class)
            ->assertViewIs('livewire.{VIEW_NAME}');
    }
}
PHP;
    }

    protected function getCachingMethods(): string
    {
        return <<<PHP
    /**
     * Get cache key for this component
     */
    protected function getCacheKey(string \$suffix = ''): string
    {
        return 'thrillwiki.' . class_basename(static::class) . '.' . \$suffix;
    }

    /**
     * Remember data with caching
     */
    protected function remember(string \$key, \$callback, int \$ttl = 3600)
    {
        return Cache::remember(\$this->getCacheKey(\$key), \$ttl, \$callback);
    }

    /**
     * Invalidate component cache
     */
    protected function invalidateCache(string \$key = null): void
    {
        if (\$key) {
            Cache::forget(\$this->getCacheKey(\$key));
        } else {
            // Clear all cache for this component
            Cache::flush();
        }
    }
PHP;
    }

    protected function replaceStubPlaceholders(string $stub, string $className, string $kebabName): string
    {
        $imports = ['use Livewire\Component;'];
        $traits = [];

        if ($this->option('paginated')) {
            $imports[] = 'use Livewire\WithPagination;';
            $traits[] = 'WithPagination';
        }

        if ($this->option('cached') || $this->option('reusable')) {
            $imports[] = 'use Illuminate\Support\Facades\Cache;';
        }

        $traitsString = empty($traits) ? '' : "\n    use " . implode(', ', $traits) . ";\n";
        $importsString = implode("\n", $imports);
        $methodsString = '';

        if ($this->option('cached') || $this->option('reusable')) {
            $methodsString = "\n\n" . $this->getCachingMethods();
        }

        return str_replace(
            ['{IMPORTS}', '{CLASS_NAME}', '{VIEW_NAME}', '{TRAITS}', '{PROPERTIES}', '{METHODS}'],
            [$importsString, $className, $kebabName, $traitsString, '', $methodsString],
            $stub
        );
    }

    protected function replaceViewPlaceholders(string $stub, string $className, string $kebabName): string
    {
        return str_replace(
            ['{CLASS_NAME}', '{VIEW_NAME}'],
            [$className, $kebabName],
            $stub
        );
    }

    protected function replaceTestPlaceholders(string $stub, string $className): string
    {
        return str_replace(
            ['{CLASS_NAME}', '{VIEW_NAME}'],
            [$className, Str::kebab($className)],
            $stub
        );
    }

    protected function displaySummary(string $className, string $kebabName): void
    {
        $this->newLine();
        $this->info("🎉 ThrillWiki Livewire Component '{$className}' created successfully!");
        $this->newLine();
        
        $this->comment("📁 Files Generated:");
        $this->line("   • app/Livewire/{$className}.php");
        $this->line("   • resources/views/livewire/{$kebabName}.blade.php");
        
        if ($this->option('with-tests')) {
            $this->line("   • tests/Feature/Livewire/{$className}Test.php");
        }

        $this->newLine();
        $this->comment("🚀 Features Added:");
        
        if ($this->option('reusable')) {
            $this->line("   • Reusable component patterns with optimization traits");
        }
        
        if ($this->option('cached')) {
            $this->line("   • Caching optimization methods");
        }
        
        if ($this->option('paginated')) {
            $this->line("   • Pagination support with Tailwind theme");
        }
        
        if ($this->option('with-tests')) {
            $this->line("   • Automated test suite with ThrillWiki patterns");
        }

        $this->newLine();
        $this->comment("📝 Next Steps:");
        $this->line("   1. Customize the component logic in app/Livewire/{$className}.php");
        $this->line("   2. Update the view template in resources/views/livewire/{$kebabName}.blade.php");
        $this->line("   3. Include the component in your templates with <livewire:{$kebabName} />");
        
        if ($this->option('with-tests')) {
            $this->line("   4. Run tests with: php artisan test --filter {$className}Test");
        }

        $this->newLine();
        $this->info("✨ Happy coding with ThrillWiki acceleration patterns!");
    }
}