<?php

use Illuminate\Auth\UserTrait;
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableTrait;
use Illuminate\Auth\Reminders\RemindableInterface;
use Illuminate\Database\Eloquent\SoftDeletingTrait;

class User extends Eloquent implements UserInterface, RemindableInterface {

	use UserTrait,
		 RemindableTrait,
		 SoftDeletingTrait;

	public static $unguarded = true;
	protected $softDelete		 = true;

	/**
	 * The database table used by the model.
	 *
	 * @var string
	 */
	protected $table = 'users';

	/**
	 * The attributes excluded from the model's JSON form.
	 *
	 * @var array
	 */
	protected $hidden = array('password', 'remember_token', 'persist_code', 'remember_token');

	public function roles() {
		return $this->belongsToMany('Role', 'users_roles')->orderBy('name', 'ASC');
	}

  public function sessions() {
		return $this->hasMany('Session');
	}
  
	public function getPersistCode() {
		$this->persist_code	 = $this->getRandomString();
		$persistCode				 = $this->persist_code;
		$this->save();

		return $persistCode;
	}

	public function checkPersistCode($persistCode) {
		if (!$persistCode) {
			return false;
		}

		return $persistCode == $this->persist_code;
	}

	public function isSuperuser() {
		return $this->issuperuser;
	}

	public function isAdmin() {
		return $this->isSuperuser() ? $this->isSuperuser() : $this->isadmin;
	}

	public function hasRole($roleId) {
		$cacheKey	 = "access_user_{$this->id}_role_{$roleId}";
		$cacheTime = 5;
		if (Cache::has($cacheKey)) {
			return Cache::get($cacheKey);
		}
		if (is_numeric($roleId)) {
			if ($this->isAdmin()) {
				Cache::put($cacheKey, true, $cacheTime);
				return true;
			}
			$userRoles = $this->roles;
			foreach ($userRoles as $role) {
				if ($role->id == $roleId) {
					Cache::put($cacheKey, true, $cacheTime);
					return true;
				}
			}
		}
		Cache::put($cacheKey, false, $cacheTime);
		return false;
	}

	public function hasAnyRole($roles) {
		if ($this->isAdmin()) {
			return true;
		}
		if (is_array($roles)) {
			$userRoles = $this->roles->toArray();
			foreach ($roles as $roleId) {
				if (is_numeric($roleId)) {
					foreach ($userRoles as $role) {
						if ($role['id'] == $roleId) {
							return true;
						}
					}
				}
			}
		}
		return false;
	}

	public function projects() {
		return $this->belongsToMany('Project', 'users_projects')->orderBy('name', 'ASC');
	}

    public function hasProject($projectId) {
		$cacheKey	 = "access_user_{$this->id}_project_{$projectId}";
		$cacheTime = 0;
		if (Cache::has($cacheKey)) {
			return Cache::get($cacheKey);
		}
		if (is_numeric($projectId)) {
			if ($this->isAdmin()) {
				Cache::put($cacheKey, true, $cacheTime);
				return true;
			}
			$userProjects = $this->projects()->get();
			foreach ($userProjects as $project) {
				if ($project->id == $projectId) {
					Cache::put($cacheKey, true, $cacheTime);
					return true;
				}
			}
		}
		Cache::put($cacheKey, false, $cacheTime);
		return false;
	}
    
	public function budgetProjects() {
		return $this->belongsToMany('Project', 'users_projects')->whereUsebudget(1)->orderBy('name', 'ASC');
	}
	
	public function allBudgetProjects($exeptCurrentProjectId = null) {
		if($exeptCurrentProjectId == null){
			$projects = Project::whereUsebudget(1)->orderBy('name', 'ASC')->get();
		}else{
			$projects = Project::whereUsebudget(1)->where('id', '<>', $exeptCurrentProjectId)->orderBy('name', 'ASC')->get();
		}
		return $projects;
	}
	
	public function salaryProjects() {
		return $this->belongsToMany('Project', 'users_salary_projects')->orderBy('name', 'ASC');
	}

	public function usertasks() {
		return $this->belongsToMany('Usertask', 'usertasks_users');
	}

	public function getMyUsers() {
		$users = null;
		if (Auth::user()->isAdmin()) {
			$users = User::whereRaw('users.id IN (SELECT user_id FROM users_projects WHERE project_id IN (SELECT project_id FROM users_projects WHERE user_id=?))', array(Auth::user()->id))
							->whereIssuperuser(0)
							->orderBy('user_id', 'ASC')
							->orderBy('first_name', 'ASC')
							->orderBy('last_name', 'ASC')
							->get();
		}
		elseif (Auth::user()->hasRole(Role::ROLE_PROJECT_MANAGER)) {
			$users = User::whereUserId(Auth::user()->id)
							->whereIsadmin(0)
							->whereIssuperuser(0)
							->orderBy('user_id', 'ASC')
							->orderBy('first_name', 'ASC')
							->orderBy('last_name', 'ASC')
							->get();
		}
		else {
			$users = User::whereId(Auth::user()->id)->get();
		}
		return $users;
	}

	public function scopeMyUsers() {
		if (Auth::user()->isAdmin()) {
			$users = User::/*orderBy('user_id', 'ASC')
							->*/orderBy('first_name', 'ASC')
							->orderBy('last_name', 'ASC')
//							->paginate(100);
							->get();
		}
		else {
			$users = User::where(function ($query) {
								$query->where('id', Auth::user()->id)
								->orWhere('user_id', Auth::user()->id);
							})
//							->orderBy('user_id', 'ASC')
							->orderBy('first_name', 'ASC')
							->orderBy('last_name', 'ASC')
//							->paginate(100);
							->get();
		}
		$users->each(function ($user) {
			if ($user->id == 1) {
				$user->status = 'Суперадминистратор';
			}
			elseif (!$user->user_id) {
				$user->status = 'Администратор';
			}
			else {
				$user->status = 'Пользователь';
			}
		});
		return $users;
	}

	public function scopeAllUsers() {
		$users = User::withTrashed()
						->orderBy('id', 'ASC')
//						->paginate(100);
						->get();

		$users->each(function ($user) {
			if ($user->id == 1) {
				$user->status = 'Суперадминистратор';
			}
			elseif (!$user->user_id) {
				$user->status = 'Администратор';
			}
			else {
				$user->status = 'Пользователь';
			}
		});

		return $users;
	}

	function getUsertasksQuant() {
		return Usertask::join('usertasks_users', function($join) {
											$join->on('usertasks_users.usertask_id', '=', 'usertasks.id');
										})
										->where('usertasks_users.user_id', '=', $this->id)
										->whereRaw('usertasks.id NOT IN (SELECT usertask_id FROM usertask_results WHERE DATE(created_at)=DATE(NOW()) AND user_id=?)', array($this->id))
										->count();
	}

	public function getRandomString($length = 42) {
		if (function_exists('openssl_random_pseudo_bytes')) {
			$bytes = openssl_random_pseudo_bytes($length * 2);

			if ($bytes === false) {
				throw new \RuntimeException('Unable to generate random string.');
			}

			return substr(str_replace(array('/', '+', '='), '', base64_encode($bytes)), 0, $length);
		}

		$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

		return substr(str_shuffle(str_repeat($pool, 5)), 0, $length);
	}

	//Первоначальная настройка пользователя после регистрации
	public function signUpInit($password) {
		//отправляем приветственное сообщение пользователю
		$subject						 = 'Добро пожаловать на leadstat.ru';
		$email							 = $this->email;
		$view								 = 'emails.auth.welcome';
		$data['email']			 = $this->email;
		$data['password']		 = $password;
		$data['first_name']	 = $this->first_name;
		$data['last_name']	 = $this->last_name;
		Mail::queue($view, $data, function($message) use($email, $subject) {
			$message->to($email)->subject($subject);
		});
	}

	public function changePassword($data) {
		$result = array();

		$this->password = e(Hash::make($data['newPassword']));

		if ($this->save()) {
			$result['success'] = true;
			$result['message'] = trans('users.passwordchg');
		}
		else {
			$result['success'] = false;
			$result['message'] = trans('users.passwordprob');
		}
		return $result;
	}

	public function setPaySalaryAttribute($value) {
		$value													 = str_replace(',', '.', $value);
		$value													 = str_replace(' ', '', $value);
		$this->attributes['pay_salary']	 = round($value * 100, 0);
	}

	public function getPaySalaryAttribute() {
		return round($this->attributes['pay_salary'] / 100, 2);
	}

	public function setPaySalaryDayAttribute($value) {
		$value															 = str_replace(',', '.', $value);
		$value															 = str_replace(' ', '', $value);
		$this->attributes['pay_salary_day']	 = round($value * 100, 0);
	}

	public function getPaySalaryDayAttribute() {
		return round($this->attributes['pay_salary_day'] / 100, 2);
	}

	public function setPayPercentAllAttribute($value) {
		$value															 = str_replace(',', '.', $value);
		$value															 = str_replace(' ', '', $value);
		$this->attributes['pay_percent_all'] = round($value * 100, 0);
	}

	public function getPayPercentAllAttribute() {
		return round($this->attributes['pay_percent_all'] / 100, 2);
	}

	public function setPayPercentMarginAttribute($value) {
		$value																	 = str_replace(',', '.', $value);
		$value																	 = str_replace(' ', '', $value);
		$this->attributes['pay_percent_margin']	 = round($value * 100, 0);
	}

	public function getPayPercentMarginAttribute() {
		return round($this->attributes['pay_percent_margin'] / 100, 2);
	}

	public function setPayPercentMarginAllAttribute($value) {
		$value																			 = str_replace(',', '.', $value);
		$value																			 = str_replace(' ', '', $value);
		$this->attributes['pay_percent_margin_all']	 = round($value * 100, 0);
	}

	public function getPayPercentMarginAllAttribute() {
		return round($this->attributes['pay_percent_margin_all'] / 100, 2);
	}

	public function setLateFeeAttribute($value) {
		$value												 = str_replace(',', '.', $value);
		$value												 = str_replace(' ', '', $value);
		$this->attributes['late_fee']	 = round($value * 100, 0);
	}

	public function getLateFeeAttribute() {
		return round($this->attributes['late_fee'] / 100, 2);
	}

	// слева панель навигации - общее кол-во заявок по всем проектам, которые нужно обработать для разных ролей
	public function getCountRequestNav() {
		$requestsForSign  = 0; // подписать заявок
		$requestsSigned   = 0; // финдиректору - одобрить подписанных
		$requestsApproved = 0; // бух. - оплатить одобренных
		
		$requestsBackOff = BudgetCostsRequests::whereApplicantId(Auth::user()->id) // возврат от директора
																					->whereStatus(BudgetCostsRequests::STATUS_BACK_OFF)
																					->orderBy('created_at', 'DESC')
																					->count();
		
		if ($this->hasRole(Role::ROLE_BUDGET_SIGN_COST_REQUEST) && !$this->isAdmin()) { 
			$requestsForSign = BudgetCostsRequests::whereDirectorId($this->id)
																						->whereStatus(BudgetCostsRequests::STATUS_WORK)
																						->orderBy('created_at', 'DESC')
																						->count();
		}
		
		if ($this->hasRole(Role::ROLE_BUDGET_CFO) && !$this->isAdmin()) {
		  $requestsSigned = BudgetCostsRequests::whereStatus(BudgetCostsRequests::STATUS_SIGNED)
																					 ->orderBy('created_at', 'DESC')
																					 ->count();
		}
		else if ( $this->hasAnyRole(array(Role::ROLE_BUDGET_ACCOUNTANT, Role::ROLE_BUDGET_ACC_SECRETARY)) && !$this->isAdmin() ) {
			$requestsApproved = BudgetCostsRequests::whereStatus(BudgetCostsRequests::STATUS_APPROVED)
							                               ->whereRaw('project_id IN (SELECT project_id FROM users_projects WHERE user_id=' . Auth::user()->id . ')')
																						 ->orderBy('created_at', 'DESC')
																						 ->count();
		}
		$result = $requestsBackOff + $requestsForSign + $requestsSigned + $requestsApproved;
						
		return $result;
	}

	// выбирает все бюджетные проекты + те, у которых были расходные операции за период
	// иначе в таблицу  расходов не попадают операции проектов, у которых в текущем месяце был отключен бюджет
	public function notNullCostsBudjetProjects($startDate = null, $endDate = null){
		$dateRaw = '';
		
		if($startDate && $endDate){
			$date					 = explode('.', $startDate);
			$startDateRaw	 = "{$date[2]}-{$date[1]}-{$date[0]}";

			$date					 = explode('.', $endDate);
			$endDateRaw	 = "{$date[2]}-{$date[1]}-{$date[0]}";
			
		  $dateRaw = "AND budget_operations.date >= '$startDateRaw' AND budget_operations.date <= '$endDateRaw'";
		}
		$projects = Project::leftJoin('budget_operations', 'projects.id', '=', 'budget_operations.project_id')
						           ->select(DB::raw('projects.*'))
						           ->whereRaw('projects.usebudget = 1 OR (budget_operations.type = 1 AND budget_operations.deleted_at IS NULL '.$dateRaw.')')
						           ->groupBy('projects.id')
						           ->orderBy('projects.name')
						           ->get();
		
		return $projects;
	}
	
	// сумма з/п сотрудников по месяцам по одному проекту
	public function getUserBudgetSalaryByMonth($projectId, $monthRange = null) {
		if(!$monthRange){
			$monthRange = 0;
		}
		$startDate = date("Y-m-01");

		$budgetSalaryAmount = BudgetSalary::whereProjectId($projectId)
																					->whereSalaryUserId($this->id)
																					->where('budget_salary.salary_date', '>=', DB::raw('DATE("'.$startDate.'") - INTERVAL '.$monthRange.' MONTH'))                   
						                              ->select(DB::raw('sum(budget_salary.amount)/100 as sum, MONTH(budget_salary.salary_date) as month, YEAR(budget_salary.salary_date) as year, budget_salary.salary_date as date'))
						                              ->groupBy(DB::raw('YEAR(budget_salary.salary_date)'))
																					->groupBy(DB::raw('MONTH(budget_salary.salary_date)'))
						                              ->orderBy('budget_salary.salary_date', 'DESC')
																					->get();

		$operaions = array();
		foreach($budgetSalaryAmount as $item){
			$id = $item['month'].'-'.$item['year'];
			$operaions[$id] = $item;
		}

		return $operaions;
	}
	
    // массив з/п пользователей с их з/п проектами
    public function getSalaryUsersProjects() {
      $salaryUsersProjects = UsersSalaryProject::whereNull('p.deleted_at')
                                                 ->leftJoin('projects as p', 'p.id', '=', 'users_salary_projects.project_id')
						                         ->select(DB::raw('users_salary_projects.user_id as user_id, users_salary_projects.project_id as project_id, p.name as project_name'))
						                         ->withTrashed()
						                         ->get();

		$usersProjects = array();
		foreach($salaryUsersProjects as $user){
			$usersProjects[$user->user_id][$user->project_id] = $user->project_name;
        }
      
      return $usersProjects;
    }
    
  // массив id бюджетных проектов пользователя
  public function getBudgetProjectsId() {
      $userBudgetProjects = $this->budgetProjects()->get();

		$projectsId = array();
		foreach($userBudgetProjects as $item){
			$projectsId[] = $item['id'];
		}
    
      return $projectsId;
  }
	
	public function sendOperationsSum($content, $date) {
		$subject						 = 'Leadstat: выписка за '.$date;
		$email							 = $this->email;
		$view								 = 'budget.emails.operations_sum';
		$data['content']		 = $content;

		Mail::queue($view, $data, function($message) use($email, $subject) {
			$message->to($email)->subject($subject);
		});
		
	}
}