<?php

declare(strict_types=1);

use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentTriageReview;
use App\Models\User;
use App\Support\BackupHealth\BackupFreshnessEvaluation;
use App\Support\BackupHealth\BackupScheduleFollowUpEvaluation;
use App\Support\BackupHealth\TenantBackupHealthAssessment;
use App\Support\PortfolioTriage\PortfolioArrivalContextToken;
use App\Support\PortfolioTriage\ManagedEnvironmentTriageReviewStateResolver;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

function triageResolverBackupAssessment(int $tenantId, string $posture, ?string $reason = null): TenantBackupHealthAssessment
{
    return new TenantBackupHealthAssessment(
        tenantId: $tenantId,
        posture: $posture,
        primaryReason: $reason,
        headline: 'Headline',
        supportingMessage: 'Supporting message',
        latestRelevantBackupSetId: null,
        latestRelevantCompletedAt: now()->subMinutes(10),
        qualitySummary: null,
        freshnessEvaluation: new BackupFreshnessEvaluation(
            latestCompletedAt: now()->subMinutes(10),
            cutoffAt: now()->subHour(),
            isFresh: $posture === TenantBackupHealthAssessment::POSTURE_HEALTHY,
        ),
        scheduleFollowUp: new BackupScheduleFollowUpEvaluation(
            hasEnabledSchedules: false,
            enabledScheduleCount: 0,
            overdueScheduleCount: 0,
            failedRecentRunCount: 0,
            neverSuccessfulCount: 0,
            needsFollowUp: false,
            primaryScheduleId: null,
            summaryMessage: null,
        ),
        healthyClaimAllowed: $posture === TenantBackupHealthAssessment::POSTURE_HEALTHY,
        primaryActionTarget: null,
        positiveClaimBoundary: 'Boundary',
    );
}

it('resolves active review rows into current-set summaries', function (): void {
    $firstTenant = ManagedEnvironment::factory()->create(['status' => 'active']);
    [$reviewer, $firstTenant] = createUserWithTenant(tenant: $firstTenant, role: 'owner');

    $secondTenant = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $firstTenant->workspace_id,
    ]);
    createUserWithTenant(tenant: $secondTenant, user: $reviewer, role: 'owner');

    $thirdTenant = ManagedEnvironment::factory()->create([
        'status' => 'active',
        'workspace_id' => (int) $firstTenant->workspace_id,
    ]);
    createUserWithTenant(tenant: $thirdTenant, user: $reviewer, role: 'owner');

    ManagedEnvironmentTriageReview::factory()
        ->for($firstTenant)
        ->for($reviewer, 'reviewer')
        ->reviewed()
        ->backupHealth()
        ->create([
            'workspace_id' => (int) $firstTenant->workspace_id,
        ]);

    ManagedEnvironmentTriageReview::factory()
        ->for($secondTenant)
        ->for($reviewer, 'reviewer')
        ->followUpNeeded()
        ->backupHealth()
        ->create([
            'workspace_id' => (int) $firstTenant->workspace_id,
        ]);

    $resolved = app(ManagedEnvironmentTriageReviewStateResolver::class)->resolveMany(
        workspaceId: (int) $firstTenant->workspace_id,
        tenantIds: [(int) $firstTenant->getKey(), (int) $secondTenant->getKey(), (int) $thirdTenant->getKey()],
        backupHealthByTenant: [
            (int) $firstTenant->getKey() => triageResolverBackupAssessment(
                tenantId: (int) $firstTenant->getKey(),
                posture: TenantBackupHealthAssessment::POSTURE_STALE,
                reason: TenantBackupHealthAssessment::REASON_LATEST_BACKUP_STALE,
            ),
            (int) $secondTenant->getKey() => triageResolverBackupAssessment(
                tenantId: (int) $secondTenant->getKey(),
                posture: TenantBackupHealthAssessment::POSTURE_STALE,
                reason: TenantBackupHealthAssessment::REASON_LATEST_BACKUP_STALE,
            ),
            (int) $thirdTenant->getKey() => triageResolverBackupAssessment(
                tenantId: (int) $thirdTenant->getKey(),
                posture: TenantBackupHealthAssessment::POSTURE_STALE,
                reason: TenantBackupHealthAssessment::REASON_LATEST_BACKUP_STALE,
            ),
        ],
    );

    $summary = $resolved['summaries'][PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH];

    expect($resolved['rows'][(int) $firstTenant->getKey()][PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH]['derived_state'])
        ->toBe(ManagedEnvironmentTriageReview::STATE_REVIEWED)
        ->and($resolved['rows'][(int) $secondTenant->getKey()][PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH]['derived_state'])
        ->toBe(ManagedEnvironmentTriageReview::STATE_FOLLOW_UP_NEEDED)
        ->and($resolved['rows'][(int) $thirdTenant->getKey()][PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH]['derived_state'])
        ->toBe(ManagedEnvironmentTriageReview::DERIVED_STATE_NOT_REVIEWED)
        ->and($summary['affected_total'])->toBe(3)
        ->and($summary['reviewed_count'])->toBe(1)
        ->and($summary['follow_up_needed_count'])->toBe(1)
        ->and($summary['changed_since_review_count'])->toBe(0)
        ->and($summary['not_reviewed_count'])->toBe(1);
});

it('prefers changed-since-review when the current fingerprint no longer matches', function (): void {
    $tenant = ManagedEnvironment::factory()->create(['status' => 'active']);
    [$reviewer, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    ManagedEnvironmentTriageReview::factory()
        ->for($tenant)
        ->for($reviewer, 'reviewer')
        ->reviewed()
        ->backupHealth()
        ->changedFingerprint()
        ->create([
            'workspace_id' => (int) $tenant->workspace_id,
        ]);

    $resolved = app(ManagedEnvironmentTriageReviewStateResolver::class)->resolveMany(
        workspaceId: (int) $tenant->workspace_id,
        tenantIds: [(int) $tenant->getKey()],
        backupHealthByTenant: [
            (int) $tenant->getKey() => triageResolverBackupAssessment(
                tenantId: (int) $tenant->getKey(),
                posture: TenantBackupHealthAssessment::POSTURE_STALE,
                reason: TenantBackupHealthAssessment::REASON_LATEST_BACKUP_STALE,
            ),
        ],
    );

    $row = $resolved['rows'][(int) $tenant->getKey()][PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH];

    expect($row['derived_state'])->toBe(ManagedEnvironmentTriageReview::DERIVED_STATE_CHANGED_SINCE_REVIEW)
        ->and($resolved['summaries'][PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH]['changed_since_review_count'])->toBe(1);
});

it('excludes inactive concern families from the current affected set', function (): void {
    $tenant = ManagedEnvironment::factory()->create(['status' => 'active']);
    [$reviewer, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    ManagedEnvironmentTriageReview::factory()
        ->for($tenant)
        ->for($reviewer, 'reviewer')
        ->reviewed()
        ->backupHealth()
        ->create([
            'workspace_id' => (int) $tenant->workspace_id,
        ]);

    $resolved = app(ManagedEnvironmentTriageReviewStateResolver::class)->resolveMany(
        workspaceId: (int) $tenant->workspace_id,
        tenantIds: [(int) $tenant->getKey()],
        backupHealthByTenant: [
            (int) $tenant->getKey() => triageResolverBackupAssessment(
                tenantId: (int) $tenant->getKey(),
                posture: TenantBackupHealthAssessment::POSTURE_HEALTHY,
            ),
        ],
    );

    expect($resolved['rows'][(int) $tenant->getKey()][PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH]['current_concern_present'])
        ->toBeFalse()
        ->and($resolved['summaries'][PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH]['affected_total'])->toBe(0);
});
