<?php

declare(strict_types=1);

namespace Tests\Unit;

use App\Features\Monitoring\Services\HeartbeatHealthCalculator;
use Illuminate\Support\Carbon;
use PHPUnit\Framework\TestCase;

class HeartbeatHealthCalculatorTest extends TestCase
{
    private HeartbeatHealthCalculator $calculator;

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

    public function test_one_minute_interval_missed_counts(): void
    {
        Carbon::setTestNow('2026-06-30 12:10:00');
        $last = Carbon::parse('2026-06-30 12:00:00');

        $this->assertSame(0, $this->calculator->missedHeartbeats(30, 60));
        $this->assertSame(1, $this->calculator->missedHeartbeats(90, 60));
        $this->assertSame(2, $this->calculator->missedHeartbeats(150, 60));
        $this->assertSame(3, $this->calculator->missedHeartbeats(210, 60));

        $metrics = $this->calculator->metrics($last, 60);
        $this->assertSame(9, $metrics['missed_heartbeats']);
        $this->assertSame('critical', $metrics['heartbeat_status']);

        Carbon::setTestNow();
    }

    public function test_five_minute_interval_missed_counts(): void
    {
        Carbon::setTestNow('2026-06-30 12:16:00');
        $last = Carbon::parse('2026-06-30 12:00:00');

        $this->assertSame(0, $this->calculator->missedHeartbeats(300, 300));
        $this->assertSame(1, $this->calculator->missedHeartbeats(360, 300));
        $this->assertSame(2, $this->calculator->missedHeartbeats(660, 300));
        $this->assertSame(3, $this->calculator->missedHeartbeats(960, 300));

        $metrics = $this->calculator->metrics($last, 300);
        $this->assertSame(3, $metrics['missed_heartbeats']);
        $this->assertSame('critical', $metrics['heartbeat_status']);

        Carbon::setTestNow();
    }

    public function test_fifteen_minute_interval_stays_healthy_within_first_window(): void
    {
        Carbon::setTestNow('2026-06-30 12:10:00');
        $last = Carbon::parse('2026-06-30 12:00:00');

        $metrics = $this->calculator->metrics($last, 900);
        $this->assertSame(0, $metrics['missed_heartbeats']);
        $this->assertSame('healthy', $metrics['heartbeat_status']);

        Carbon::setTestNow();
    }

    public function test_recent_heartbeat_resets_missed_counter(): void
    {
        Carbon::setTestNow('2026-06-30 12:25:00');
        $last = Carbon::parse('2026-06-30 12:24:30');

        $metrics = $this->calculator->metrics($last, 300);
        $this->assertSame(0, $metrics['missed_heartbeats']);
        $this->assertSame('healthy', $metrics['heartbeat_status']);

        Carbon::setTestNow();
    }

    public function test_offline_threshold_uses_max_twelve_intervals_or_one_hour(): void
    {
        $this->assertSame(3600, $this->calculator->offlineThresholdSeconds(60));
        $this->assertSame(3600, $this->calculator->offlineThresholdSeconds(300));
        $this->assertSame(10800, $this->calculator->offlineThresholdSeconds(900));
    }

    public function test_offline_status_after_threshold(): void
    {
        Carbon::setTestNow('2026-06-30 13:30:00');
        $last = Carbon::parse('2026-06-30 12:00:00');

        $metrics = $this->calculator->metrics($last, 300);
        $this->assertSame('offline', $metrics['heartbeat_status']);

        Carbon::setTestNow();
    }
}
