<?php

namespace App\Model\Table;

use Cake\ORM\Table;
use Cake\Validation\Validator;
use Cake\Auth\DefaultPasswordHasher;
use Cake\Network\Exception\BadRequestException;

class UsersTable extends Table
{
    public function initialize(array $config)
    {
        $this->hasMany('Links');
        $this->hasMany('Statistics');
        $this->hasMany('Invoices');
        $this->hasMany('Bundles');
        $this->belongsTo('Plans');
        $this->addBehavior('Timestamp');

        $this->hasMany('ADmad/HybridAuth.SocialProfiles');
        \Cake\Event\EventManager::instance()->on('HybridAuth.newUser', [$this, 'createUser']);
    }

    public function findAuth(\Cake\ORM\Query $query, array $options)
    {
        $user_status = 1;
        if (version_compare(get_option('app_version', '1.0.0'), '2.0.0', '<')) {
            $user_status = 'Active';
        }
        $query
            ->contain(['Plans'])
            ->where(['Users.username' => $options['username']])
            ->orwhere(['Users.email' => $options['username']])
            ->andwhere([
                'Users.status' => $user_status,
                'Users.id <>' => 1
            ]);

        return $query;
    }

    public function findSocial(\Cake\ORM\Query $query, array $options)
    {
        $query
            ->contain(['Plans'])
            ->where([
                'Users.status' => 1,
                'Users.id <>' => 1
            ]);

        return $query;
    }

    public function validationDefault(Validator $validator)
    {
        return $validator
            ->notEmpty('username', 'A username is required')
            ->add('username', [
                'alphaNumeric' => [
                    'rule' => ['alphaNumeric'],
                    'message' => __('alphaNumeric Only')
                ],
                'minLength' => [
                    'rule' => ['minLength', 5],
                    'message' => __('Minimum Length 5')
                ],
                'maxLength' => [
                    'rule' => ['maxLength', 255],
                    'message' => __('Maximum Length 255')
                ]
            ])
            ->add('username', 'checkReserved', [
                'rule' => function ($value, $context) {
                    $reserved_domains = explode(',', get_option('reserved_usernames'));
                    $reserved_domains = array_map('trim', $reserved_domains);
                    $reserved_domains = array_filter($reserved_domains);

                    if (in_array(strtolower($value), $reserved_domains)) {
                        return false;
                    }
                    return true;
                },
                'message' => __('This username is a reserved word.')
            ])
            ->add('username', [
                'unique' => [
                    'rule' => 'validateUnique',
                    'provider' => 'table',
                    'message' => __('Username already exists')
                ]
            ])
            ->add('username_compare', [
                'compare' => [
                    'rule' => ['compareWith', 'username'],
                    'message' => __('Not the same')
                ]
            ])
            ->notEmpty('password', 'A password is required')
            ->add('password', [
                'minLength' => [
                    'rule' => ['minLength', 5],
                    'message' => __('Minimum Length 5')
                ],
                'maxLength' => [
                    'rule' => ['maxLength', 25],
                    'message' => __('Maximum Length 25')
                ]
            ])
            ->add('password_compare', [
                'compare' => [
                    'rule' => ['compareWith', 'password'],
                    'message' => __('Not the same')
                ]
            ])
            ->notEmpty('email', 'An email is required')
            ->add('email', 'validFormat', [
                'rule' => 'email',
                'message' => __('E-mail must be valid')
            ])
            ->add('email', [
                'unique' => [
                    'rule' => 'validateUnique',
                    'provider' => 'table',
                    'message' => __('E-mail must be unique')
                ]
            ])
            ->add('email_compare', [
                'compare' => [
                    'rule' => ['compareWith', 'email'],
                    'message' => __('Not the same')
                ]
            ])
            //->notEmpty('first_name', __('This field should not be blank.'))
            //->notEmpty('last_name', __('This field should not be blank.'))
            ->add('redirect_type', 'inList', [
                'rule' => ['inList', array_keys(get_allowed_redirects())],
                'message' => __('Choose a valid value.')
            ]);
    }

    public function validationChangeEmail(Validator $validator)
    {
        //$validator = $this->validateDefault($validator);
        return $validator
            ->notEmpty('temp_email', 'An email is required')
            ->add('temp_email', 'validFormat', [
                'rule' => 'email',
                'message' => __('E-mail must be valid')
            ])
            ->add('temp_email', 'custom', [
                'rule' => function ($value, $context) {
                    $count = $this->find('all')
                        ->where(['email' => $value])
                        ->count();
                    if ($count > 0) {
                        return false;
                    } else {
                        return true;
                    }
                },
                'message' => __('E-mail must be unique')
            ])
            ->add('confirm_email', [
                'compare' => [
                    'rule' => ['compareWith', 'temp_email'],
                    'message' => __('Not the same')
                ]
            ]);
    }

    public function validationChangePassword(Validator $validator)
    {
        //$validator = $this->validateDefault($validator);
        return $validator
            ->notEmpty('current_password', 'Please enter current password.')
            ->add('current_password', 'custom', [
                'rule' => function ($value, $context) {
                    $user = $this->findById($context['data']['id'])->first();
                    return (new DefaultPasswordHasher)->check($value, $user->password);
                },
                'message' => __('Please enter current password.')
            ])
            ->notEmpty('password', 'A password is required')
            ->add('password', [
                'minLength' => [
                    'rule' => ['minLength', 5],
                    'message' => __('Minimum Length 5')
                ],
                'maxLength' => [
                    'rule' => ['maxLength', 25],
                    'message' => __('Maximum Length 25')
                ]
            ])
            ->add('confirm_password', [
                'compare' => [
                    'rule' => ['compareWith', 'password'],
                    'message' => __('Not the same')
                ]
            ]);
    }

    public function validationForgotPassword(Validator $validator)
    {
        //$validator = $this->validateDefault($validator);
        return $validator
            ->notEmpty('email', 'An email is required')
            ->add('email', 'validFormat', [
                'rule' => 'email',
                'message' => __('E-mail must be valid')
            ])
            ->notEmpty('password', 'A password is required')
            ->add('password', [
                'minLength' => [
                    'rule' => ['minLength', 5],
                    'message' => __('Minimum Length 5')
                ],
                'maxLength' => [
                    'rule' => ['maxLength', 25],
                    'message' => __('Maximum Length 25')
                ]
            ])
            ->add('confirm_password', [
                'compare' => [
                    'rule' => ['compareWith', 'password'],
                    'message' => __('Not the same')
                ]
            ]);
    }

    public function createUser(\Cake\Event\Event $event)
    {
        if ((bool)get_option('close_registration', false) ||
            (bool)get_option('private_service', false)) {
            session_destroy();
            throw new BadRequestException(__('Registration is currently closed.'));
        }

        // Entity representing record in social_profiles table
        $profile = $event->data()['profile'];

        $data = [
            'status' => 1,
            'username' => $profile->identifier,
            'password' => generate_random_string(10),
            'plan_id' => 1,
            'role' => 2,
            'api_token' => \Cake\Utility\Security::hash(\Cake\Utility\Text::uuid(), 'sha1', true),
            'register_ip' => get_ip()
        ];

        if (!empty($profile->email)) {
            $data['email'] = $profile->email;
        }

        if (!empty($profile->first_name)) {
            $data['first_name'] = $profile->first_name;
        }

        if (!empty($profile->last_name)) {
            $data['last_name'] = $profile->last_name;
        }

        $user = $this->newEntity($data);

        if ($this->save($user)) {
            $user = $this->find()->contain(['Plans'])->where(['Users.id' => $user->id])->first();
            return $user;
        } else {
            //debug($user->errors());
            \Cake\Log\Log::write('debug', $user->errors());
            session_destroy();
            throw new \RuntimeException('Unable to save new user');
        }
    }
}
