<?php

namespace App\Services;

use App\Models\FavouriteCategory;
use App\Models\Save;
use App\Models\User;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;

trait FavouriteCategoryService
{
    /**
     * Store new record
     *
     * @param array $data
     * @return Builder|Model
     */
    public static function store(array $data): Model|Builder
    {
        return FavouriteCategory::query()->create($data);
    }

    /**
     * Update existing record
     *
     * @param array $data
     * @return mixed
     */
    public function updateService(array $data): mixed
    {
        return tap($this)->update($data);
    }

    /**
     * Add category
     *
     * @param string $designation
     * @return Model|Builder|FavouriteCategory|null
     */
    public static function create(string $designation): Model|Builder|FavouriteCategory|null
    {
        try {
            /** @var User $user */
            $user = auth()->user();

            $favouriteCategory = self::store([
                "designation" => $designation,
                "user_id" => $user->{"id"},
            ]);

            $result = $favouriteCategory;
        } catch (\Exception $exception) {
            log_debug(exception: $exception, prefix: 'FavouriteCategoryService::create');
            $result = null;
        }

        return $result;
    }

    /**
     * FInd by id
     *
     * @param int $id
     * @return Builder|Model|null
     */
    public static function findById(int $id): Model|Builder|null
    {
        return FavouriteCategory::query()->find($id);
    }

    /**
     * Update
     *
     * @param string $designation
     * @return FavouriteCategory
     */
    public function updateCategory(string $designation): FavouriteCategory
    {
        $favouriteCategory = $this;
        try {
            $favouriteCategory->updateService(["designation" => $designation]);
        } catch (Exception $exception) {
            log_debug(exception: $exception, prefix: 'FavouriteCategoryService::updateCategory');
            $favouriteCategory = null;
        }
        return $favouriteCategory;
    }

    /**
     * Delete category
     *
     * @return void
     */
    public function deleteCategory(): void
    {
        $this->forceDelete();
    }

    /**
     * Number of posts for each category
     *
     * @param int $postId
     * @return int
     */
    public function occurrencePost(int $postId): int
    {
        return
            Save::query()
                ->where('favourite_category_id', $this->{'id'})
                ->where('post_id', $postId)
                ->distinct()
                ->count();
    }

    /**
     * Get user's categories
     *
     * @param int|null $postId
     * @return Collection|array
     */
    public static function getCategories(int $postId = null): Collection|array
    {
        $result = [];

        /** @var User $user */
        $user = auth()->user();

        $favorites =
            FavouriteCategory::query()
                ->where("user_id", $user->{"id"})
                ->orderByDesc("created_at")
                ->get();

        if($postId !== null) {
            $result[] = array (
                'id' => null,
                'designation' => __('messages.by_default'),
                'post_occurrence' => Save::totalSavePost($user, $postId, false),
            );
        }

        foreach ($favorites as $favorite) {
            $result[] = $favorite->commonSerialization($postId);
        }

        return $result;
    }

    /**
     * Common serialization
     *
     * @param int|null $postId
     * @return Collection|array
     */
    public function commonSerialization(int $postId = null): Collection|array
    {
        $favorite = $this;

        return array (
            'id' => $favorite->{'id'},
            'designation' => $favorite->{'designation'},
            'post_occurrence' => $postId !== null ? $favorite->occurrencePost($postId) : 0
        );
    }
}
