<?php

declare(strict_types=1);

namespace Database\Factories;

use App\Models\ManagedEnvironment;
use App\Models\ManagedEnvironmentTriageReview;
use App\Models\User;
use App\Models\Workspace;
use App\Support\PortfolioTriage\PortfolioArrivalContextToken;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends Factory<ManagedEnvironmentTriageReview>
 */
class ManagedEnvironmentTriageReviewFactory extends Factory
{
    protected $model = ManagedEnvironmentTriageReview::class;

    /**
     * @return array<string, mixed>
     */
    public function definition(): array
    {
        $snapshot = [
            'concernFamily' => PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH,
            'concernState' => 'stale',
            'reasonCode' => 'latest_backup_stale',
            'severityKey' => 'latest_backup_stale',
            'supportingKey' => 'latest_backup_stale',
        ];

        return [
            'managed_environment_id' => ManagedEnvironment::factory()->for(Workspace::factory()),
            'workspace_id' => function (array $attributes): int {
                $tenantId = $attributes['managed_environment_id'] ?? null;

                if (! is_numeric($tenantId)) {
                    return (int) Workspace::factory()->create()->getKey();
                }

                $tenant = ManagedEnvironment::query()->whereKey((int) $tenantId)->first();

                if (! $tenant instanceof ManagedEnvironment || ! is_numeric($tenant->workspace_id)) {
                    return (int) Workspace::factory()->create()->getKey();
                }

                return (int) $tenant->workspace_id;
            },
            'concern_family' => PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH,
            'current_state' => ManagedEnvironmentTriageReview::STATE_REVIEWED,
            'reviewed_at' => now()->subMinutes(5),
            'reviewed_by_user_id' => User::factory(),
            'review_fingerprint' => $this->hashSnapshot($snapshot),
            'review_snapshot' => $snapshot,
            'last_seen_matching_at' => now()->subMinutes(5),
            'resolved_at' => null,
        ];
    }

    public function reviewed(): static
    {
        return $this->state(fn (): array => [
            'current_state' => ManagedEnvironmentTriageReview::STATE_REVIEWED,
        ]);
    }

    public function followUpNeeded(): static
    {
        return $this->state(fn (): array => [
            'current_state' => ManagedEnvironmentTriageReview::STATE_FOLLOW_UP_NEEDED,
        ]);
    }

    public function backupHealth(): static
    {
        return $this->state(function (): array {
            $snapshot = [
                'concernFamily' => PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH,
                'concernState' => 'stale',
                'reasonCode' => 'latest_backup_stale',
                'severityKey' => 'latest_backup_stale',
                'supportingKey' => 'latest_backup_stale',
            ];

            return [
                'concern_family' => PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH,
                'review_fingerprint' => $this->hashSnapshot($snapshot),
                'review_snapshot' => $snapshot,
            ];
        });
    }

    public function recoveryEvidence(): static
    {
        return $this->state(function (): array {
            $snapshot = [
                'concernFamily' => PortfolioArrivalContextToken::FAMILY_RECOVERY_EVIDENCE,
                'concernState' => 'weakened',
                'reasonCode' => 'failed',
                'severityKey' => 'failed',
                'supportingKey' => 'failed',
            ];

            return [
                'concern_family' => PortfolioArrivalContextToken::FAMILY_RECOVERY_EVIDENCE,
                'review_fingerprint' => $this->hashSnapshot($snapshot),
                'review_snapshot' => $snapshot,
            ];
        });
    }

    public function resolved(): static
    {
        return $this->state(fn (): array => [
            'resolved_at' => now()->subMinute(),
        ]);
    }

    public function active(): static
    {
        return $this->state(fn (): array => [
            'resolved_at' => null,
        ]);
    }

    public function changedFingerprint(): static
    {
        return $this->state(fn (): array => [
            'review_fingerprint' => hash('sha256', 'changed-fingerprint-'.fake()->uuid()),
        ]);
    }

    /**
     * @param  array<string, mixed>  $snapshot
     */
    private function hashSnapshot(array $snapshot): string
    {
        return hash('sha256', json_encode($snapshot, JSON_THROW_ON_ERROR));
    }
}
