<?php

namespace App\Modules\Publishers\Repositories;

use App\Events\Publisher\Deleting;
use App\Events\Publisher\PublisherAdminAssignment;
use App\Modules\Publishers\Filters\PublishersFilter;
use App\Modules\Publishers\Interfaces\PublisherInterface;
use App\Modules\Publishers\Database\Models\Publisher;
use App\Modules\Publishers\Database\Models\RequestPublisher;
use App\System\User\Database\Models\User;
use App\Modules\Publishers\Database\Models\RequestPublisherOwnership;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Event;
use NicoAuth\AuthManager;
use NicoAuth\database\Traits\NicoAuths;
use NicoSystem\Exceptions\NicoBadRequestException;
use NicoSystem\Exceptions\NicoException;
use NicoSystem\Repositories\BaseRepository;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

/**
 * Class PublisherRepository
 * @package App\Modules\Publishers\Repositories
 */
class PublisherRepository extends BaseRepository implements PublisherInterface
{
    protected $user;
    protected $requestPublisher; 
    protected $requestPublisherOwnership;
    /**
     * PublisherRepository constructor.
     * @param Publisher $model
     */
    public function __construct(Publisher $model, User $user)
    {
        parent::__construct($model);
        $this->user = $user;
        $this->events['deleting'] = Deleting::class;
    }

    protected function isAdministratorIsEditableByUser ($model, $user) {

        return $model -> created_by == $user -> id || $model -> created_by == 1 || $model -> created_by == 2 || $model -> created_by == 3; // administrator editing is allowed only the the user that created it.
    }

    public function getFilter(Builder $builder) {
        return new PublishersFilter($builder);
    }

    public function getById($id, array $attributes = [])
    {
        $model =  parent::getById($id, $attributes);
        $model -> load ('administrator');
        return $model;
    }

    protected function save(array $attributes, $id = null)
    {
        $user = Auth::user();
        $user->loadPermissionAndPermissionGroups();

        $model = parent::save($attributes, $id);

        if(!$user->isA('app.administrator') && $id == null) {
            $model->owner = $user->id;
            $model -> save ();
        }
        return $model;
    }

    public function assignAdministrator ($id, $userId, $isRequested = false) {

        $model = $this->model->findOrFail($id);
        $user = $this->user -> where ('id', $userId) -> first ();
        if (!$this->isAdministratorIsEditableByUser($model, Auth::user()) && !$isRequested) {
            throw new NicoBadRequestException("Not allowed");
        }
        if(!$user) {
            throw new NicoException("Invalid user.");
        }

        $model -> owner = $user->id;
        Event::dispatch(new PublisherAdminAssignment($model, $user));
        $model -> save ();

    }

    public function removeAdministrator ($id) {
        $model = $this->model->findOrFail ($id);
        if (!$this->isAdministratorIsEditableByUser($model, Auth::user())) {
            throw new NicoBadRequestException("Not allowed");
        }
        $model -> owner = null;
        $model -> save ();
    }

    public function requestPublisher(array $attributes)
    {
        $requestPublisher = new RequestPublisher();      
        $model = $requestPublisher->create($attributes);

    }

     public function getPublisherRequestList(array $params = [], $paginate = true, array $attributes = [])
    {
        // return RequestPublisher::orderBy('created_by','desc')->get();
        return $requestPublihser = DB::table('request_publishers as r')
            ->select('r.id',
                    'r.title',
                    'r.street',
                    'r.city',
                    'r.phone_number',
                    'r.created_at',
                    'r.created_by',
                    'r.email',
		    'r.logo_url',
		    'r.certificate_url',
                    DB::raw("CONCAT(u.first_name,' ',u.last_name) AS user")
                    )
            ->join('users as u', 'u.id', '=', 'r.created_by')
	    ->where('r.deleted_at', null)
	    ->orderBy('r.id','desc')
            ->paginate(20);
        
    }

    public function getRequestPublisherById($id)
    {
        return $requestPublihser = DB::table('request_publishers as r')
        ->select('r.id',
                'r.title',
                'r.street',
                'r.city',
                'r.phone_number',
                'r.created_at',
                'r.created_by',
                'r.email',
		'r.logo_url',
		'r.certificate_url',
                DB::raw("CONCAT(u.first_name,' ',u.last_name) AS user")
                )
        ->join('users as u', 'u.id', '=', 'r.created_by')
        ->where('r.id',$id)->first();
        
    }

    public function acceptRequestPublisher($id)
    {
    
        $requestPublisherObj = RequestPublisher::find($id);
       
        $requestPublisherObj->updated_at =  Carbon :: now();     
        $requestPublisherObj->updated_by =  Auth::user()->id;
        $requestPublisherObj->deleted_at =  Carbon :: now();

        $requestPublisherObj->save();

        $copiedData = $requestPublisherObj->attributesToArray();
        $copiedData['owner'] = $requestPublisherObj->created_by;
        
       $publisher =  $this->model->newInstance();
       $publisher->fill($copiedData);
       $publisher->save();
    }

    public function requestPublisherOwnership($data)
    {
        $publisher = $data->get('publisher');
        $userId = $data->get('user');

        $model = $this->model->findOrFail($publisher);
        $user = $this->user -> where ('id', $userId) -> first ();
        
        if(!$model || !$user)
        {
            throw new NicoException("Invalid data.");
        }

        $reqOwnership =  new RequestPublisherOwnership();

        $reqOwnership->publisher =  $model->id;
        $reqOwnership->user =  $user->id;
        $reqOwnership->created_at =   Carbon :: now();
        $reqOwnership->updated_at =   Carbon :: now();

        $reqOwnership->save();

    }

    public function getPublisherRequestOwner(array $params = [], $paginate = true, array $attributes = [])
    {
        return $requestPublihserOwner = DB::table('request_publisher_ownership as r')
        ->select( 
                'r.id',                  
                'u.email',
                'r.created_at',
                'p.title',
                DB::raw("CONCAT(u.first_name,' ',u.last_name) AS user")
                )
        ->join('users as u', 'u.id', '=', 'r.user')
        ->join('publishers as p', 'p.id', '=', 'r.publisher')
	->where('r.deleted_at', null)
	->orderBy('r.id','desc')
        ->paginate(20);
    
    }

    public function acceptRequestPublisherOwner($id)
    {
        $requestPublisherObj = RequestPublisherOwnership::find($id);
       
        $publisher = $requestPublisherObj->publisher;
        $userId = $requestPublisherObj->user;

        $model = $this->model->findOrFail($publisher);
        $user = $this->user -> where ('id', $userId) -> first ();
        
        if(!$model || !$user)
        {
            throw new NicoException("Invalid data.");
        }

        $requestPublisherObj->updated_at =  Carbon :: now();     
        $requestPublisherObj->updated_by =  Auth::user()->id;
        $requestPublisherObj->deleted_at =  Carbon :: now();

        $requestPublisherObj->save();

       
        $copiedData['owner'] = $requestPublisherObj->user;
        
       
       $model->owner = $requestPublisherObj->user;
  
       $model->save();
    }

    public function getRequestPublisherOwnerList($request)
    {
	    $thisUser = Auth::user()->id;
	    $keyword = $request['keyword'];
	            $query = $this->model->select('*');

        if($keyword){
            $query->where('title','like',"%{$keyword}%");
        } else {
            $query->limit(200);
        }
	    return $query->orderBy('title')->get();
    }

}
