<?php

namespace App\Observers;

use App\Models\Post;

class PostObserver
{
    public function saved(Post $post): void
    {
        // Sık değişen ama search-irrelevant alanlar (view_count, sort_order,
        // meta_*) reindex tetiklemez. Phase 9'daki view counter
        // increment('view_count') Meili'yi spamlemesin diye guard.
        //
        // Pivot (tags) değişimi `wasChanged`'ı tetiklemez — Phase 5 indexer'lar
        // gelince PostService::create/update sonunda explicit reindex çağırılacak.
        $searchRelevant = ['title', 'slug', 'content', 'excerpt', 'status', 'published_at', 'is_featured', 'subtype'];

        if ($post->wasRecentlyCreated || $post->wasChanged($searchRelevant)) {
            $this->reindex($post);
        }
    }

    public function deleted(Post $post): void
    {
        $this->indexerForType($post->type)?->delete($post->id);
    }

    /**
     * Public reindex API for service-layer callers.
     *
     * `PostService::create/update` çağırır — pivot save (tags()->sync) model
     * save'i tetiklemediği için `saved()` event'i içindeki `wasChanged` guard'ı
     * tag değişimini yakalamaz. Service tag sync sonrası bu metodu explicit
     * çağırarak Meili doc'larını günceller.
     */
    public function reindex(Post $post): void
    {
        $this->indexerForType($post->type)?->reindex($post);
    }

    /**
     * Resolve the search indexer for a given post type.
     *
     * Indexer sınıfları Phase 5'te yaratılacak; o zamana kadar `class_exists`
     * + try/catch guard'ları ile post save/delete'leri patlatmadan silent
     * skip yapıyoruz. Phase 5 ship olduktan sonra bu metod normalde
     * `app($class)` döndürecek.
     */
    private function indexerForType(string $type): mixed
    {
        $class = match ($type) {
            'announcement' => 'App\Services\Search\AnnouncementSearchIndexer',
            'kb_article'   => 'App\Services\Search\KnowledgebaseSearchIndexer',
            'blog_post'    => 'App\Services\Search\BlogSearchIndexer',
            default        => null,
        };

        if ($class === null) {
            return null;
        }

        try {
            return class_exists($class) ? app($class) : null;
        } catch (\Throwable) {
            return null;
        }
    }
}
