<?php

namespace Ignite\Core\Repositories;

use Ignite\Core\Contracts\Repositories\GroupRepository as GroupRepositoryContract;
use Ignite\Core\Entities\Group;
use Ignite\Core\Entities\GroupPermission;

class GroupRepository implements GroupRepositoryContract
{
    /**
     * The scoped Group query.
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function query()
    {
        return Group::query();
    }

    /**
     * The groups accessible by the currently authenticated user.
     *
     * @return \Ignite\Core\Collections\GroupsCollection
     */
    public function getAccessibleGroups()
    {
        return $this->query()->where('level', '>=', auth()->user()->getLevel())->get();
    }

    /**
     * Find a group by primary key.
     *
     * @param  int $id
     * @return \Ignite\Core\Entities\Group
     */
    public function find($id)
    {
        return $this->query()->with('permissions')->where('id', $id)->firstOrFail();
    }

    /**
     * Find a group by unique key.
     *
     * @param  string $key
     * @return \Ignite\Core\Entities\Group
     */
    public function findByKey($key)
    {
        return $this->query()->with('permissions')->where('key', $key)->firstOrFail();
    }

    /**
     * Find all groups in the system.
     *
     * @return \Ignite\Core\Collections\GroupsCollection
     */
    public function findAll()
    {
        return $this->query()->with('permissions')->get();
    }

    /**
     * Create a new group and optionally provide permissions.
     *
     * @param  array $data
     * @param  array $permissions
     * @return \Ignite\Core\Entities\Group
     */
    public function create(array $data, array $permissions = [])
    {
        /** @var Group $group */
        $group = Group::create(array_merge(
            ['is_user_defined' => true], $data
        ));

        $group->permissions()->sync($permissions);

        return $group->refresh();
    }

    /**
     * Update an existing group and optionally provide permissions.
     *
     * @param  int $id
     * @param  array $data
     * @param  array $permissions
     *
     * @return \Ignite\Core\Entities\Group
     */
    public function update($id, array $data, array $permissions = [])
    {
        $group = $this->find($id);
        $group->update($data);
        $group->permissions()->sync($permissions);

        return $group->refresh();
    }

    /**
     * Delete the provide group by id.
     *
     * @param  int $id
     * @return \Ignite\Core\Entities\Group
     * @throws \Exception
     */
    public function delete($id)
    {
        $group = $this->find($id);
        $group->permissions()->delete();
        $group->delete();

        return $group;
    }

    /**
     * Delete multiple groups in a batch request.
     *
     * @param  array $ids
     * @return array
     */
    public function deleteMany(array $ids)
    {
        GroupPermission::whereIn('group_id', $ids)->delete();
        Group::destroy($ids);

        return $ids;
    }
}
