<?php

namespace Ignite\Core\Http\Controllers\Admin;

use Ignite\Core\Contracts\Repositories\TransactionRepository;
use Ignite\Core\Entities\User;
use Ignite\Core\Entities\TransactionResource;
use Ignite\Core\Http\Controllers\Controller;
use Ignite\Core\Http\Forms\Admin\WaitingTransactionForm;
use Ignite\Core\Http\Requests\WaitingTransactionDeleteManyRequest;
use Ignite\Core\Models\Grid\WaitingTransactionsTable;
use Ignite\Core\Models\Transformers\TransactionResourceTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Kris\LaravelFormBuilder\FormBuilderTrait;

class TransactionResourceController extends Controller
{
    use FormBuilderTrait;

    /**
     * Display a listing of the resource.
     *
     * @param WaitingTransactionsTable $table
     * @param Request $request
     *
     * @return JsonResponse|Response
     */
    public function index(WaitingTransactionsTable $table, Request $request)
    {
        if ($request->wantsJson()) {
            return $table->ajax();
        }

        return $table->render('Core::admin.transactions.waiting.index');
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return RedirectResponse
     */
    public function create()
    {
        return redirect()->route('admin.transactions.resource.index');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param Request $request
     *
     * @return RedirectResponse
     */
    public function store(Request $request)
    {
        return redirect()->route('admin.transactions.resource.index');
    }

    /**
     * Show the specified resource.
     *
     * @param int $id
     *
     * @return RedirectResponse
     */
    public function show($id)
    {
        return redirect()->route('admin.transactions.resource.index');
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param int $id
     *
     * @return \Illuminate\View\View
     */
    public function edit($id)
    {
        $model = TransactionResource::find($id);
        $form = $this->form(WaitingTransactionForm::class, [
            'method' => 'PUT',
            'model' => $model,
            'url' => route('admin.transactions.resource.update', ['id' => $id])
        ]);

        return view('Core::admin.transactions.waiting.edit', compact('model', 'form'));
    }

    /**
     * Update the specified resource in storage.
     *
     * @param int $id
     * @param Request $request
     * @param TransactionResourceTransformer $transformer
     *
     * @return RedirectResponse
     */
    public function update($id, Request $request, TransactionResourceTransformer $transformer)
    {
        $resource = TransactionResource::find($id);

        $form = $this->form(WaitingTransactionForm::class, ['model' => $resource]);

        $form->redirectIfNotValid();

        $values = $form->getFieldValues(true);

        $resource->fill($values);

        $user = User::find($request->get('user_id'));
        $transaction = $transformer->transform($resource, $user);

        TransactionResource::query()->getConnection()->beginTransaction();

        try {
            $resource->delete();
            $transaction->save();
            $this->flashSuccess("Successfully assigned waiting transaction to {$user->fullName()}");
            TransactionResource::query()->getConnection()->commit();
            return redirect()->route('admin.transactions.resource.index');
        } catch (\Exception $exception) {
            TransactionResource::query()->getConnection()->rollBack();
            logger()->critical(
                'Unable to assign a resource transaction to a participant',
                compact('exception', 'user', 'resource')
            );
            $this->flashError("Unable to assign the waiting transaction to {$user->fullName()}. Please contact IT.");
            return redirect()->route('admin.transactions.resource.index');
        }
    }

    /**
     * Remove the specified resource from storage.
     * @param int $id
     * @return Response
     */
    public function destroy($id)
    {
        //
    }

    /**
     * Delete multiple records at once.
     *
     * @param  WaitingTransactionDeleteManyRequest $waitingTransactionDeleteManyRequest
     * @return RedirectResponse
     */
    public function destroyMany(WaitingTransactionDeleteManyRequest $waitingTransactionDeleteManyRequest): RedirectResponse
    {
        $ids = $waitingTransactionDeleteManyRequest->ids;
        $transactionRepo = app(TransactionRepository::class);

        try {
            $transactionRepo->delete($ids);
            $this->flashSuccess("The selected waiting transaction(s) deleted successfully!");
        } catch (\Exception $e) {
            $this->logException($e);
            $this->flashSuccess('The selected waiting transactions could not be deleted. The error has been logged and a bug report has been sent to the developers. Please contact an administrator to follow up!');
        }

        return redirect()->back();
    }
}
