<?php

namespace Illuminate\Database\Eloquent\Relations;

/**
* @template TRelatedModel of \Illuminate\Database\Eloquent\Model
* @template-extends Relation<TRelatedModel>
* @mixin \Illuminate\Database\Eloquent\Builder<TRelatedModel>
*/
class BelongsToMany extends Relation
{
    use Concerns\InteractsWithPivotTable;

    /**
     * @template T
     * @psalm-param T $id
     * @param  int|non-empty-string|array<int|non-empty-string>|\Illuminate\Contracts\Support\Arrayable<int|non-empty-string>  $id
     * @param  list<non-empty-string>  $columns
     * @return \Illuminate\Support\Collection|\Illuminate\Database\Eloquent\Model
     * @psalm-return (T is (array|\Illuminate\Contracts\Support\Arrayable) ? \Illuminate\Support\Collection<int, TRelatedModel>|TRelatedModel
     */
    public function findOrNew($id, $columns = ['*']) {}

    /**
     * @param  array<string, mixed>  $attributes
     * @return \Illuminate\Database\Eloquent\Model
     * @psalm-return TRelatedModel
     */
    public function firstOrNew(array $attributes) {}

    /**
     * @param  array<string, mixed>  $attributes
     * @param  array  $joining
     * @param  bool   $touch
     * @return \Illuminate\Database\Eloquent\Model
     * @psalm-return TRelatedModel
     */
    public function firstOrCreate(array $attributes, array $joining = [], $touch = true) {}

    /**
     * @param  array<string, mixed>  $attributes
     * @param  array  $values
     * @param  array  $joining
     * @param  bool   $touch
     * @return TRelatedModel
     */
    public function updateOrCreate(array $attributes, array $values = [], array $joining = [], $touch = true) {}

    /**
     * @template T
     * @psalm-param T $id
     * @param  mixed  $id
     * @param  list<non-empty-string>  $columns
     * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection|null
     * @psalm-return (T is (array|\Illuminate\Contracts\Support\Arrayable) ? \Illuminate\Database\Eloquent\Collection<int, TRelatedModel>|null : TRelatedModel|null)
     */
    public function find($id, $columns = ['*']) {}

    /**
     * @param  \Illuminate\Contracts\Support\Arrayable<array-key, mixed>|array<array-key, int|string>  $ids
     * @param  list<non-empty-string>  $columns
     * @return \Illuminate\Database\Eloquent\Collection
     * @psalm-return \Illuminate\Database\Eloquent\Collection<int, TRelatedModel>
     */
    public function findMany($ids, $columns = ['*']) {}

    /**
     * @template T
     * @psalm-param T $id
     * @param  list<non-empty-string>  $columns
     * @return \Illuminate\Database\Eloquent\Model|\Illuminate\Database\Eloquent\Collection
     * @psalm-return (T is (array|\Illuminate\Contracts\Support\Arrayable) ? \Illuminate\Database\Eloquent\Collection<int, TRelatedModel>|null : TRelatedModel|null)
     *
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
     */
    public function findOrFail($id, $columns = ['*']) {}

    /**
     * @param  list<non-empty-string>  $columns
     * @return \Illuminate\Database\Eloquent\Model|null
     * @psalm-return TRelatedModel|null
     */
    public function first($columns = ['*']) {}

    /**
     * Execute the query and get the first result or throw an exception.
     *
     * @param  list<non-empty-string>  $columns
     * @return \Illuminate\Database\Eloquent\Model|static
     * @psalm-return TRelatedModel
     *
     * @throws \Illuminate\Database\Eloquent\ModelNotFoundException
     */
    public function firstOrFail($columns = ['*']) {}

    /**
     * @param  array<string, mixed>  $attributes
     * @param  array  $joining
     * @param  bool   $touch
     * @return TRelatedModel
     */
    public function create(array $attributes = [], array $joining = [], $touch = true) {}

    /**
     * @param  array  $records
     * @param  array  $joinings
     * @return list<TRelatedModel>
     */
    public function createMany(array $records, array $joinings = []) {}

    /**
     * @return \Traversable<int, TRelatedModel>
     */
    public function getResults() {}

    /**
     * @param  int|null  $perPage
     * @param  array<int, mixed>  $columns
     * @param  string  $pageName
     * @param  int|null  $page
     * @return \Illuminate\Pagination\LengthAwarePaginator<TRelatedModel>
     */
    public function paginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null) {}

    /**
     * Paginate the given query into a simple paginator.
     *
     * @param  int|null  $perPage
     * @param  array<int, mixed>  $columns
     * @param  string  $pageName
     * @param  int|null  $page
     * @return \Illuminate\Pagination\Paginator<TRelatedModel>
     */
    public function simplePaginate($perPage = null, $columns = ['*'], $pageName = 'page', $page = null) {}

    /**
     * Paginate the given query into a cursor paginator.
     *
     * @param  int|null  $perPage
     * @param  array<int, mixed>  $columns
     * @param  string  $cursorName
     * @param  string|null  $cursor
     * @return \Illuminate\Pagination\CursorPaginator<TRelatedModel>
     */
    public function cursorPaginate($perPage = null, $columns = ['*'], $cursorName = 'cursor', $cursor = null) {}
}
