<?php

namespace Maestro\Core\Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Support\Facades\Hash;
use Maestro\Core\Models\Organization;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Traits\HasRoles;

class UserSeeder extends Seeder
{
    public function run(): void
    {
        $userClass = $this->userModelClass();

        $guard = config('auth.defaults.guard');
        $guardName = is_string($guard) && $guard !== '' ? $guard : 'web';

        $permissionNames = [
            'activitylog.view',
            'settings.organization.view',
            'settings.organization.edit',
            'users.view',
            'users.create',
            'users.edit',
            'users.delete',
            'users.assign-roles',
            'roles.view',
            'roles.create',
            'roles.edit',
            'roles.delete',
        ];

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

        $adminRole = Role::firstOrCreate([
            'name' => 'admin',
            'guard_name' => $guardName,
        ]);

        $adminRole->givePermissionTo(
            Permission::query()
                ->where('guard_name', $guardName)
                ->whereIn('name', $permissionNames)
                ->get(),
        );

        $organization = Organization::query()->updateOrCreate(
            ['id' => 1],
            [
                'name' => 'Maestro Demo BV',
                'company_name' => 'Maestro Demo BV',
                'street' => 'Stationsplein 1',
                'address_line_1' => 'Stationsplein 1',
                'city' => 'Amsterdam',
                'postal_code' => '1012 AB',
                'country_code' => 'nl',
                'country' => 'Nederland',
            ],
        );

        $user = $userClass::query()->updateOrCreate(
            ['email' => 'demo@example.com'],
            [
                'name' => 'Demo Admin',
                'password' => Hash::make('password'),
                'organization_id' => $organization->id,
                'email_verified_at' => now(),
                'is_active' => true,
            ],
        );

        $user->syncRoles(['admin']);
    }

    /** @return class-string<\Illuminate\Contracts\Auth\Authenticatable&\Illuminate\Database\Eloquent\Model> */
    private function userModelClass(): string
    {
        /** @var mixed $configured */
        $configured = config('auth.providers.users.model');

        $class = $configured;

        $class = is_string($class) ? $class : null;

        if ($class === null || ! class_exists($class)) {
            throw new \LogicException('auth.providers.users.model must name an existing User class for Maestro\\Core\\Database\\Seeders\\UserSeeder.');
        }

        $usesHasRoles = in_array(
            HasRoles::class,
            class_uses_recursive($class),
            true,
        );

        if (! is_subclass_of($class, Authenticatable::class) || ! $usesHasRoles) {
            throw new \LogicException(sprintf(
                'Maestro CORE requires `%s` to extend `%s` and use `%s`. Run `php artisan core:install` or extend `Maestro\\Core\\Models\\User`.',
                $class,
                Authenticatable::class,
                HasRoles::class,
            ));
        }

        /** @phpstan-ignore-next-line Laravel auth model satisfies contract */
        return $class;
    }
}
