<?php

namespace Tests\Feature\Master;

use App\Master\Http\Controllers\ApiUsageController;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Mtc\MercuryDataModels\ApiUsage;
use Mtc\MercuryDataModels\ApiUsageEndpoint;
use Tests\DatabaseTestCase;

class ApiUsageControllerTest extends DatabaseTestCase
{
    protected bool $needsTenantDatabase = false;

    private ApiUsageController $controller;
    private string $window;

    protected function setUp(): void
    {
        parent::setUp();
        ApiUsageEndpoint::clearIdCache();
        $this->controller = new ApiUsageController();
        $this->window = Carbon::now()->format('Y-m-d H');
    }

    public function testEndpointsReturnsBothLegacyVarcharAndNormalizedRows(): void
    {
        $this->legacyRow('legacy/raw/url', 'GET', 5);
        $this->normalizedRow('frontend/vehicles/{vehicle}', 'GET', 10);

        $data = collect($this->controller->endpoints(new Request())['data'])->keyBy('endpoint');

        $this->assertSame(5, $data['legacy/raw/url']['total_hits']);
        $this->assertSame(10, $data['frontend/vehicles/{vehicle}']['total_hits']);
    }

    public function testEndpointsAggregatesNormalizedRowsSharingOneEndpoint(): void
    {
        $endpointId = ApiUsageEndpoint::resolveId('frontend/vehicles/{vehicle}');
        $this->usageRow(['endpoint_id' => $endpointId, 'method' => 'GET', 'hits' => 4]);
        $this->usageRow(['endpoint_id' => $endpointId, 'method' => 'GET', 'hits' => 6]);

        $data = collect($this->controller->endpoints(new Request())['data'])->keyBy('endpoint');

        // Two separate api_usage rows pointing at the same endpoint collapse in the report.
        $this->assertSame(10, $data['frontend/vehicles/{vehicle}']['total_hits']);
    }

    public function testSnapshotsResolveByCoalescedEndpoint(): void
    {
        $usage = $this->normalizedRow('frontend/offers/{offer}', 'POST', 2);
        $usage->snapshots()->create(['input' => ['foo' => 'bar'], 'request_time' => 4.2]);

        $result = $this->controller->snapshots(
            new Request(['endpoint' => 'frontend/offers/{offer}']),
            substr($this->window, 0, 10),
            'tenant-a',
            'POST'
        );

        $this->assertCount(1, $result['data']);
        $this->assertEqualsWithDelta(4.2, $result['data'][0]['request_time'], 0.0001);
    }

    private function legacyRow(string $endpoint, string $method, int $hits): ApiUsage
    {
        return $this->usageRow(['endpoint' => $endpoint, 'endpoint_id' => null, 'method' => $method, 'hits' => $hits]);
    }

    private function normalizedRow(string $endpoint, string $method, int $hits): ApiUsage
    {
        return $this->usageRow([
            'endpoint_id' => ApiUsageEndpoint::resolveId($endpoint),
            'method' => $method,
            'hits' => $hits,
        ]);
    }

    private function usageRow(array $attributes): ApiUsage
    {
        return ApiUsage::query()->create(array_merge([
            'tenant_id' => 'tenant-a',
            'time_window' => $this->window,
            'avg' => 0.1,
            'min' => 0.05,
            'max' => 0.2,
        ], $attributes));
    }
}
