<?php

declare(strict_types=1);

namespace App\Services\NovaCards;

use App\Models\NovaCard;
use App\Models\NovaCardVersion;
use App\Models\User;

class NovaCardVersionService
{
    public function __construct(
        private readonly NovaCardProjectNormalizer $normalizer,
    ) {
    }

    public function snapshot(NovaCard $card, ?User $actor = null, ?string $label = null, bool $force = false): NovaCardVersion
    {
        $project = $this->normalizer->normalizeForCard($card->fresh(['template']));
        $hash = hash('sha256', json_encode($project, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
        $latest = $card->versions()->latest('version_number')->first();

        if (! $force && $latest && $latest->snapshot_hash === $hash) {
            return $latest;
        }

        return $card->versions()->create([
            'user_id' => $actor?->id,
            'version_number' => (int) ($latest?->version_number ?? 0) + 1,
            'label' => $label,
            'snapshot_hash' => $hash,
            'snapshot_json' => $project,
        ]);
    }

    public function restore(NovaCard $card, NovaCardVersion $version, ?User $actor = null): NovaCard
    {
        $project = $this->normalizer->normalize($version->snapshot_json, $card->template, [], $card);
        $topLevel = $this->normalizer->syncTopLevelAttributes($project);

        $card->forceFill([
            'project_json' => $project,
            'schema_version' => $topLevel['schema_version'],
            'title' => $topLevel['title'],
            'quote_text' => $topLevel['quote_text'],
            'quote_author' => $topLevel['quote_author'],
            'quote_source' => $topLevel['quote_source'],
            'background_type' => $topLevel['background_type'],
            'background_image_id' => $topLevel['background_image_id'],
            'render_version' => (int) $card->render_version + 1,
        ])->save();

        $this->snapshot($card->refresh(['template']), $actor, 'Restored from version ' . $version->version_number, true);

        return $card->refresh()->load(['category', 'template', 'tags', 'backgroundImage', 'versions']);
    }
}