<?php

namespace Database\Factories;

use App\Models\AlertDelivery;
use App\Models\AlertDestination;
use App\Models\AlertRule;
use App\Models\ManagedEnvironment;
use App\Models\Workspace;
use Illuminate\Database\Eloquent\Factories\Factory;

/**
 * @extends Factory<AlertDelivery>
 */
class AlertDeliveryFactory extends Factory
{
    protected $model = AlertDelivery::class;

    public function definition(): array
    {
        return [
            // managed_environment_id and alert_rule_id are nullable; test() state sets them to null.
            // Default definition creates a tenant-scoped delivery.
            'managed_environment_id' => ManagedEnvironment::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) {
                    return (int) Workspace::factory()->create()->getKey();
                }

                if ($tenant->workspace_id === null) {
                    $workspaceId = (int) Workspace::factory()->create()->getKey();
                    $tenant->forceFill(['workspace_id' => $workspaceId])->save();

                    return $workspaceId;
                }

                return (int) $tenant->workspace_id;
            },
            'alert_rule_id' => function (array $attributes): int {
                $workspaceId = is_numeric($attributes['workspace_id'] ?? null)
                    ? (int) $attributes['workspace_id']
                    : (int) Workspace::factory()->create()->getKey();

                return (int) AlertRule::factory()->create([
                    'workspace_id' => $workspaceId,
                ])->getKey();
            },
            'alert_destination_id' => function (array $attributes): int {
                $workspaceId = is_numeric($attributes['workspace_id'] ?? null)
                    ? (int) $attributes['workspace_id']
                    : (int) Workspace::factory()->create()->getKey();

                return (int) AlertDestination::factory()->create([
                    'workspace_id' => $workspaceId,
                ])->getKey();
            },
            'event_type' => AlertRule::EVENT_HIGH_DRIFT,
            'severity' => 'high',
            'status' => AlertDelivery::STATUS_QUEUED,
            'fingerprint_hash' => hash('sha256', fake()->uuid()),
            'send_after' => null,
            'attempt_count' => 0,
            'last_error_code' => null,
            'last_error_message' => null,
            'sent_at' => null,
            'payload' => [
                'title' => 'Alert',
                'body' => 'Delivery payload',
            ],
        ];
    }

    /**
     * A tenantless test delivery for a specific destination.
     */
    public function test(): static
    {
        return $this->state(fn (array $attributes): array => [
            'managed_environment_id' => null,
            'alert_rule_id' => null,
            'event_type' => AlertDelivery::EVENT_TYPE_TEST,
            'severity' => null,
            'fingerprint_hash' => 'test:'.($attributes['alert_destination_id'] instanceof \Closure ? 0 : ($attributes['alert_destination_id'] ?? 0)),
            'payload' => [
                'title' => 'Test alert',
                'body' => 'This is a test delivery for destination verification.',
            ],
        ]);
    }
}
