<?php

namespace Tests\Feature\Master;

use App\Master\Http\Controllers\CronLogController;
use App\Models\CronLog;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Tests\DatabaseTestCase;

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

    private CronLogController $controller;

    protected function setUp(): void
    {
        parent::setUp();
        $this->controller = new CronLogController();
    }

    public function testDefaultsToAllRuns(): void
    {
        $this->log(['command' => 'clear:audit', 'tenant_id' => null]);
        $this->log(['command' => 'reservations:ingest', 'tenant_id' => 'site-a']);

        $result = $this->controller->index(new Request());

        $this->assertSame(2, $result['logs']->total());
    }

    public function testFiltersToMasterRuns(): void
    {
        $this->log(['command' => 'clear:audit', 'tenant_id' => null]);
        $this->log(['command' => 'reservations:ingest', 'tenant_id' => 'site-a']);

        $result = $this->controller->index(new Request(['tenant' => 'master']));

        $this->assertSame(1, $result['logs']->total());
        $this->assertSame('clear:audit', $result['logs']->first()->command);
    }

    public function testFiltersByTenant(): void
    {
        $this->log(['command' => 'clear:audit', 'tenant_id' => null]);
        $this->log(['command' => 'reservations:ingest', 'tenant_id' => 'site-a']);
        $this->log(['command' => 'reservations:ingest', 'tenant_id' => 'site-b']);

        $result = $this->controller->index(new Request(['tenant' => 'site-a']));

        $this->assertSame(1, $result['logs']->total());
        $this->assertSame('site-a', $result['logs']->first()->tenant_id);
    }

    public function testFiltersByCommandAndStatus(): void
    {
        $this->log(['command' => 'clear:audit', 'tenant_id' => null, 'status' => CronLog::STATUS_COMPLETED]);
        $this->log(['command' => 'clear:audit', 'tenant_id' => null, 'status' => CronLog::STATUS_FAILED]);
        $this->log(['command' => 'api-usage:flush', 'tenant_id' => null, 'status' => CronLog::STATUS_COMPLETED]);

        $byCommand = $this->controller->index(new Request(['command' => 'clear:audit']));
        $this->assertSame(2, $byCommand['logs']->total());

        $byStatus = $this->controller->index(new Request([
            'command' => 'clear:audit',
            'status' => CronLog::STATUS_FAILED,
        ]));
        $this->assertSame(1, $byStatus['logs']->total());
    }

    public function testReturnsTenantAndCommandFilterOptions(): void
    {
        $this->log(['command' => 'clear:audit', 'tenant_id' => null]);
        $this->log(['command' => 'reservations:ingest', 'tenant_id' => 'site-a']);

        $result = $this->controller->index(new Request());

        // Only tenants that actually appear in the logs are offered (master excluded).
        $this->assertEqualsCanonicalizing(['site-a'], array_column($result['tenants'], 'id'));
        $this->assertSame('site-a', $result['tenants'][0]['name']); // falls back to id when no Tenant row
        $this->assertEqualsCanonicalizing(['clear:audit', 'reservations:ingest'], $result['commands']);
    }

    /**
     * @param  array<string, mixed>  $attributes
     */
    private function log(array $attributes): CronLog
    {
        return CronLog::query()->create(array_merge([
            'command' => 'clear:audit',
            'status' => CronLog::STATUS_COMPLETED,
            'exit_code' => 0,
            'started_at' => Carbon::now(),
            'finished_at' => Carbon::now(),
            'duration_ms' => 1200,
        ], $attributes));
    }
}
