<?php

namespace App\Services\Module;

use App\Contracts\ModuleServiceProviderContract;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\ServiceProvider;

abstract class AbstractModuleServiceProvider extends ServiceProvider implements ModuleServiceProviderContract
{
    abstract protected function modulePath(): string;

    abstract protected function moduleSlug(): string;

    abstract protected function moduleName(): string;

    abstract protected function moduleVersion(): string;

    /**
     * @return array<string, string>
     */
    abstract protected function modulePermissions(): array;

    /**
     * @return list<array{route: string, icon: string, label: string}>
     */
    abstract protected function moduleNavigation(): array;

    public function register(): void
    {
        //
    }

    public function bootModule(): void
    {
        if (! $this->isShellModule()) {
            $this->loadMigrationsFrom($this->modulePath().'/database/migrations');
        }

        $this->loadViewsFrom($this->modulePath().'/resources/views', $this->viewNamespace());
        $this->loadRoutes();
        $this->bootPolicies();
    }

    protected function isShellModule(): bool
    {
        $manifestPath = $this->modulePath().'/module.json';

        if (! File::exists($manifestPath)) {
            return false;
        }

        $manifest = json_decode(File::get($manifestPath), true);

        return is_array($manifest) && ($manifest['type'] ?? 'full') === 'shell';
    }

    public function getSlug(): string
    {
        return $this->moduleSlug();
    }

    public function getName(): string
    {
        return $this->moduleName();
    }

    public function getVersion(): string
    {
        return $this->moduleVersion();
    }

    public function getPermissions(): array
    {
        return $this->modulePermissions();
    }

    public function getNavigationItems(): array
    {
        return $this->moduleNavigation();
    }

    protected function viewNamespace(): string
    {
        return $this->moduleSlug();
    }

    protected function routePrefix(): string
    {
        return $this->moduleSlug();
    }

    protected function routeNamePrefix(): string
    {
        return $this->moduleSlug().'.';
    }

    protected function loadRoutes(): void
    {
        $routesFile = $this->modulePath().'/routes/web.php';

        if (! File::exists($routesFile)) {
            return;
        }

        Route::middleware(['web', 'installed', 'auth', 'license'])
            ->prefix($this->routePrefix())
            ->name($this->routeNamePrefix())
            ->group($routesFile);
    }

    protected function bootPolicies(): void
    {
        //
    }
}
