<?php

use App\Models\User;
use App\Http\Middleware\HandleInertiaRequests;
use cPad\Plugins\Forum\Models\ForumBoard;
use cPad\Plugins\Forum\Models\ForumCategory;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

uses(Tests\TestCase::class);

beforeEach(function (): void {
    $this->withoutMiddleware(HandleInertiaRequests::class);

    createForumRestrictedCategoryAccessSchema();

    config()->set('forum.category_role_access', [
        'administrators-and-moderators-forum' => ['admin', 'manager'],
    ]);
});

it('hides restricted forum categories from guests and regular users', function () {
    seedForumAccessBoards();

    $this->get(route('forum.index'))
        ->assertOk()
        ->assertDontSee('Administrators and Moderators Forum')
        ->assertSee('Public Forum');

    $member = makeForumAccessUser('member-role', 'user');

    $this->actingAs($member)
        ->get(route('forum.index'))
        ->assertOk()
        ->assertDontSee('Administrators and Moderators Forum')
        ->assertSee('Public Forum');

    $this->get(route('forum.category.show', ['categorySlug' => 'administrators-and-moderators-forum']))->assertNotFound();
    $this->get(route('forum.board.show', ['boardSlug' => 'administrators-and-moderators-forum']))->assertNotFound();

    $this->actingAs($member)
        ->get(route('forum.category.show', ['categorySlug' => 'administrators-and-moderators-forum']))
        ->assertNotFound();

    $this->actingAs($member)
        ->get(route('forum.board.show', ['boardSlug' => 'administrators-and-moderators-forum']))
        ->assertNotFound();
});

it('allows admin and manager roles to access restricted forum categories', function () {
    seedForumAccessBoards();

    $admin = makeForumAccessUser('admin-role', 'admin');
    $manager = makeForumAccessUser('manager-role', 'manager');

    $this->actingAs($admin)
        ->get(route('forum.index'))
        ->assertOk()
        ->assertSee('Administrators and Moderators Forum');

    $this->actingAs($admin)
        ->get(route('forum.category.show', ['categorySlug' => 'administrators-and-moderators-forum']))
        ->assertOk();

    $this->actingAs($admin)
        ->get(route('forum.board.show', ['boardSlug' => 'administrators-and-moderators-forum']))
        ->assertOk();

    $this->actingAs($manager)
        ->get(route('forum.index'))
        ->assertOk()
        ->assertSee('Administrators and Moderators Forum');

    $this->actingAs($manager)
        ->get(route('forum.category.show', ['categorySlug' => 'administrators-and-moderators-forum']))
        ->assertOk();

    $this->actingAs($manager)
        ->get(route('forum.board.show', ['boardSlug' => 'administrators-and-moderators-forum']))
        ->assertOk();
});

function createForumRestrictedCategoryAccessSchema(): void
{
    foreach (['forum_posts', 'forum_topics', 'forum_boards', 'forum_categories', 'user_profiles', 'users'] as $table) {
        Schema::dropIfExists($table);
    }

    Schema::create('users', function (Blueprint $table): void {
        $table->id();
        $table->string('username')->nullable();
        $table->timestamp('username_changed_at')->nullable();
        $table->timestamp('last_username_change_at')->nullable();
        $table->string('onboarding_step')->nullable();
        $table->string('name')->nullable();
        $table->string('email')->nullable();
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password')->nullable();
        $table->boolean('is_active')->default(true);
        $table->string('role')->nullable();
        $table->rememberToken();
        $table->timestamps();
        $table->softDeletes();
    });

    Schema::create('user_profiles', function (Blueprint $table): void {
        $table->unsignedBigInteger('user_id')->primary();
        $table->string('avatar_hash')->nullable();
        $table->timestamps();
    });

    Schema::create('forum_categories', function (Blueprint $table): void {
        $table->id();
        $table->string('name')->nullable();
        $table->string('title')->nullable();
        $table->string('slug')->unique();
        $table->text('description')->nullable();
        $table->unsignedBigInteger('parent_id')->nullable();
        $table->integer('position')->default(0);
        $table->boolean('is_active')->default(true);
        $table->timestamps();
    });

    Schema::create('forum_boards', function (Blueprint $table): void {
        $table->id();
        $table->foreignId('category_id')->constrained('forum_categories')->cascadeOnDelete();
        $table->unsignedBigInteger('legacy_category_id')->nullable();
        $table->string('title');
        $table->string('slug')->unique();
        $table->text('description')->nullable();
        $table->string('icon')->nullable();
        $table->string('image')->nullable();
        $table->integer('position')->default(0);
        $table->boolean('is_active')->default(true);
        $table->boolean('is_read_only')->default(false);
        $table->timestamps();
    });

    Schema::create('forum_topics', function (Blueprint $table): void {
        $table->id();
        $table->foreignId('board_id')->constrained('forum_boards')->cascadeOnDelete();
        $table->foreignId('user_id')->nullable()->constrained('users')->nullOnDelete();
        $table->unsignedBigInteger('artwork_id')->nullable();
        $table->unsignedBigInteger('legacy_thread_id')->nullable();
        $table->string('title');
        $table->string('slug')->unique();
        $table->unsignedInteger('views')->default(0);
        $table->unsignedInteger('replies_count')->default(0);
        $table->boolean('is_pinned')->default(false);
        $table->boolean('is_locked')->default(false);
        $table->boolean('is_deleted')->default(false);
        $table->unsignedBigInteger('last_post_id')->nullable();
        $table->timestamp('last_post_at')->nullable();
        $table->timestamps();
    });

    Schema::create('forum_posts', function (Blueprint $table): void {
        $table->id();
        $table->unsignedBigInteger('thread_id')->nullable();
        $table->foreignId('topic_id')->nullable()->constrained('forum_topics')->nullOnDelete();
        $table->foreignId('user_id')->nullable()->constrained('users')->nullOnDelete();
        $table->text('content')->nullable();
        $table->boolean('is_edited')->default(false);
        $table->timestamp('edited_at')->nullable();
        $table->timestamps();
        $table->softDeletes();
    });
}

function seedForumAccessBoards(): array
{
    $restrictedCategory = ForumCategory::query()->create([
        'title' => 'Administrators and Moderators Forum',
        'slug' => 'administrators-and-moderators-forum',
        'description' => 'Restricted board.',
        'is_active' => true,
        'position' => 1,
    ]);

    $publicCategory = ForumCategory::query()->create([
        'title' => 'Public Forum',
        'slug' => 'public-forum',
        'description' => 'Visible to everyone.',
        'is_active' => true,
        'position' => 2,
    ]);

    $restrictedBoard = ForumBoard::query()->create([
        'category_id' => $restrictedCategory->id,
        'title' => 'Administrators and Moderators Forum',
        'slug' => 'administrators-and-moderators-forum',
        'description' => 'Restricted board.',
        'is_active' => true,
        'position' => 1,
    ]);

    $publicBoard = ForumBoard::query()->create([
        'category_id' => $publicCategory->id,
        'title' => 'Public Forum',
        'slug' => 'public-forum',
        'description' => 'Visible to everyone.',
        'is_active' => true,
        'position' => 1,
    ]);

    return [$restrictedCategory, $publicCategory, $restrictedBoard, $publicBoard];
}

function makeForumAccessUser(string $username, string $role): User
{
    return User::query()->create([
        'username' => $username,
        'username_changed_at' => now()->subDays(120),
        'last_username_change_at' => now()->subDays(120),
        'onboarding_step' => 'complete',
        'name' => ucfirst($role) . ' User',
        'email' => $username . '@example.com',
        'email_verified_at' => now(),
        'password' => 'password',
        'is_active' => true,
        'role' => $role,
    ]);
}