<?php

namespace App\Repositories\Api;

use Carbon\Carbon;
use App\Models\Auth\User;
use App\Models\City;
use App\Models\ServiceProviderToCity;
use App\Models\Category;
use App\Models\ServiceProviderToService;
use Illuminate\Support\Facades\DB;
use App\Exceptions\GeneralException;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Storage;

/**
 * Class ApiRepository.
 */
class ApiRepository
{
    /**
     * @var user, city, ServiceProviderToCity, ServiceProviderToService
     * 
     */
    protected $user;
    protected $city;
    protected $ServiceProviderToCity;
    protected $ServiceProviderToService;

    /**
     * ApiRepository constructor.
     *
     * @return User model instance $this->user
     */
    public function __construct()
    {
        $this->user = new User();
        $this->ServiceProviderToCity = new ServiceProviderToCity();
        $this->city = new City();
        $this->ServiceProviderToService = new ServiceProviderToService();
        $this->service = new Category();
    }

    /**
     * Find Auth by Token
     *
     * @param $authToken
     *
     * @return mixed
     */
    public function findByAuthToken($authToken)
    {
        $user = $this->user
            ->where('uuid', $authToken)
            ->first();
        if ($user instanceof $this->user) {
            return $user;
        } else {
            return false;
        }
    }

    /**
     * Find all City
     * 
     * @return json response
     */
    public function findAllCity()
    {
        $city = $this->city
            ->orderBy('city_name', 'asc')
            ->get();
        if ($city) {
            return $city;
        } else {
            return false;
        }
    }


    /**
     * Find all sevices
     * 
     * @return json response
     */
    public function findAllServices()
    {
        $service = $this->service
            ->orderBy('category_name', 'asc')
            ->get();
        if ($service) {
            return $service;
        } else {
            return false;
        }
    }

    /**
     * Find all service provider city
     * 
     * @param  UserID  $user_id
     * 
     * @return json response
     */
    public function serviceProviderCity($user_id = null)
    {
        $serviceProviderCity = $this->ServiceProviderToCity
            ->where('user_id',$user_id)
            ->get();
        if ($serviceProviderCity) {
            return $serviceProviderCity;
        } else {
            return false;
        }
    }


    /**
     * Find all service provider services
     * 
     * @param  UserID  $user_id
     * 
     * @return json response
     */
    public function serviceProviderService($user_id = null)
    {
        $serviceProviderService = $this->ServiceProviderToService
            ->where('user_id',$user_id)
            ->get();
        if ($serviceProviderService) {
            return $serviceProviderService;
        } else {
            return false;
        }
    }


    /**
     * Find user by condition
     * 
     * @param  Array $data
     * 
     * @return Array
     */
    public function findUserByCondition(array $data) : array
    {
        $returnArr = [];
        $users = $this->city
            ->where($data)
            ->with(array('serviceProviderCity'=>function($query) {
                    $query->with('user');
            }))
            ->get()->toArray();
        if ($users) {
            return $users;
        } else {
            return $returnArr;
        }
    }


    /**
     * @param       $authToken
     * @param array $input
     * @param bool|UploadedImage  $image
     * @param bool|UploadedFile  $document
     *
     * @return array|bool
     */
    public function update($authToken, array $input, $image = false, $document = false)
    {
        $user = $this->findByAuthToken($authToken);
        $user->first_name = $input['first_name'];
        $user->last_name = $input['last_name'];
        //$user->user_type = $input['user_type'];
        $user->company_service_desc = $input['company_service_desc'];
        $user->avatar_type = 'storage';

        // Upload profile image if necessary
        if ($image) {
            $user->avatar_location = $image->store('/avatars', 'public');
            Storage::disk('public')->delete(auth()->user()->avatar_location);
        }

        if ($document) {
            $user->document_location = $document->store('/document', 'public');
            Storage::disk('public')->delete(auth()->user()->document_location);
        }

        //Emails have to be unique
        $emailexist = $this->user
            ->where('email', $input['email'])
            ->where('id','<>', $user->id)
            ->first();
        if ($emailexist) {
            return false;
        } else {
            $user->email = $input['email'];
            $updated = $user->save();

            return $user;
        }
    }

    /**
     * @param UserId $user_id
     *
     * @return bool
     */

    function existsCityDelete($user_id) : bool
    {
        return DB::transaction(function () use ($user_id) {
            if($this->ServiceProviderToCity->where('user_id',$user_id)->delete()) {
                return true;
            }
            return false;
        });
    }

    /**
     * @param UserId $user_id
     *
     * @return bool
     */

    function existsServiceDelete($user_id) : bool
    {
        return DB::transaction(function () use ($user_id) {
            if($this->ServiceProviderToService->where('user_id',$user_id)->delete()) {
                return true;
            }
            return false;
         });
    }


    /**
     * @param array $data
     *
     * @return ServiceProviderToCity
     */
    public function createCity(array $data) : ServiceProviderToCity
    {
        return DB::transaction(function () use ($data) {
            $city = $this->ServiceProviderToCity->create([
                'user_id' => $data['user_id'],
                'city_id' => $data['city_id']
            ]);
            if ($city) {
                return $city;
            }
        });
    }

    /**
     * @param array $data
     *
     * @return ServiceProviderToService
     */
    public function createService(array $data) : ServiceProviderToService
    {
        return DB::transaction(function () use ($data) {
            $service = $this->ServiceProviderToService->create([
                'user_id' => $data['user_id'],
                'service_id' => $data['service_id']
            ]);
            if ($service) {
                return $service;
            }
        });
    }
}
