<?php

namespace Tests\Feature;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Tests\TestCase;

/**
 * A turn that stopped for approval still says so after a reload.
 *
 * A tool gated on approval ends its turn with the call pending and no assistant
 * text, so the row is written empty and the transcript dropped it for being
 * blank. Reloading showed "Approve and publish the campaign." answered by
 * nothing at all, as though the click had gone nowhere.
 *
 * Seen on arb-dev on 25 Sep. The approval sat unresolved, the buyer moved on to
 * the next platform, and the only record of what the product was waiting for
 * lived in the JSON of a turn that had already scrolled past. It happened four
 * times in one conversation.
 *
 * Genuinely empty turns are still dropped. The difference is whether anything
 * was pending.
 */
class AnApprovalTurnSurvivesAReloadTest extends TestCase
{
    use RefreshDatabase;

    protected User $user;

    protected function setUp(): void
    {
        parent::setUp();

        $this->user = User::factory()->create();
        $this->actingAs($this->user);
    }

    private function conversation(): string
    {
        $id = (string) Str::uuid();

        DB::table('agent_conversations')->insert([
            'id' => $id,
            'participant_type' => $this->user->getMorphClass(),
            'participant_id' => $this->user->getKey(),
            'title' => 'Publishing',
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        return $id;
    }

    private function message(string $conversation, string $role, string $content, ?string $approvalState = null): void
    {
        DB::table('agent_conversation_messages')->insert([
            'id' => (string) Str::uuid(),
            'conversation_id' => $conversation,
            'agent' => 'marketing',
            'attachments' => '[]',
            'tool_calls' => '[]',
            'tool_results' => '[]',
            'usage' => '[]',
            'meta' => '[]',
            'role' => $role,
            'content' => $content,
            'approval_state' => $approvalState,
            'created_at' => now()->addMicroseconds(DB::table('agent_conversation_messages')->count() + 1),
            'updated_at' => now(),
        ]);
    }

    /** The defect: the click appears to have gone nowhere. */
    public function test_an_approval_pending_turn_is_shown_rather_than_dropped(): void
    {
        $conversation = $this->conversation();

        $this->message($conversation, 'user', 'Approve and publish the campaign.');
        $this->message($conversation, 'assistant', '', json_encode(['pending' => ['fc_084ca6' => null]]));

        $this->get(route('chat.show', ['conversation' => $conversation]))
            ->assertOk()
            ->assertSee('Waiting for your approval before anything is sent to the platform.', escape: false);
    }

    /** A turn that was simply empty is still dropped, as it always was. */
    public function test_a_genuinely_empty_turn_is_still_dropped(): void
    {
        $conversation = $this->conversation();

        $this->message($conversation, 'user', 'Hello');
        $this->message($conversation, 'assistant', '');

        $this->get(route('chat.show', ['conversation' => $conversation]))
            ->assertOk()
            ->assertDontSee('Waiting for your approval', escape: false);
    }

    /** And a turn that did speak keeps its own words. */
    public function test_a_turn_with_text_is_unchanged(): void
    {
        $conversation = $this->conversation();

        $this->message($conversation, 'user', 'What next?');
        $this->message($conversation, 'assistant', 'Choose the campaign objective.', json_encode(['pending' => []]));

        $this->get(route('chat.show', ['conversation' => $conversation]))
            ->assertOk()
            ->assertSee('Choose the campaign objective.', escape: false)
            ->assertDontSee('Waiting for your approval', escape: false);
    }

    /** An empty approval state is not a pending approval. */
    public function test_an_empty_pending_list_is_not_treated_as_waiting(): void
    {
        $conversation = $this->conversation();

        $this->message($conversation, 'user', 'Approve and publish the campaign.');
        $this->message($conversation, 'assistant', '', json_encode(['pending' => []]));

        $this->get(route('chat.show', ['conversation' => $conversation]))
            ->assertOk()
            ->assertDontSee('Waiting for your approval', escape: false);
    }
}
