<?php

namespace Tests\Feature;

use App\Models\AutoTraderLocationStatus;
use Carbon\Carbon;
use Tests\DatabaseTestCase;

class AutoTraderLocationStatusTest extends DatabaseTestCase
{
    public function testAccessFailureIncrementsConsecutiveFailures(): void
    {
        AutoTraderLocationStatus::recordCheck('tenant-x', '111', 403);
        AutoTraderLocationStatus::recordCheck('tenant-x', '111', 401);

        $status = AutoTraderLocationStatus::query()
            ->forTenant('tenant-x')
            ->where('advertiser_id', '111')
            ->first();

        $this->assertSame(2, $status->consecutive_failures);
        $this->assertNotNull($status->last_failure_at);
        $this->assertStringContainsString('401', $status->last_error);
    }

    public function testSuccessResetsFailureAndAlertState(): void
    {
        AutoTraderLocationStatus::recordCheck('tenant-x', '111', 403);

        $status = AutoTraderLocationStatus::query()
            ->forTenant('tenant-x')
            ->where('advertiser_id', '111')
            ->first();
        $status->update(['last_alerted_at' => Carbon::now(), 'alert_count' => 2]);

        AutoTraderLocationStatus::recordCheck('tenant-x', '111', 200);

        $status->refresh();
        $this->assertSame(0, $status->consecutive_failures);
        $this->assertNull($status->last_error);
        $this->assertNull($status->last_alerted_at);
        $this->assertSame(0, $status->alert_count);
        $this->assertNotNull($status->last_success_at);
    }

    public function testTransientStatusLeavesStateUnchanged(): void
    {
        AutoTraderLocationStatus::recordCheck('tenant-x', '111', 500);

        $this->assertSame(0, AutoTraderLocationStatus::query()->forTenant('tenant-x')->count());
    }

    public function testIsDueForAlertFollowsFibonacciGate(): void
    {
        $status = new AutoTraderLocationStatus([
            'tenant_id' => 'tenant-x',
            'advertiser_id' => '111',
            'consecutive_failures' => 3,
            'alert_count' => 0,
            'last_alerted_at' => null,
        ]);

        // Never alerted while failing -> due immediately.
        $this->assertTrue($status->isDueForAlert());

        // alert_count 0 -> 1 day gap.
        $status->last_alerted_at = Carbon::now()->subHours(12);
        $this->assertFalse($status->isDueForAlert());
        $status->last_alerted_at = Carbon::now()->subDays(1);
        $this->assertTrue($status->isDueForAlert());

        // alert_count 3 -> 3 day gap.
        $status->alert_count = 3;
        $status->last_alerted_at = Carbon::now()->subDays(2);
        $this->assertFalse($status->isDueForAlert());
        $status->last_alerted_at = Carbon::now()->subDays(3);
        $this->assertTrue($status->isDueForAlert());
    }

    public function testIsDueForAlertFalseWhenNotFailing(): void
    {
        $status = new AutoTraderLocationStatus([
            'tenant_id' => 'tenant-x',
            'advertiser_id' => '111',
            'consecutive_failures' => 0,
        ]);

        $this->assertFalse($status->isDueForAlert());
    }
}
