<?php

namespace App\Models;

use App\Enums\PostType;
use App\Enums\DeletedType;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;

class Post extends Model
{
    use HasFactory, SoftDeletes;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'content',
        'user_id',
        'type',
        'origin_id',
        'is_seen',
        'is_accepted',
        'deleted_type',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'type' => PostType::class,
        'is_seen' => 'boolean',
        'is_accepted' => 'boolean',
        'deleted_type' => DeletedType::class,
    ];

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    public function group(): BelongsTo
    {
        return $this->belongsTo(Group::class, 'origin_id')->whereExists(function ($query) {
            $query->from('posts')->whereColumn('groups.id', 'posts.origin_id')->where('posts.type', PostType::GROUP);
        });
    }

    public function comments(): HasMany
    {
        return $this->hasMany(Comment::class);
    }

    public function likes(): BelongsToMany
    {
        return $this->belongsToMany(User::class, 'post_likes');
    }

    public function images(): MorphMany
    {
        return $this->morphMany(Image::class, 'imageable');
    }

    public function scopeType($query, PostType $type)
    {
        return $query->where('type', $type);
    }

    public function scopeSeen($query, $value)
    {
        return $query->where('is_seen', $value);
    }

    public function scopeAccepted($query, $value)
    {
        return $query->where('is_accepted', $value);
    }

    public function scopeOwned($query)
    {
        return $query->where('user_id', auth()->id());
    }

    public function scopeFilter($query, $filters)
    {
        $query->when($filters['search'] ?? false, function ($query, $searchText) {
            $query->whereHas('user', function ($query) use ($searchText) {
                $query->whereHas('profile', function ($query) use ($searchText) {
                    $query->where(function ($query) use ($searchText) {
                        $query->where('first_name', 'like', '%' . $searchText . '%')
                            ->orWhere('last_name', 'like', '%' . $searchText . '%');
                    });
                });
            })->orWhere('content', 'like', '%' . $searchText . '%');
        });
    }

    public function scopeAvailable($query)
    {
        $loginUser = auth()->user();
        if ($loginUser) {
            return $query->where(function ($query) use ($loginUser) {
                $query->whereIn('type', [PostType::PUBLIC, PostType::SHARE_PUBLIC])
                    ->orWhere(function ($query) use ($loginUser) {
                        $friends = $loginUser->getFriends()->pluck('id');
                        $query->whereIn('type', [PostType::FRIENDS, PostType::SHARE_FRIENDS])
                            ->whereIn('user_id', [$loginUser->id, ...$friends]);
                    })
                    ->orWhere(function ($query) use ($loginUser) {
                        $query->whereIn('type', [PostType::PRIVATE, PostType::SHARE_PRIVATE, PostType::GROUP])
                            ->where('user_id', $loginUser->id);
                    })
                    ->orWhere(function ($query) use ($loginUser) {
                        $groups = $loginUser->groups->pluck('id');
                        $query->where('type', PostType::GROUP)
                            ->whereIn('origin_id', $groups)
                            ->where(function ($query) use ($loginUser) {
                                $query->where(function ($query) use ($loginUser) {
                                    $query->where('is_accepted', false)
                                        ->whereHas('group', function ($query) use ($loginUser) {
                                            $query->where('user_id', $loginUser->id);
                                        });
                                })
                                    ->orWhere('is_accepted', true);
                            });
                    });
            });
        }

        return $query->whereIn('type', [PostType::PUBLIC, PostType::SHARE_PUBLIC]);
    }
}
