<?php

declare(strict_types=1);

namespace Builder\Core\Foundation\Commands;

use Builder\Core\Foundation\Registry;
use Builder\Core\Foundation\Resources\Resource;
use Builder\Core\Models\Language;
use Illuminate\Console\Command;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Hash;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;

final class InstallCommand extends Command
{
    protected $signature = 'builder:install';

    protected $description = 'Install Builder: seeds permissions and creates default roles';

    public function __construct(private readonly Registry $registry)
    {
        parent::__construct();
    }

    public function handle(): int
    {
        // Collect permissions from registered resources + extra registered permissions + core defaults
        $permissions = collect($this->registry->resources())
            ->map(fn (string $resourceClass): Resource => new $resourceClass)
            ->flatMap(fn (Resource $resource): array => $resource->getPermissionSet())
            ->merge($this->registry->getRegisteredPermissions())
            ->merge(['read:admin', 'read:settings', 'manage:settings'])
            ->unique()
            ->sort()
            ->values();

        foreach ($permissions as $name) {
            Permission::firstOrCreate(['name' => $name, 'guard_name' => 'web']);
        }

        $sysAdminRole = Role::firstOrCreate(['name' => 'System administrator', 'guard_name' => 'web']);
        $sysAdminRole->syncPermissions($permissions->all());

        $this->seedLanguages();

        $this->info('Builder installed successfully!');

        if ($this->confirm('Would you like to create an administrator user now?')) {
            $name = $this->ask('Name');
            $email = $this->ask('Email address');
            $password = $this->secret('Password');

            /** @var class-string<Model> $modelClass */
            $modelClass = config('auth.providers.users.model');
            $user = (new $modelClass)->forceFill([
                'name' => $name,
                'email' => $email,
                'password' => Hash::make($password),
                'activated_at' => now(),
            ]);
            $user->save();

            if (method_exists($user, 'assignRole')) {
                $user->assignRole('System administrator');
                $this->info("Administrator user [{$email}] created and assigned the 'System administrator' role.");
            } else {
                $this->info("Administrator user [{$email}] created.");
            }
        }

        return self::SUCCESS;
    }

    private function seedLanguages(): void
    {
        if (Language::count() > 0) {
            return;
        }

        $first = true;

        foreach (config('builder.locales', []) as $code => $name) {
            Language::create([
                'code' => $code,
                'name' => $name,
                'is_active' => true,
                'is_default' => $first,
                'order' => 0,
            ]);

            $first = false;
        }
    }
}
