<?php

namespace Ignite\Core\Http\Controllers\Admin;

use Ignite\Core\Contracts\Repositories\GroupRepository;
use Ignite\Core\Contracts\Repositories\PermissionRepository;
use Ignite\Core\Http\Controllers\Controller;
use Ignite\Core\Http\Forms\Admin\GroupForm;
use Ignite\Core\Models\Grid\GroupTable;
use Illuminate\Http\Request;

class GroupsController extends Controller
{
    /**
     * @var GroupRepository
     */
    private $groupRepository;

    /**
     * @var PermissionRepository
     */
    private $permissionRepository;

    /**
     * GroupsController constructor.
     *
     * @param GroupRepository $groupRepository
     * @param PermissionRepository $permissionRepository
     */
    public function __construct(GroupRepository $groupRepository, PermissionRepository $permissionRepository)
    {
        $this->groupRepository = $groupRepository;
        $this->permissionRepository = $permissionRepository;
    }

    /**
     * List the groups in a grid table.
     *
     * @param  GroupTable $table
     * @param  Request $request
     * @return \Illuminate\Http\JsonResponse|\Illuminate\View\View
     */
    public function index(GroupTable $table, Request $request)
    {
        if ($request->wantsJson()) {
            return $table->ajax();
        }

        return $table->render('Core::admin.security.groups.index', compact('table'));
    }

    /**
     * Display the form to create a group.
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function create()
    {
        $permissions = $this->permissionRepository->findAll();

        $form = $this->form(GroupForm::class, [
            'method' => 'post',
            'url' => route('admin.security.groups.store'),
            'form_horizontal' => true
        ]);

        return view('Core::admin.security.groups.create', compact('permissions', 'form'));
    }

    /**
     * Display the form to create a group.
     *
     * @return \Illuminate\Http\RedirectResponse
     */
    public function store()
    {
        $form = $this->form(GroupForm::class);

        $values = $form->getFieldValues();
        $permissions = request()->get('permissions', []);

        if (! $form->isValid()) {
            return redirect()->back()
                ->withErrors($form->getErrors())
                ->withInput(array_merge(['permissions' => $permissions], $values));
        }

        try {
            $group = $this->groupRepository->create($values, $permissions);
            $this->flash('success', "The group {$group->name} was created successfully.");
            return redirect()->route('admin.security.groups.edit', $group);
        } catch (\Exception $e) {
            $this->flash('error', "The group could not be created.");
            $this->logException($e);
            return redirect()->back();
        }
    }

    /**
     * Display the form to edit a group.
     *
     * @param  string $group
     * @return \Illuminate\Http\RedirectResponse
     */
    public function edit($group)
    {
        $group = $this->groupRepository->find($group);
        $permissions = $this->permissionRepository->findAll();

        $form = $this->form(GroupForm::class, [
            'method' => 'patch',
            'url' => route('admin.security.groups.update', $group),
            'model' => $group,
            'form_horizontal' => true
        ]);

        return view('Core::admin.security.groups.edit', compact('group', 'permissions', 'form'));
    }

    /**
     * Update the group in storage.
     *
     * @param  string $group
     * @return \Illuminate\Http\RedirectResponse
     */
    public function update($group)
    {
        $form = $this->form(GroupForm::class, [], ['group' => $group]);
        $values = $form->getFieldValues();
        $permissions = request()->get('permissions', []);

        if (! $form->isValid()) {
            return redirect()->back()
                ->withErrors($form->getErrors())
                ->withInput(array_merge(['permissions' => $permissions], $values));
        }

        try {
            $group = $this->groupRepository->update($group, $values, $permissions);
            $this->flash('success', "The group {$group->name} was updated successfully.");
        } catch (\Exception $e) {
            $this->flash('error', "The group could not be updated. I.T has been notified.");
            $this->logException($e);
        }

        return redirect()->back();
    }

    /**
     * Delete the group.
     *
     * @param  int $group
     * @param  Request $request
     * @return \Illuminate\Http\Response
     */
    public function destroy($group, Request $request)
    {
        try {
            $this->groupRepository->delete($group);
            $message = "Group with ID: $group was deleted successfully.";
            $level = 'success';
        } catch (\Exception $e) {
            $message = "Group with ID: $group could not be deleted. Error: " . $e->getMessage();
            $level = 'error';
        }

        if ($request->wantsJson()) {
            return response()->json(['status' => $level, 'message' => $message]);
        }

        $this->flash('success', $message);

        return redirect()->back();
    }

    /**
     * Delete the group.
     *
     * @param Request $request
     * @return \Illuminate\Http\Response
     */
    public function destroyMany(Request $request)
    {
        $ids = $request->get('ids', '');
        $groups = explode(',', $ids);
        $count = count($groups);
        $noun = str_plural('group', count($groups));
        $verb = $count === 1 ? 'was' : 'were';

        try {
            $this->groupRepository->deleteMany($groups);
            $this->flash('success', "$count $noun $verb deleted successfully.");
        } catch (\Exception $e) {
            $this->logException($e);
            $this->flash('error', "Unable to delete $count selected $noun: $ids.");
        }

        return redirect()->route('admin.security.groups.index');
    }
}
