<?php

namespace Tests\Feature;

use App\Campaigns\Targeting\LocationDiscovery;
use App\Models\AllowedAdAccount;
use App\Models\Location;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use RuntimeException;
use Tests\TestCase;

class LocationDiscoveryTest extends TestCase
{
    use RefreshDatabase;

    private function fakeMetaCities(): void
    {
        AllowedAdAccount::factory()->meta('act_123')->create();
        config(['platforms.meta.token' => 'test-token', 'platforms.meta.version' => 'v25.0']);
        Http::preventStrayRequests();
        Http::fake([
            'https://graph.facebook.com/v25.0/search*' => Http::response(['data' => [
                ['key' => '111', 'name' => 'Springfield', 'type' => 'city', 'country_code' => 'US', 'region' => 'Illinois', 'region_id' => 101],
                ['key' => '222', 'name' => 'Springfield', 'type' => 'city', 'country_code' => 'US', 'region' => 'Missouri', 'region_id' => 102],
                ['key' => '333', 'name' => 'Springfield', 'type' => 'city', 'country_code' => 'CA'],
                ['key' => '444', 'name' => '', 'type' => 'city', 'country_code' => 'US'],
            ]]),
        ]);
    }

    public function test_search_keeps_ambiguous_cities_distinct_and_saves_only_the_reverified_choice(): void
    {
        $this->fakeMetaCities();
        $country = Location::create([
            'type' => 'country',
            'name' => 'United States',
            'country_code' => 'US',
            'iso_code' => 'US',
            'source' => 'iso_3166_1',
            'source_key' => 'US',
        ]);
        $discovery = app(LocationDiscovery::class);

        $matches = $discovery->search('meta', 'city', 'US', 'Springfield', 'act_123');

        $this->assertSame(['111', '222'], array_column($matches, 'external_id'));
        $this->assertSame(['Springfield, Illinois, US', 'Springfield, Missouri, US'], array_column($matches, 'label'));
        $this->assertDatabaseCount('platform_locations', 0);

        $selected = $discovery->select('meta', 'city', 'US', 'Springfield', '222', 'act_123');

        $this->assertSame('222', $selected->external_id);
        $this->assertSame('Springfield', $selected->location->name);
        $this->assertSame($country->getKey(), $selected->location->parent_id);
        $this->assertDatabaseCount('platform_locations', 1);
        $this->assertDatabaseCount('locations', 2);
    }

    public function test_unknown_provider_id_is_not_saved(): void
    {
        $this->fakeMetaCities();

        $this->expectException(RuntimeException::class);
        try {
            app(LocationDiscovery::class)->select('meta', 'city', 'US', 'Springfield', 'not-a-result', 'act_123');
        } finally {
            $this->assertDatabaseCount('platform_locations', 0);
        }
    }

    public function test_linkedin_city_search_remains_unavailable_until_types_are_verified(): void
    {
        Http::fake();

        $this->expectException(RuntimeException::class);
        try {
            app(LocationDiscovery::class)->search('linkedin', 'city', 'US', 'Springfield');
        } finally {
            Http::assertNothingSent();
        }
    }

    public function test_meta_search_can_reach_and_select_a_later_page(): void
    {
        AllowedAdAccount::factory()->meta('act_123')->create();
        config(['platforms.meta.token' => 'test-token', 'platforms.meta.version' => 'v25.0']);
        Location::factory()->create(['iso_code' => 'US', 'country_code' => 'US', 'source_key' => 'US']);

        Http::preventStrayRequests();
        Http::fake(function ($request) {
            parse_str((string) parse_url($request->url(), PHP_URL_QUERY), $query);

            return ($query['after'] ?? null) === 'page-two'
                ? Http::response(['data' => [
                    ['key' => 'later', 'name' => 'Springfield', 'type' => 'city', 'country_code' => 'US', 'region' => 'Oregon'],
                ]])
                : Http::response(['data' => [
                    ['key' => 'first', 'name' => 'Springfield', 'type' => 'city', 'country_code' => 'US', 'region' => 'Illinois'],
                ], 'paging' => ['cursors' => ['after' => 'page-two']]]);
        });

        $discovery = app(LocationDiscovery::class);
        $matches = $discovery->search('meta', 'city', 'US', 'Springfield', 'act_123', page: 2);

        $this->assertSame(['later'], array_column($matches, 'external_id'));
        $this->assertSame('later', $discovery->select('meta', 'city', 'US', 'Springfield', 'later', 'act_123', page: 2)->external_id);
    }
}
