<?php

namespace Tests\Unit;

use App\Models\NotificationMap;
use App\NotificationMaps\NotificationOpenApiGenerator;
use Tests\TestCase;

class NotificationOpenApiGeneratorTest extends TestCase
{
    private function makeMap(): NotificationMap
    {
        $map = new NotificationMap();
        $map->name = 'Partner Feed';
        $map->slug = 'partner-feed';
        $map->field_map = [
            ['source' => 'stock_id', 'destination' => 'uuid', 'type' => 'string'],
            ['source' => 'price', 'destination' => 'price', 'type' => 'float'],
            ['source' => 'mileage', 'destination' => 'odometer_mi', 'type' => 'integer'],
            ['source' => 'vehicle.registration', 'destination' => 'registration_number', 'type' => 'string'],
            ['source' => 'media', 'destination' => 'images', 'type' => 'image_list'],
        ];
        $map->validation = ['uuid' => ['required', 'string']];
        $map->config = ['images' => ['url_key' => 'href']];

        return $map;
    }

    public function test_it_builds_a_path_for_the_inbound_endpoint(): void
    {
        $doc = (new NotificationOpenApiGenerator())->generate($this->makeMap());

        $this->assertSame('3.0.0', $doc['openapi']);
        $this->assertArrayHasKey('/api/notifications/{tenant}/partner-feed', $doc['paths']);
        $this->assertArrayHasKey('post', $doc['paths']['/api/notifications/{tenant}/partner-feed']);
    }

    public function test_request_schema_reflects_types_and_required(): void
    {
        $doc = (new NotificationOpenApiGenerator())->generate($this->makeMap());
        $schema = $doc['paths']['/api/notifications/{tenant}/partner-feed']['post']['requestBody']
            ['content']['application/json']['schema'];

        $props = $schema['properties'];
        $this->assertSame('string', $props['stock_id']['type']);
        $this->assertSame('number', $props['price']['type']);
        $this->assertSame('integer', $props['mileage']['type']);

        // Required is derived from the validation rule on the mapped destination.
        $this->assertContains('stock_id', $schema['required']);
    }

    public function test_nested_source_paths_become_nested_objects(): void
    {
        $doc = (new NotificationOpenApiGenerator())->generate($this->makeMap());
        $schema = $doc['paths']['/api/notifications/{tenant}/partner-feed']['post']['requestBody']
            ['content']['application/json']['schema'];

        $this->assertSame('object', $schema['properties']['vehicle']['type']);
        $this->assertSame('string', $schema['properties']['vehicle']['properties']['registration']['type']);
    }

    public function test_image_list_allows_strings_or_objects_with_configured_key(): void
    {
        $doc = (new NotificationOpenApiGenerator())->generate($this->makeMap());
        $schema = $doc['paths']['/api/notifications/{tenant}/partner-feed']['post']['requestBody']
            ['content']['application/json']['schema'];

        $items = $schema['properties']['media']['items'];
        $this->assertSame('array', $schema['properties']['media']['type']);
        $this->assertSame('string', $items['oneOf'][0]['type']);
        $this->assertArrayHasKey('href', $items['oneOf'][1]['properties']);
    }
}
