<?php

namespace App\Jobs;

use App\Jobs\Middleware\TrackOperationRun;
use App\Models\BackupItem;
use App\Models\BackupSet;
use App\Models\OperationRun;
use App\Models\Policy;
use App\Models\PolicyVersion;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Services\Intune\FoundationSnapshotService;
use App\Services\Intune\PolicyCaptureOrchestrator;
use App\Services\Intune\SnapshotValidator;
use App\Services\Intune\VersionService;
use App\Services\OperationRunService;
use App\Support\OpsUx\RunFailureSanitizer;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Database\QueryException;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Throwable;

class AddPoliciesToBackupSetJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $timeout = 240;

    public bool $failOnTimeout = true;

    public ?OperationRun $operationRun = null;

    /**
     * @param  array<int, int>  $policyIds
     * @param  array{include_assignments?: bool, include_scope_tags?: bool, include_foundations?: bool}  $options
     */
    public function __construct(
        public int $tenantId,
        public int $userId,
        public int $backupSetId,
        public array $policyIds,
        public array $options,
        public string $idempotencyKey,
        ?OperationRun $operationRun = null
    ) {
        $this->operationRun = $operationRun;
    }

    public function middleware(): array
    {
        return [new TrackOperationRun];
    }

    public function handle(
        OperationRunService $operationRunService,
        PolicyCaptureOrchestrator $captureOrchestrator,
        FoundationSnapshotService $foundationSnapshots,
        SnapshotValidator $snapshotValidator,
        VersionService $versionService,
    ): void {
        if (! $this->operationRun instanceof OperationRun) {
            return;
        }

        $tenant = ManagedEnvironment::query()->find($this->tenantId);
        $initiator = User::query()->find($this->userId);

        $policyIds = $this->normalizePolicyIds($this->policyIds);
        $includeAssignments = (bool) ($this->options['include_assignments'] ?? false);
        $includeScopeTags = (bool) ($this->options['include_scope_tags'] ?? false);
        $includeFoundations = (bool) ($this->options['include_foundations'] ?? false);

        try {
            if (! $tenant instanceof ManagedEnvironment) {
                $this->failRun(
                    operationRunService: $operationRunService,
                    tenant: null,
                    code: 'tenant.not_found',
                    message: 'ManagedEnvironment not found for run.',
                    initiator: $initiator,
                );

                return;
            }

            $backupSet = BackupSet::withTrashed()
                ->where('managed_environment_id', $tenant->getKey())
                ->whereKey($this->backupSetId)
                ->first();

            if (! $backupSet) {
                $this->failRun(
                    operationRunService: $operationRunService,
                    tenant: $tenant,
                    code: 'backup_set.not_found',
                    message: 'Backup set not found.',
                    initiator: $initiator,
                );

                return;
            }

            if ($backupSet->trashed()) {
                $this->failRun(
                    operationRunService: $operationRunService,
                    tenant: $tenant,
                    code: 'backup_set.archived',
                    message: 'Backup set is archived.',
                    initiator: $initiator,
                );

                return;
            }

            $this->operationRun->update([
                'context' => array_merge($this->operationRun->context ?? [], [
                    'backup_set_id' => (int) $backupSet->getKey(),
                    'policy_ids' => $policyIds,
                    'options' => [
                        'include_assignments' => $includeAssignments,
                        'include_scope_tags' => $includeScopeTags,
                        'include_foundations' => $includeFoundations,
                    ],
                    'idempotency_key' => $this->idempotencyKey,
                ]),
            ]);

            $existingCounts = is_array($this->operationRun->summary_counts ?? null)
                ? $this->operationRun->summary_counts
                : [];
            $basePolicyCount = count($policyIds);

            $this->operationRun = $operationRunService->updateRun(
                $this->operationRun,
                status: 'running',
                outcome: 'pending',
                summaryCounts: array_merge($existingCounts, [
                    'total' => max((int) ($existingCounts['total'] ?? 0), $basePolicyCount),
                    'items' => max((int) ($existingCounts['items'] ?? 0), $basePolicyCount),
                    'processed' => (int) ($existingCounts['processed'] ?? 0),
                    'succeeded' => (int) ($existingCounts['succeeded'] ?? 0),
                    'failed' => (int) ($existingCounts['failed'] ?? 0),
                    'skipped' => (int) ($existingCounts['skipped'] ?? 0),
                    'created' => (int) ($existingCounts['created'] ?? 0),
                    'updated' => (int) ($existingCounts['updated'] ?? 0),
                ]),
            );

            if ($policyIds === []) {
                $operationRunService->updateRun(
                    $this->operationRun,
                    status: 'completed',
                    outcome: 'failed',
                    failures: [[
                        'code' => 'selection.empty',
                        'message' => 'No policies selected.',
                    ]],
                );

                $this->notifyRunFailed($initiator, $tenant, 'No policies selected.');

                return;
            }

            $existingBackupFailures = (array) Arr::get($backupSet->metadata ?? [], 'failures', []);
            $newBackupFailures = [];

            $didMutateBackupSet = false;
            $backupSetItemMutations = 0;
            $foundationMutations = 0;
            $foundationFailures = 0;

            /** @var array<int, int> $activePolicyIds */
            $activePolicyIds = BackupItem::query()
                ->where('backup_set_id', $backupSet->getKey())
                ->whereIn('policy_id', $policyIds)
                ->pluck('policy_id')
                ->filter()
                ->map(fn (mixed $value): int => (int) $value)
                ->values()
                ->all();

            $activePolicyIdSet = array_fill_keys($activePolicyIds, true);

            /** @var EloquentCollection<int, BackupItem> $trashedItems */
            $trashedItems = BackupItem::onlyTrashed()
                ->where('backup_set_id', $backupSet->getKey())
                ->whereIn('policy_id', $policyIds)
                ->get()
                ->keyBy('policy_id');

            /** @var EloquentCollection<int, Policy> $policies */
            $policies = Policy::query()
                ->where('managed_environment_id', $tenant->getKey())
                ->whereIn('id', $policyIds)
                ->get()
                ->keyBy('id');

            $runFailuresForOperationRun = [];

            foreach ($policyIds as $policyId) {
                if (isset($activePolicyIdSet[$policyId])) {
                    $operationRunService->incrementSummaryCounts($this->operationRun, [
                        'processed' => 1,
                        'skipped' => 1,
                    ]);

                    continue;
                }

                $trashed = $trashedItems->get($policyId);

                if ($trashed instanceof BackupItem) {
                    $trashed->restore();

                    $activePolicyIdSet[$policyId] = true;
                    $didMutateBackupSet = true;
                    $backupSetItemMutations++;

                    $operationRunService->incrementSummaryCounts($this->operationRun, [
                        'processed' => 1,
                        'succeeded' => 1,
                        'updated' => 1,
                    ]);

                    continue;
                }

                $policy = $policies->get($policyId);

                if (! $policy instanceof Policy) {
                    $newBackupFailures[] = [
                        'policy_id' => $policyId,
                        'reason' => RunFailureSanitizer::sanitizeMessage('Policy not found.'),
                        'status' => null,
                        'reason_code' => 'policy_not_found',
                    ];
                    $didMutateBackupSet = true;

                    $operationRunService->incrementSummaryCounts($this->operationRun, [
                        'processed' => 1,
                        'failed' => 1,
                    ]);

                    $runFailuresForOperationRun[] = [
                        'code' => 'policy.not_found',
                        'message' => "Policy {$policyId} not found.",
                    ];

                    continue;
                }

                if (! $policy->isCurrentBackupEligible()) {
                    $reasonCode = match ($policy->currentBackupBlockedReason()) {
                        Policy::VISIBILITY_PROVIDER_MISSING => 'policy_provider_missing',
                        Policy::VISIBILITY_IGNORED_LOCALLY => 'policy_ignored_locally',
                        default => 'policy_not_current_backup_eligible',
                    };
                    $reason = $policy->currentBackupBlockedReasonLabel()
                        ?? 'Policy is not eligible for current backup capture.';

                    $newBackupFailures[] = [
                        'policy_id' => $policyId,
                        'reason' => RunFailureSanitizer::sanitizeMessage($reason),
                        'status' => null,
                        'reason_code' => $reasonCode,
                    ];
                    $didMutateBackupSet = true;

                    $operationRunService->incrementSummaryCounts($this->operationRun, [
                        'processed' => 1,
                        'failed' => 1,
                    ]);

                    $runFailuresForOperationRun[] = [
                        'code' => str_replace('_', '.', $reasonCode),
                        'message' => RunFailureSanitizer::sanitizeMessage($reason),
                    ];

                    continue;
                }

                try {
                    $captureResult = $captureOrchestrator->capture(
                        policy: $policy,
                        tenant: $tenant,
                        includeAssignments: $includeAssignments,
                        includeScopeTags: $includeScopeTags,
                        createdBy: $initiator?->email ? Str::limit((string) $initiator->email, 255, '') : null,
                        metadata: [
                            'source' => 'backup',
                            'backup_set_id' => $backupSet->getKey(),
                        ],
                    );
                } catch (Throwable $throwable) {
                    $reason = RunFailureSanitizer::sanitizeMessage($throwable->getMessage());

                    $newBackupFailures[] = [
                        'policy_id' => $policyId,
                        'reason' => $reason,
                        'status' => null,
                        'reason_code' => 'unknown',
                    ];
                    $didMutateBackupSet = true;

                    $operationRunService->incrementSummaryCounts($this->operationRun, [
                        'processed' => 1,
                        'failed' => 1,
                    ]);

                    $runFailuresForOperationRun[] = [
                        'code' => 'policy.capture_exception',
                        'message' => $reason,
                    ];

                    continue;
                }

                if (isset($captureResult['failure']) && is_array($captureResult['failure'])) {
                    $failure = $captureResult['failure'];
                    $status = isset($failure['status']) && is_numeric($failure['status']) ? (int) $failure['status'] : null;
                    $reasonCode = $this->mapGraphFailureReasonCode($status);
                    $reason = RunFailureSanitizer::sanitizeMessage((string) ($failure['reason'] ?? 'Graph capture failed.'));

                    $newBackupFailures[] = [
                        'policy_id' => $policyId,
                        'reason' => $reason,
                        'status' => $status,
                        'reason_code' => $reasonCode,
                    ];
                    $didMutateBackupSet = true;

                    $operationRunService->incrementSummaryCounts($this->operationRun, [
                        'processed' => 1,
                        'failed' => 1,
                    ]);

                    $runFailuresForOperationRun[] = [
                        'code' => "graph.{$reasonCode}",
                        'message' => $reason,
                    ];

                    continue;
                }

                $version = $captureResult['version'] ?? null;
                $captured = $captureResult['captured'] ?? null;

                if (! $version || ! is_array($captured)) {
                    $newBackupFailures[] = [
                        'policy_id' => $policyId,
                        'reason' => RunFailureSanitizer::sanitizeMessage('Capture result missing version payload.'),
                        'status' => null,
                        'reason_code' => 'unknown',
                    ];
                    $didMutateBackupSet = true;

                    $operationRunService->incrementSummaryCounts($this->operationRun, [
                        'processed' => 1,
                        'failed' => 1,
                    ]);

                    $runFailuresForOperationRun[] = [
                        'code' => 'capture.missing_payload',
                        'message' => 'Capture result missing version payload.',
                    ];

                    continue;
                }

                $payload = $captured['payload'] ?? [];
                $metadata = is_array($captured['metadata'] ?? null) ? $captured['metadata'] : [];
                $assignments = is_array($captured['assignments'] ?? null) ? $captured['assignments'] : null;
                $scopeTags = is_array($captured['scope_tags'] ?? null) ? $captured['scope_tags'] : null;

                if (! is_array($payload)) {
                    $payload = [];
                }

                $validation = $snapshotValidator->validate($payload);
                $warnings = $validation['warnings'] ?? [];

                $odataWarning = BackupItem::odataTypeWarning($payload, $policy->policy_type, $policy->platform);

                if ($odataWarning) {
                    $warnings[] = $odataWarning;
                }

                if (! empty($warnings)) {
                    $existingWarnings = is_array($metadata['warnings'] ?? null) ? $metadata['warnings'] : [];
                    $metadata['warnings'] = array_values(array_unique(array_merge($existingWarnings, $warnings)));
                }

                if (is_array($scopeTags)) {
                    $metadata['scope_tag_ids'] = $scopeTags['ids'] ?? null;
                    $metadata['scope_tag_names'] = $scopeTags['names'] ?? null;
                }

                try {
                    BackupItem::create([
                        'managed_environment_id' => $tenant->getKey(),
                        'backup_set_id' => $backupSet->getKey(),
                        'policy_id' => $policy->getKey(),
                        'policy_version_id' => $version->getKey(),
                        'policy_identifier' => $policy->external_id,
                        'policy_type' => $policy->policy_type,
                        'platform' => $policy->platform,
                        'payload' => $payload,
                        'metadata' => $metadata,
                        'assignments' => $assignments,
                    ]);
                } catch (QueryException $exception) {
                    if ((string) $exception->getCode() === '23505') {
                        $operationRunService->incrementSummaryCounts($this->operationRun, [
                            'processed' => 1,
                            'skipped' => 1,
                        ]);

                        continue;
                    }

                    throw $exception;
                }

                $activePolicyIdSet[$policyId] = true;
                $didMutateBackupSet = true;
                $backupSetItemMutations++;

                $operationRunService->incrementSummaryCounts($this->operationRun, [
                    'processed' => 1,
                    'succeeded' => 1,
                    'created' => 1,
                ]);
            }

            if ($includeFoundations) {
                [$foundationOutcome, $foundationFailureEntries] = $this->captureFoundations(
                    foundationSnapshots: $foundationSnapshots,
                    snapshotValidator: $snapshotValidator,
                    versionService: $versionService,
                    operationRunService: $operationRunService,
                    tenant: $tenant,
                    backupSet: $backupSet,
                    createdBy: $initiator?->email ? Str::limit((string) $initiator->email, 255, '') : null,
                );

                if (($foundationOutcome['created'] ?? 0) > 0 || ($foundationOutcome['restored'] ?? 0) > 0) {
                    $didMutateBackupSet = true;
                    $foundationMutations = (int) $foundationOutcome['created'] + (int) $foundationOutcome['restored'];
                }

                if ($foundationFailureEntries !== []) {
                    $didMutateBackupSet = true;
                    $foundationFailures = count($foundationFailureEntries);
                    $newBackupFailures = array_merge($newBackupFailures, $foundationFailureEntries);

                    foreach ($foundationFailureEntries as $foundationFailure) {
                        $runFailuresForOperationRun[] = [
                            'code' => 'foundation.capture_failed',
                            'message' => (string) ($foundationFailure['reason'] ?? 'Foundation capture failed.'),
                        ];
                    }
                }
            }

            if ($didMutateBackupSet) {
                $allFailures = array_merge($existingBackupFailures, $newBackupFailures);
                $mutations = $backupSetItemMutations + $foundationMutations;

                $backupSetStatus = match (true) {
                    $mutations === 0 && count($allFailures) > 0 => 'failed',
                    count($allFailures) > 0 => 'partial',
                    default => 'completed',
                };

                $backupSet->update([
                    'status' => $backupSetStatus,
                    'item_count' => $backupSet->items()->count(),
                    'completed_at' => now(),
                    'metadata' => ['failures' => $allFailures],
                ]);
            }

            $this->operationRun->refresh();

            $counts = is_array($this->operationRun->summary_counts) ? $this->operationRun->summary_counts : [];
            $failed = (int) ($counts['failed'] ?? 0);
            $succeeded = (int) ($counts['succeeded'] ?? 0);
            $skipped = (int) ($counts['skipped'] ?? 0);

            $outcome = 'succeeded';
            if ($failed > 0 && $succeeded > 0) {
                $outcome = 'partially_succeeded';
            }
            if ($failed > 0 && $succeeded === 0) {
                $outcome = 'failed';
            }

            $operationRunService->updateRun(
                $this->operationRun,
                status: 'completed',
                outcome: $outcome,
                failures: $runFailuresForOperationRun,
            );

        } catch (Throwable $throwable) {
            $this->failRun(
                operationRunService: $operationRunService,
                tenant: $tenant instanceof ManagedEnvironment ? $tenant : null,
                code: 'exception.unhandled',
                message: $throwable->getMessage(),
                initiator: $initiator,
            );

            // TrackOperationRun will catch this throw
            throw $throwable;
        }
    }

    /**
     * @param  array<int, int>  $policyIds
     * @return array<int>
     */
    private function normalizePolicyIds(array $policyIds): array
    {
        $policyIds = array_values(array_unique(array_map('intval', $policyIds)));
        $policyIds = array_values(array_filter($policyIds, fn (int $value): bool => $value > 0));
        sort($policyIds);

        return $policyIds;
    }

    private function failRun(
        OperationRunService $operationRunService,
        ?ManagedEnvironment $tenant,
        string $code,
        string $message,
        ?User $initiator = null,
    ): void {
        $safeMessage = RunFailureSanitizer::sanitizeMessage($message);
        $safeCode = RunFailureSanitizer::sanitizeCode($code);

        $operationRunService->updateRun(
            $this->operationRun,
            status: 'completed',
            outcome: 'failed',
            failures: [[
                'code' => $safeCode,
                'message' => $safeMessage,
            ]],
        );

    }

    private function mapGraphFailureReasonCode(?int $status): string
    {
        return match (true) {
            $status === 403 => 'graph_forbidden',
            in_array($status, [429, 503], true) => 'graph_throttled',
            in_array($status, [408, 500, 502, 504], true) => 'graph_transient',
            default => 'unknown',
        };
    }

    /**
     * @return array{0:array{created:int,restored:int,failures:array<int,array{foundation_type:string,reason:string,status:int|string|null,reason_code:string}>},1:array<int,array{foundation_type:string,reason:string,status:int|string|null,reason_code:string}>}
     */
    private function captureFoundations(
        FoundationSnapshotService $foundationSnapshots,
        SnapshotValidator $snapshotValidator,
        VersionService $versionService,
        OperationRunService $operationRunService,
        ManagedEnvironment $tenant,
        BackupSet $backupSet,
        ?string $createdBy = null,
    ): array {
        $types = config('tenantpilot.foundation_types', []);
        $created = 0;
        $restored = 0;
        $failures = [];

        foreach ($types as $typeConfig) {
            $foundationType = $typeConfig['type'] ?? null;

            if (! is_string($foundationType) || $foundationType === '') {
                continue;
            }

            $result = $foundationSnapshots->fetchAll($tenant, $foundationType);

            foreach (($result['failures'] ?? []) as $failure) {
                if (! is_array($failure)) {
                    continue;
                }

                $status = isset($failure['status']) && is_numeric($failure['status']) ? (int) $failure['status'] : null;
                $reasonCode = $this->mapGraphFailureReasonCode($status);
                $reason = RunFailureSanitizer::sanitizeMessage((string) ($failure['reason'] ?? 'Foundation capture failed.'));

                $failures[] = [
                    'foundation_type' => $foundationType,
                    'reason' => $reason,
                    'status' => $status,
                    'reason_code' => $reasonCode,
                ];

                $operationRunService->incrementSummaryCounts($this->operationRun, [
                    'total' => 1,
                    'items' => 1,
                    'processed' => 1,
                    'failed' => 1,
                ]);
            }

            foreach (($result['items'] ?? []) as $snapshot) {
                if (! is_array($snapshot)) {
                    continue;
                }

                $sourceId = $snapshot['source_id'] ?? null;

                if (! is_string($sourceId) || $sourceId === '') {
                    continue;
                }

                $existing = BackupItem::withTrashed()
                    ->where('backup_set_id', $backupSet->getKey())
                    ->where('policy_type', $foundationType)
                    ->where('policy_identifier', $sourceId)
                    ->first();

                if ($existing) {
                    if ($existing->trashed()) {
                        $existing->restore();
                        $restored++;

                        $operationRunService->incrementSummaryCounts($this->operationRun, [
                            'total' => 1,
                            'items' => 1,
                            'processed' => 1,
                            'succeeded' => 1,
                            'updated' => 1,
                        ]);
                    } else {
                        $operationRunService->incrementSummaryCounts($this->operationRun, [
                            'total' => 1,
                            'items' => 1,
                            'processed' => 1,
                            'skipped' => 1,
                        ]);
                    }

                    continue;
                }

                $payload = is_array($snapshot['payload'] ?? null) ? $snapshot['payload'] : [];
                $metadata = is_array($snapshot['metadata'] ?? null) ? $snapshot['metadata'] : [];
                $platform = is_string($typeConfig['platform'] ?? null) ? $typeConfig['platform'] : null;

                if ($this->supportsFoundationVersioning($foundationType)) {
                    $policy = $this->resolveFoundationPolicy(
                        tenant: $tenant,
                        foundationType: $foundationType,
                        sourceId: $sourceId,
                        platform: $platform,
                        payload: $payload,
                        metadata: $metadata,
                    );

                    $version = $versionService->captureFoundationVersion(
                        policy: $policy,
                        payload: $payload,
                        createdBy: $createdBy,
                        metadata: array_merge(
                            $metadata,
                            [
                                'foundation_type' => $foundationType,
                                'source' => 'backup_foundation',
                            ],
                        ),
                    );

                    $this->createFoundationBackupItem(
                        tenant: $tenant,
                        backupSet: $backupSet,
                        snapshotValidator: $snapshotValidator,
                        foundationType: $foundationType,
                        platform: $platform,
                        sourceId: $sourceId,
                        payload: $payload,
                        metadata: $metadata,
                        policy: $policy,
                        version: $version,
                    );
                } else {
                    $this->createFoundationBackupItem(
                        tenant: $tenant,
                        backupSet: $backupSet,
                        snapshotValidator: $snapshotValidator,
                        foundationType: $foundationType,
                        platform: $platform,
                        sourceId: $sourceId,
                        payload: $payload,
                        metadata: $metadata,
                    );
                }

                $created++;

                $operationRunService->incrementSummaryCounts($this->operationRun, [
                    'total' => 1,
                    'items' => 1,
                    'processed' => 1,
                    'succeeded' => 1,
                    'created' => 1,
                ]);
            }
        }

        return [
            [
                'created' => $created,
                'restored' => $restored,
                'failures' => $failures,
            ],
            $failures,
        ];
    }

    /**
     * @param  array<string, mixed>  $payload
     * @param  array<string, mixed>  $metadata
     */
    private function createFoundationBackupItem(
        ManagedEnvironment $tenant,
        BackupSet $backupSet,
        SnapshotValidator $snapshotValidator,
        string $foundationType,
        ?string $platform,
        string $sourceId,
        array $payload,
        array $metadata,
        ?Policy $policy = null,
        ?PolicyVersion $version = null,
    ): BackupItem {
        $warnings = is_array($metadata['warnings'] ?? null) ? $metadata['warnings'] : [];
        $validation = $snapshotValidator->validate($payload);
        $warnings = array_merge($warnings, $validation['warnings']);

        $odataWarning = BackupItem::odataTypeWarning($payload, $foundationType, $platform);
        if ($odataWarning !== null) {
            $warnings[] = $odataWarning;
        }

        if ($warnings !== []) {
            $metadata['warnings'] = array_values(array_unique($warnings));
        }

        return BackupItem::create([
            'managed_environment_id' => $tenant->getKey(),
            'backup_set_id' => $backupSet->getKey(),
            'policy_id' => $policy?->getKey(),
            'policy_version_id' => $version?->getKey(),
            'policy_identifier' => $sourceId,
            'policy_type' => $foundationType,
            'platform' => $platform,
            'payload' => $payload,
            'metadata' => $metadata,
        ]);
    }

    private function supportsFoundationVersioning(string $foundationType): bool
    {
        return in_array($foundationType, ['intuneRoleDefinition', 'intuneRoleAssignment'], true);
    }

    /**
     * @param  array<string, mixed>  $payload
     * @param  array<string, mixed>  $metadata
     */
    private function resolveFoundationPolicy(
        ManagedEnvironment $tenant,
        string $foundationType,
        string $sourceId,
        ?string $platform,
        array $payload,
        array $metadata,
    ): Policy {
        $displayName = $metadata['displayName']
            ?? $metadata['display_name']
            ?? $payload['displayName']
            ?? $payload['name']
            ?? $sourceId;

        $policy = Policy::query()->firstOrNew([
            'managed_environment_id' => $tenant->getKey(),
            'external_id' => $sourceId,
            'policy_type' => $foundationType,
        ]);

        $existingMetadata = is_array($policy->metadata) ? $policy->metadata : [];

        $policy->fill([
            'platform' => $platform,
            'display_name' => is_string($displayName) && $displayName !== '' ? $displayName : $sourceId,
            'last_synced_at' => null,
            'metadata' => array_merge(
                $existingMetadata,
                [
                    'foundation_anchor' => true,
                    'foundation_type' => $foundationType,
                    'capture_mode' => 'immutable_backup',
                ],
            ),
        ]);
        $policy->save();

        return $policy;
    }
}
