<?php

namespace App\Traits\Utilities;

trait WithSortOrder
{
    /**
     * Get the model class for this sortable entity
     */
    abstract protected function getModelClass(): string;

    /**
     * Get the current model instance
     */
    abstract protected function getModelInstance();

    /**
     * Adjust sort order after deletion
     */
    protected function adjustSortOrderAfterDelete($deletedModel): void
    {
        $modelClass = $this->getModelClass();

        $modelClass::where('sort_order', '>', $deletedModel->sort_order)
            ->orderBy('sort_order')
            ->get()
            ->each(function ($item) {
                $item->update(['sort_order' => $item->sort_order - 1]);
            });
    }

    /**
     * Handle sort order changes (up, down, first, last)
     */
    public function sortOrder(string $direction): void
    {
        $modelClass = $this->getModelClass();
        $model = $this->getModelInstance();

        if (in_array($direction, ['up', 'down'])) {
            $swap = null;

            if ($direction === 'up') {
                $swap = $modelClass::where('sort_order', '<', $model->sort_order)
                    ->orderByDesc('sort_order')
                    ->first();
            } else {
                $swap = $modelClass::where('sort_order', '>', $model->sort_order)
                    ->orderBy('sort_order')
                    ->first();
            }

            if ($swap) {
                $temp = $model->sort_order;
                $model->update(['sort_order' => $swap->sort_order]);
                $swap->update(['sort_order' => $temp]);
            }
        } elseif ($direction === 'first') {
            $model->update(['sort_order' => $modelClass::min('sort_order') - 1]);
            $this->normalizeSortOrder();
        } elseif ($direction === 'last') {
            $model->update(['sort_order' => $modelClass::max('sort_order') + 1]);
            $this->normalizeSortOrder();
        }
    }

    /**
     * Normalize sort order to ensure consecutive numbering
     */
    protected function normalizeSortOrder(): void
    {
        $modelClass = $this->getModelClass();
        $items = $modelClass::orderBy('sort_order')->get();

        foreach ($items as $index => $item) {
            $item->update(['sort_order' => $index + 1]);
        }
    }
}
