<?php

namespace App\Services;

use App\Models\Like;
use App\Models\Post;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\DB;

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

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

    /**
     * Like/Unlike post
     *
     * @param int $postId
     * @return Builder|Model|null
     */
    public static function likePost(int $postId): Model|Builder|null
    {
        DB::beginTransaction();
        try {
            /** @var User $user */
            $user = auth()->user();

            /** @var Post $post */
            $post = Post::findById($postId);

            //Check if post has already been liked
            $alreadyLiked = self::alreadyLikedPost($user, $postId);
            if ($alreadyLiked) {
                self::unlikePost($postId);
                $post->subtractPostLike();
            } else {
                $likeAction = Like::store([
                    "post_id" => $postId,
                    "user_id" => $user->{"id"},
                ]);

                $likeAction->{"currentPost"}->addPostLike();
            }

            DB::commit();
            $result = $post->refresh();
        } catch (\Exception $exception) {
            log_debug(exception: $exception, prefix: 'LikeService::likePost');
            DB::rollBack();

            $result = null;
        }

        return $result;
    }

    /**
     * Check if post has already been liked
     *
     * @param User $user
     * @param int $postId
     * @return bool
     */
    public static function alreadyLikedPost(User $user, int $postId): bool
    {
        // Query table
        $like = Like::query();

        return
            $like
                ->where("user_id", $user->{"id"})
                ->where("post_id", $postId)
                ->exists();
    }

    /**
     * Unlike post
     *
     * @param int $postId
     * @return mixed
     */
    public static function unlikePost(int $postId): mixed
    {
        /** @var User $user */
        $user = auth()->user();

        return
            Like::query()
                ->where("user_id", $user->{"id"})
                ->where("post_id", $postId)->delete();
    }

    /**
     * Get post liked by request user
     *
     * @param User $user
     * @param int|null $pageNumber
     * @return array
     */
    public static function userLikedPosts(User $user, int $pageNumber = null): array
    {
        $queryBuilder = Like::query()->with('currentPost')->where("user_id", $user->{"id"})->orderByDesc("created_at");
        $likedPostPaginator = $queryBuilder->paginate(
            perPage: config("torryme.constants.items_per_page"),
            page: $pageNumber
        );

        $likedPostArray = array();
        foreach ($likedPostPaginator as $likedPost) {
            $post =  $likedPost->{"currentPost"};
            $likedPostArray[] = $post->commonSerialization();
        }

        return default_paginator_format(
            $likedPostPaginator->lastPage(),
            $likedPostPaginator->total(),
            $likedPostPaginator->currentPage(),
            "posts",
            $likedPostArray,
        );
    }
}
