<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use App\Models\User;
use App\Models\Book;
use Carbon\Carbon;

class StoreLoanRequest extends FormRequest {

    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize() {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules() {
        return [
            'user_id' => 'required|numeric|integer|exists:users,id',
            'book_id' => 'required|numeric|integer|exists:books,id',
            'start' => 'required|date'
        ];
    }

    /**
     * Configure the validator instance.
     *
     * @param  \Illuminate\Validation\Validator  $validator
     * @return void
     */
    public function withValidator($validator) {
        $validator->after(function ($validator) {
            if ($this->hasUserLoans()) {
                $validator->errors()->add('user_id', 'The user has 1 or more '
                        . 'pending loans.');
            }

            if ($this->hasUserPenalties()) {
                $validator->errors()->add('user_id', 'The user has pending '
                        . 'penalties.');
            }

            if ($this->isBookDownloadable()) {
                $validator->errors()->add('book_id', 'The book is '
                        . 'downloadable.');
            }

            if ($this->hasBookLoan()) {
                $validator->errors()->add('book_id', 'The book has been '
                        . 'loaned.');
            }
        });
    }

    /**
     * Check if the user has pending loans.
     * 
     * @return bool
     */
    private function hasUserLoans() {
        return User::where('id', $this->user_id)
                        ->withCount(['loans' => function ($query) {
                                $query->whereNull('end');
                            }])->having('loans_count', '>=', 1)
                        ->exists();
    }

    /**
     * Check if the user has pending penalties.
     * 
     * @return bool
     */
    private function hasUserPenalties() {
        return User::where('id', $this->user_id)
                        ->whereHas('penalties', function ($query) {
                            $query->where('end', '>',
                                    Carbon::parse($this->start)
                                    ->format('Y-m-d'));
                        })->exists();
    }

    /**
     * Check if the book is downloadable.
     * 
     * return bool
     */
    private function isBookDownloadable() {
        return Book::where('id', $this->book_id)
                        ->whereNotNull('document')
                        ->exists();
    }

    /**
     * Check if the book has been loaned.
     * 
     * @return bool
     */
    private function hasBookLoan() {
        return Book::where('id', $this->book_id)
                        ->whereHas('loans', function ($query) {
                            $query->whereNull('end');
                        })->exists();
    }

}
