<?php

namespace Tests\Feature;

use App\Agent\Choices;
use App\Agent\ToolRegistry;
use App\Agent\Workspace;
use App\Models\Campaign;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Laravel\Ai\Tools\Request;
use Tests\TestCase;

class OfferedCountriesTest extends TestCase
{
    use RefreshDatabase;

    /** @return array{0: string, 1: array<string, mixed>} */
    private function offeredCountries(): array
    {
        $this->actingAs(User::factory()->create());

        $workspace = app(Workspace::class);
        $workspace->bindTo('conv-countries-0001');

        $campaign = Campaign::create([
            'user_id' => auth()->id(),
            'name' => 'Winter Sale',
            'platform' => 'meta',
            'status' => 'draft',
            'objective' => 'OUTCOME_TRAFFIC',
        ]);

        $workspace->produced($campaign);

        $tool = collect(app(ToolRegistry::class)->resolve())
            ->first(fn ($t) => $t->name() === 'campaign__set_targeting');

        $result = (string) $tool->handle(new Request([]));

        return [$result, collect(app(Choices::class)->all())->firstWhere('field', 'countries')];
    }

    public function test_the_picker_offers_the_global_country_dataset_with_searchable_codes(): void
    {
        [, $choice] = $this->offeredCountries();
        $options = array_column($choice['options'], null, 'value');

        $this->assertCount(249, $options);
        $this->assertSame(['US', 'GB', 'IN', 'CA', 'AU'], array_slice(array_column($choice['options'], 'value'), 0, 5));
        $this->assertSame('France', $options['FR']['label']);
        $this->assertSame('FR', $options['FR']['hint']);
        $this->assertArrayHasKey('ZA', $options);
        $this->assertArrayHasKey('JP', $options);
        $this->assertArrayHasKey('IN', $options);
        $this->assertTrue($choice['multiple']);
        $this->assertStringContainsString('Search', $choice['question']);
    }

    public function test_countries_outside_the_old_shortlist_are_normalized_and_saved(): void
    {
        $this->offeredCountries();
        Http::fake(['*search*' => Http::response(['data' => [
            ['key' => 'FR', 'type' => 'country', 'name' => 'France'],
            ['key' => 'JP', 'type' => 'country', 'name' => 'Japan'],
        ]])]);
        $tool = collect(app(ToolRegistry::class)->resolve())
            ->first(fn ($tool) => $tool->name() === 'campaign__set_targeting');

        $result = json_decode((string) $tool->handle(new Request(['countries' => [' fr ', 'JP', 'FR']])), true);

        $this->assertTrue($result['ok']);
        $this->assertSame(['FR', 'JP'], Campaign::sole()->locations['countries']);
    }

    public function test_invalid_country_codes_do_not_change_targeting(): void
    {
        $this->offeredCountries();
        $campaign = Campaign::sole();
        $campaign->update(['locations' => ['countries' => ['US']]]);
        $tool = collect(app(ToolRegistry::class)->resolve())
            ->first(fn ($tool) => $tool->name() === 'campaign__set_targeting');

        $result = json_decode((string) $tool->handle(new Request(['countries' => ['ZZ']])), true);

        $this->assertFalse($result['ok']);
        $this->assertStringContainsString('ZZ', $result['error']);
        $this->assertSame(['US'], $campaign->fresh()->locations['countries']);
    }

    public function test_unavailable_provider_country_does_not_change_targeting(): void
    {
        $this->offeredCountries();
        $campaign = Campaign::sole();
        $campaign->update(['locations' => ['countries' => ['US']]]);
        Http::fake(['*search*' => Http::response(['data' => []])]);
        $tool = collect(app(ToolRegistry::class)->resolve())
            ->first(fn ($tool) => $tool->name() === 'campaign__set_targeting');

        $result = json_decode((string) $tool->handle(new Request(['countries' => ['CA']])), true);

        $this->assertFalse($result['ok']);
        $this->assertStringContainsString('CA', $result['error']);
        $this->assertSame(['US'], $campaign->fresh()->locations['countries']);
    }

    public function test_country_search_preserves_multiple_selections_and_submits_iso_codes(): void
    {
        [, $choice] = $this->offeredCountries();
        $command = 'node '.escapeshellarg(base_path('tests/js/choice-boxes.cjs'))
            .' '.escapeshellarg(public_path('assets/js/chat.js'))
            .' '.escapeshellarg(public_path('assets/mb/css/app.css'))
            .' '.escapeshellarg(json_encode($choice)).' 2>&1';

        $output = shell_exec($command);
        $result = json_decode((string) $output, true);

        $this->assertIsArray($result, (string) $output);
        $this->assertArrayNotHasKey('error', $result, (string) $output);
        $this->assertSame(249, $result['countries']['initialCount']);
        $this->assertSame(['France', 'Japan'], $result['countries']['picked']);
        $this->assertStringContainsString('name="answers[0][value][]"'."\r\n\r\nFR", $result['countries']['submitted']);
        $this->assertStringContainsString('name="answers[0][value][]"'."\r\n\r\nJP", $result['countries']['submitted']);
    }
}
