<?php

namespace FluxCms\Components;

use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Str;
use Livewire\Livewire;
use ReflectionClass;

class FluxCmsComponentsServiceProvider extends ServiceProvider
{
    /**
     * Register services
     */
    public function register(): void
    {
        // Merge config if needed
    }

    /**
     * Bootstrap services
     */
    public function boot(): void
    {
        $this->bootViews();
        $this->bootPublishing();
        $this->bootLivewireComponents();
    }

    /**
     * Boot views
     */
    protected function bootViews(): void
    {
        $this->loadViewsFrom(__DIR__.'/../resources/views', 'flux-cms-components');
    }

    /**
     * Boot publishing
     */
    protected function bootPublishing(): void
    {
        if ($this->app->runningInConsole()) {
            // Publish views
            $this->publishes([
                __DIR__.'/../resources/views' => resource_path('views/vendor/flux-cms-components'),
            ], 'flux-cms-components-views');

            // Publish assets
            $this->publishes([
                __DIR__.'/../resources/assets' => public_path('vendor/flux-cms-components'),
            ], 'flux-cms-components-assets');
        }
    }

    /**
     * Register Livewire components
     */
    protected function bootLivewireComponents(): void
    {
        $this->registerLivewireComponentsFrom(__DIR__.'/Livewire/Backend', 'FluxCms\\Components\\Livewire\\Backend', 'flux-cms::');
        $this->registerLivewireComponentsFrom(__DIR__.'/Livewire/Frontend', 'FluxCms\\Components\\Livewire\\Frontend', 'flux-cms::');
    }

    protected function registerLivewireComponentsFrom(string $path, string $namespace, string $aliasPrefix = ''): void
    {
        $filesystem = new Filesystem;
        if (! $filesystem->isDirectory($path)) {
            return;
        }

        foreach ($filesystem->allFiles($path) as $file) {
            $class = $namespace.'\\'.str_replace(['/', '.php'], ['\\', ''], $file->getRelativePathname());

            if (class_exists($class) && is_subclass_of($class, \Livewire\Component::class) && ! (new ReflectionClass($class))->isAbstract()) {
                $alias = $aliasPrefix.Str::kebab(class_basename($class));
                Livewire::component($alias, $class);
            }
        }
    }
}
