<?php

namespace App\Services\PromptLandingPageEditor;

use App\Enums\PromptLandingPageVersionKind;
use App\Models\PromptLandingPage;
use App\Models\PromptLandingPageVersion;
use App\Models\User;

class RecordPublishedVersion
{
    public function ensureOriginal(PromptLandingPage $page, ?User $actor = null): ?PromptLandingPageVersion
    {
        $this->reclaimVersionOneFromDraft($page);

        $existing = $page->versions()->where('version', 1)->first();

        if ($existing !== null) {
            return $existing;
        }

        if ($this->documentIsEmpty($page)) {
            return null;
        }

        return $this->store(
            $page,
            $actor,
            (string) ($page->html ?? ''),
            (string) ($page->css ?? ''),
            (string) ($page->js ?? ''),
            1,
        );
    }

    public function snapshotLive(PromptLandingPage $page, ?User $actor = null): ?PromptLandingPageVersion
    {
        $original = $this->ensureOriginal($page, $actor);

        if ($this->documentIsEmpty($page)) {
            return $original;
        }

        $html = (string) ($page->html ?? '');
        $css = (string) ($page->css ?? '');
        $js = (string) ($page->js ?? '');

        $match = $page->versions()
            ->where('kind', PromptLandingPageVersionKind::Published)
            ->get()
            ->first(fn (PromptLandingPageVersion $version): bool => (string) ($version->html ?? '') === $html
                && (string) ($version->css ?? '') === $css
                && (string) ($version->js ?? '') === $js);

        if ($match !== null) {
            return $match;
        }

        return $this->store(
            $page,
            $actor,
            $html,
            $css,
            $js,
            $this->nextVersionNumber($page),
        );
    }

    private function reclaimVersionOneFromDraft(PromptLandingPage $page): void
    {
        $first = $page->versions()->where('version', 1)->first();

        if ($first === null || $first->kind !== PromptLandingPageVersionKind::Draft) {
            return;
        }

        if ($page->versions()->where('kind', PromptLandingPageVersionKind::Published)->exists()) {
            return;
        }

        $page->versions()
            ->orderByDesc('version')
            ->get()
            ->each(function (PromptLandingPageVersion $version): void {
                $version->update(['version' => $version->version + 1]);
            });
    }

    private function store(
        PromptLandingPage $page,
        ?User $actor,
        string $html,
        string $css,
        string $js,
        int $version,
    ): PromptLandingPageVersion {
        return $page->versions()->create([
            'version' => $version,
            'kind' => PromptLandingPageVersionKind::Published,
            'html' => $html,
            'css' => $css,
            'js' => $js,
            'created_by' => $actor?->id ?? $page->user_id,
            'created_at' => $version === 1
                ? ($page->approved_at ?? $page->created_at ?? now())
                : now(),
        ]);
    }

    private function nextVersionNumber(PromptLandingPage $page): int
    {
        return max(2, (int) $page->versions()->max('version') + 1);
    }

    private function documentIsEmpty(PromptLandingPage $page): bool
    {
        return trim((string) ($page->html ?? '')) === ''
            && trim((string) ($page->css ?? '')) === ''
            && trim((string) ($page->js ?? '')) === '';
    }
}
