<?php

namespace App\Observers;

use App\Facades\Settings;
use Illuminate\Support\Collection;
use Mtc\ContentManager\Contracts\MediaUse;
use Mtc\MercuryDataModels\VehicleOffer;
use Mtc\MercuryDataModels\VehicleOfferContent;
use Mtc\MercuryDataModels\VehicleOfferContentHistory;
use Mtc\Stemmer\Stemmer;

class VehicleOfferObserver
{
    /**
     * Actions to do when saving an offer
     *
     * @param VehicleOffer $offer
     * @return void
     */
    public function saving(VehicleOffer $offer): void
    {
        $this->setSearchableContent($offer);
        $this->setOrderValue($offer);
    }

    /**
     * Actions to do when deleting offer
     *
     * @param VehicleOffer $offer
     * @return void
     */
    public function deleting(VehicleOffer $offer)
    {
        $offer->content->each(fn (VehicleOfferContent $content) => $content->delete());
        $offer->versions->each(fn (VehicleOfferContentHistory $version) => $version->delete());
        $offer->mediaUses->each(fn (MediaUse $mediaUse) => $mediaUse->delete());
    }

    /**
     * Set the search_content column value based on data
     *
     * @param VehicleOffer $offer
     * @return void
     */
    private function setSearchableContent(VehicleOffer $offer): void
    {
        $fields = collect([
            'make_id' => $offer->make?->name,
            'model_id' => $offer->model?->name,
            'name' => $offer->name,
            'derivative' => $offer->derivative,
        ]);

        $contentIsUpToDate = $offer->content()->max('updated_at') < $offer->updated_at;
        $fieldsChanged = $offer->isDirty($fields->keys()->toArray());

        if ($contentIsUpToDate && $fieldsChanged === false) {
            return;
        }

        $offer->search_content = $fields
            ->merge($this->getSearchableContent($offer))
            ->filter()
            ->map(fn (string $value) => Stemmer::multiStem($value))
            ->flatten()
            ->implode(' ');
    }

    /**
     * Find searchable content field values from offer content
     *
     * @param VehicleOffer $offer
     * @return Collection
     */
    private function getSearchableContent(VehicleOffer $offer): Collection
    {
        return $offer->content()
            ->with('contentElement.fields')
            ->whereHas('contentElement.fields', fn ($fieldQuery) => $fieldQuery->where('field_type', 'textarea'))
            ->get()
            ->filter(fn (VehicleOfferContent $content) => $content->content)
            ->map(fn (VehicleOfferContent $content) => $content->contentElement->fields
                ->filter(fn ($field) => $field->field_type === 'textarea')
                ->map(fn ($field) => $content->content[$field->name] ?? null))
            ->flatten();
    }

    private function setOrderValue(VehicleOffer $offer): void
    {
        if (!is_null($offer->order)) {
            return;
        }

        if (Settings::get('offers-new-offer-position') === 'beginning') {
            VehicleOffer::query()->increment('order');
            $offer->order = 0;
        } else {
            $maxOrder = VehicleOffer::max('order');
            $offer->order = is_null($maxOrder) ? 0 : $maxOrder + 1;
        }
    }
}
