<?php

declare(strict_types=1);

namespace Builder\Core\Tests;

use Builder\Core\BuilderServiceProvider;
use Builder\Core\Foundation\Concerns\HasBuilderAccess;
use Builder\Core\Foundation\Contracts\BuilderAccessible;
use Builder\Core\Models\Language;
use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Schema;
use Inertia\ServiceProvider;
use Orchestra\Testbench\TestCase as Orchestra;
use Spatie\LaravelSettings\LaravelSettingsServiceProvider;
use Spatie\Permission\PermissionServiceProvider;

class TestCase extends Orchestra
{
    protected function setUp(): void
    {
        parent::setUp();

        // Create a fake Vite hot file so Assets::tags() takes the dev-server path
        // and does not need a real built manifest in the Testbench public directory.
        $hotDir = $this->app->publicPath('vendor/builder/core');
        if (! is_dir($hotDir) && ! @mkdir($hotDir, 0755, true) && ! is_dir($hotDir)) {
            throw new \RuntimeException("Unable to create directory: {$hotDir}");
        }
        file_put_contents($hotDir.'/hot', 'http://localhost:5173');

        Factory::guessFactoryNamesUsing(
            fn (string $modelName): string => 'Builder\\Core\\Database\\Factories\\'.class_basename($modelName).'Factory'
        );

        config([
            'inertia.pages.paths' => array_merge(
                config('inertia.pages.paths', []),
                [__DIR__.'/../resources/js/Pages'],
            ),
        ]);

        Cache::forget(Language::CACHE_KEY);

        if (! Schema::hasTable('languages')) {
            Schema::create('languages', function ($table): void {
                $table->id();
                $table->string('code')->unique();
                $table->string('name');
                $table->boolean('is_active')->default(true);
                $table->boolean('is_default')->default(false);
                $table->unsignedInteger('order')->default(0);
                $table->timestamps();
            });

            /** @var array<string, string> $locales */
            $locales = config('builder.locales', ['en' => 'English']);
            $order = 0;

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

    protected function getPackageProviders($app): array
    {
        return [
            ServiceProvider::class,
            PermissionServiceProvider::class,
            LaravelSettingsServiceProvider::class,
            BuilderServiceProvider::class,
        ];
    }

    public function getEnvironmentSetUp($app): void
    {
        config()->set('app.key', 'base64:'.base64_encode(str_repeat('A', 32)));
        config()->set('database.default', 'testing');
        config()->set('database.connections.testing', [
            'driver' => 'sqlite',
            'database' => ':memory:',
            'prefix' => '',
        ]);
        config()->set('auth.guards.web.provider', 'users');
        config()->set('auth.providers.users.driver', 'eloquent');
        config()->set('auth.providers.users.model', BuilderTestUser::class);
    }
}

final class BuilderTestUser extends Authenticatable implements BuilderAccessible
{
    use HasBuilderAccess;

    protected $table = 'users';

    protected $guarded = [];
}
