<?php

namespace Tests\Feature;

use App\Models\ApiToken;
use App\Models\Organization;
use App\Models\Role;
use App\Models\User;
use App\Support\Authorization\PermissionCatalog;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\PermissionRegistrar;
use Tests\TestCase;

class OwnerApiTokenSettingsTest extends TestCase
{
    use RefreshDatabase;

    public function test_owner_user_can_create_reset_and_revoke_tokens_from_settings(): void
    {
        $user = $this->makeOwnerUserWithSettingsPermission();

        $createResponse = $this->actingAs($user)
            ->post(route('owner.settings.api-tokens.store'), [
                'name' => 'n8n chatwoot',
            ]);

        $createResponse->assertRedirect(route('owner.settings.index'));
        $createResponse->assertSessionHas('api_token_plaintext');
        $this->assertDatabaseHas('api_tokens', [
            'user_id' => $user->id,
            'name' => 'n8n chatwoot',
            'revoked_at' => null,
        ]);

        $activeTokenIdsBeforeReset = ApiToken::query()
            ->where('user_id', $user->id)
            ->whereNull('revoked_at')
            ->pluck('id');

        $resetResponse = $this->actingAs($user)
            ->post(route('owner.settings.api-tokens.reset'), [
                'name' => 'token principal',
            ]);

        $resetResponse->assertRedirect(route('owner.settings.index'));
        $resetResponse->assertSessionHas('api_token_plaintext');

        foreach ($activeTokenIdsBeforeReset as $tokenId) {
            $this->assertDatabaseMissing('api_tokens', [
                'id' => $tokenId,
                'revoked_at' => null,
            ]);
        }

        $newActiveToken = ApiToken::query()
            ->where('user_id', $user->id)
            ->whereNull('revoked_at')
            ->latest('id')
            ->first();

        $this->assertNotNull($newActiveToken);
        $this->assertSame('token principal', $newActiveToken->name);

        $revokeResponse = $this->actingAs($user)
            ->post(route('owner.settings.api-tokens.revoke', $newActiveToken));

        $revokeResponse->assertRedirect(route('owner.settings.index'));
        $this->assertDatabaseMissing('api_tokens', [
            'id' => $newActiveToken->id,
            'revoked_at' => null,
        ]);
    }

    private function makeOwnerUserWithSettingsPermission(): User
    {
        app(PermissionRegistrar::class)->forgetCachedPermissions();

        $organization = Organization::query()->create([
            'name' => 'Mariachis Settings Test',
            'entity_type' => 'ORGANIZATION',
            'contact_phone' => '3000000000',
            'city' => 'Bogotá',
            'country_code' => 'CO',
            'is_active' => true,
        ]);

        $user = User::query()->create([
            'name' => 'Owner Settings',
            'email' => 'owner-settings@example.com',
            'password' => 'secret',
            'role' => User::ROLE_CLIENT,
            'organization_id' => $organization->id,
            'has_all_mariachi_groups' => true,
            'is_active' => true,
        ]);

        $permissionName = PermissionCatalog::permissionName(PermissionCatalog::PANEL_OWNER, 'settings_general', 'edit');
        Permission::findOrCreate($permissionName, 'web');
        Permission::findOrCreate(PermissionCatalog::permissionName(PermissionCatalog::PANEL_OWNER, 'settings_general', 'view'), 'web');

        $role = Role::query()->create([
            'name' => 'Owner Settings API',
            'code' => 'owner_settings_api_'.$organization->id,
            'guard_name' => 'web',
            'organization_id' => $organization->id,
            'is_system' => false,
            'is_active' => true,
        ]);
        $role->givePermissionTo([
            PermissionCatalog::permissionName(PermissionCatalog::PANEL_OWNER, 'settings_general', 'edit'),
            PermissionCatalog::permissionName(PermissionCatalog::PANEL_OWNER, 'settings_general', 'view'),
        ]);

        setPermissionsTeamId((int) $organization->id);
        $user->assignRole($role);

        return $user;
    }
}
