<?php
/*
 * Import the Google SDK and load all the classes
 */
include(plugin_dir_path(__FILE__) . 'google-sdk/autoload.php');

/**
 * Class JobsearchGoogle
 */
class JobsearchGoogle
{
    private $client_id = '';
    private $client_secret = '';
    private $redirect_url = '';
    private $login_redirect_url = '';
    private $google_details;
    private $state_token;

    public function __construct()
    {
        global $jobsearch_plugin_options;

        $login_page = isset($jobsearch_plugin_options['user-login-template-page']) ? $jobsearch_plugin_options['user-login-template-page'] : '';
        $login_page = jobsearch__get_post_id($login_page, 'page');

        $client_id = isset($jobsearch_plugin_options['jobsearch-google-client-id']) ? $jobsearch_plugin_options['jobsearch-google-client-id'] : '';
        $client_secret = isset($jobsearch_plugin_options['jobsearch-google-client-secret']) ? $jobsearch_plugin_options['jobsearch-google-client-secret'] : '';

        $this->redirect_url = home_url('/');
        $this->state_token = $this->generate_state_token();

        if (get_post_type($login_page) == 'page') {
            $this->login_redirect_url = get_permalink($login_page);
        }
        $this->client_id = $client_id;
        $this->client_secret = $client_secret;

        add_action('wp', array($this, 'set_access_tokes'), 50);
        add_shortcode('jobsearch_google_login', array($this, 'renderShortcode'));

        if (!isset($_GET['jobsearch_instagram_login'])) {
            add_action('jobsearch_apply_job_with_google', array($this, 'apply_job_with_google'), 10, 1);
            add_action('wp_ajax_jobsearch_applying_job_with_google', array($this, 'applying_job_with_google'));
            add_action('wp_ajax_nopriv_jobsearch_applying_job_with_google', array($this, 'applying_job_with_google'));
        }
    }

    private function generate_state_token() {
        if (!isset($_SESSION['google_state_token'])) {
            $_SESSION['google_state_token'] = bin2hex(random_bytes(16));
        }
        return $_SESSION['google_state_token'];
    }

    public function set_access_tokes()
    {
	if (!isset($_GET['code'])) { 
		return;
	}

        // Validate state token
        if (!isset($_GET['state']) || $_GET['state'] !== $this->state_token) {
            wp_die(__('Invalid state token', 'wp-jobsearch'));
        }

        // Validate scope
        if (!isset($_GET['scope'])) {
            wp_die(__('Missing scope parameter', 'wp-jobsearch'));
        }

        $get_scope = urldecode($_GET['scope']);
        if (strpos($get_scope, 'googleapis') !== false) {
            $this->google_callback();
        }
    }

    public function google_callback()
    {
        global $jobsearch_plugin_options;

        if (is_user_logged_in()) {
            if (is_admin()) {
                wp_redirect(admin_url('/'), 302);
                exit;
            }

            $user_dashboard_page = isset($jobsearch_plugin_options['user-dashboard-template-page']) ? $jobsearch_plugin_options['user-dashboard-template-page'] : '';
            $user_dashboard_page = isset($user_dashboard_page) && !empty($user_dashboard_page) ? jobsearch__get_post_id($user_dashboard_page, 'page') : 0;
            $real_redirect_url = $user_dashboard_page > 0 ? get_permalink($user_dashboard_page) : home_url('/');
            wp_redirect($real_redirect_url, 302);
            exit;
        }

        if (!isset($_GET['code'])) {
            wp_die(__('Authentication failed: missing code', 'wp-jobsearch'));
        }

        $client = new Google_Client();
        $client->setApplicationName('Login Check');
        $client->setClientId($this->client_id);
        $client->setClientSecret($this->client_secret);
        $client->setRedirectUri($this->redirect_url);
        $client->addScope("email");
        $client->addScope("profile");

        try {
            $client->authenticate($_GET['code']);
            $access_token = $client->getAccessToken();

            if (is_wp_error($access_token)) {
                wp_die(__('Failed to authenticate with Google', 'wp-jobsearch'));
            }

            $service = new Google_Service_Oauth2($client);
            $client->setAccessToken($access_token);
            $this->google_details = $service->userinfo->get();

            if (empty($this->google_details)) {
                wp_die(__('Failed to retrieve user details from Google', 'wp-jobsearch'));
            }

            // First try to login existing user
            if (!$this->loginUser()) {
                // Otherwise create new account
                $this->createUser();
            }

            $real_redirect_url = $this->get_safe_redirect_url();
            wp_redirect($real_redirect_url);
            exit();
        } catch (Exception $e) {
            wp_die(__('Google authentication error: ', 'wp-jobsearch') . $e->getMessage());
        }
    }

    private function get_safe_redirect_url() {
        global $jobsearch_plugin_options;
        
        $default_url = home_url('/');
        $user_dashboard_page = isset($jobsearch_plugin_options['user-dashboard-template-page']) ? $jobsearch_plugin_options['user-dashboard-template-page'] : '';
        $user_dashboard_page = isset($user_dashboard_page) && !empty($user_dashboard_page) ? jobsearch__get_post_id($user_dashboard_page, 'page') : 0;
        $default_url = $user_dashboard_page > 0 ? get_permalink($user_dashboard_page) : $default_url;

        // Validate redirect URL from cookie
        if (isset($_COOKIE['google_redirect_url']) && $_COOKIE['google_redirect_url'] != '') {
            $redirect_url = esc_url_raw($_COOKIE['google_redirect_url']);
            if (wp_validate_redirect($redirect_url, $default_url) === $redirect_url) {
                unset($_COOKIE['google_redirect_url']);
                setcookie('google_redirect_url', null, -1, '/');
                return $redirect_url;
            }
        }

        return apply_filters('jobsearch_after_social_login_redirect_url', $default_url, 'google');
    }

    public static function getLoginURL()
    {
        $client = new Google_Client();
        $client->setApplicationName('Login Check');
        $client->setClientId($this->client_id);
        $client->setClientSecret($this->client_secret);
        $client->setRedirectUri($this->redirect_url);
        $client->addScope("email");
        $client->setState($this->state_token);

        $service = new Google_Service_Oauth2($client);
        $authUrl = $client->createAuthUrl();

        return $authUrl;
    }

    public function renderShortcode()
    {
        $client = new Google_Client();
        $client->setApplicationName('Login Check');
        $client->setClientId($this->client_id);
        $client->setClientSecret($this->client_secret);
        $client->setRedirectUri($this->redirect_url);
        $client->addScope("email");
        $client->addScope("profile");
        $client->setState($this->state_token);

        $service = new Google_Service_Oauth2($client);
        $authUrl = $client->createAuthUrl();

        if (isset($authUrl)) {
            echo '<li><a class="jobsearch-google-plus-bg" data-original-title="google" href="' . esc_url($authUrl) . '"><div class="jobsearch-google-svg"><div></div></div>' . __('Sign in with Google', 'wp-jobsearch') . '</a></li>';
        }
    }

    private function loginUser()
    {
        if (empty($this->google_details->id)) {
            return false;
        }

        $wp_users = get_users(array(
            'meta_key' => 'jobsearch_google_id',
            'meta_value' => $this->google_details->id,
            'number' => 1,
            'count_total' => false,
            'fields' => 'id',
        ));

        if (empty($wp_users[0])) {
            return false;
        }

        // Additional verification - check email matches
        $user = get_user_by('id', $wp_users[0]);
        if ($user->user_email !== $this->google_details->email) {
            return false;
        }

        wp_set_auth_cookie($wp_users[0]);
        $this->do_apply_job_with_google($wp_users[0]);

        return true;
    }

    public function jobsearch_is_valid_domain($url) {
        $url = (false === strpos($url, '://')) ? 'http://' . $url : $url;
        
        if (!filter_var($url, FILTER_VALIDATE_URL)) {
            return false;
        }
        
        $parsed = parse_url($url);
        if (!isset($parsed['host'])) {
            return false;
        }
        
        // Add any additional domain validation here
        
        return true;
    }

    private function createUser()
    {
        global $jobsearch_plugin_options;
        
        if (empty($this->google_details)) {
            return false;
        }

        $google_user = $this->google_details;
        $user_id = isset($google_user->id) ? $google_user->id : '';
        $email = isset($google_user->email) ? sanitize_email($google_user->email) : '';

        if (!is_email($email)) {
            wp_die(__('Invalid email address from Google', 'wp-jobsearch'));
        }

        // Check if email already exists
        if (email_exists($email)) {
            $existing_user = get_user_by('email', $email);
            update_user_meta($existing_user->ID, 'jobsearch_google_id', $user_id);
            $this->loginUser();
            return;
        }

        $first_name = isset($google_user->given_name) ? sanitize_text_field($google_user->given_name) : '';
        $last_name = isset($google_user->family_name) ? sanitize_text_field($google_user->family_name) : '';
        $name = isset($google_user->name) ? sanitize_text_field($google_user->name) : '';

        $user_pic = isset($google_user->picture) ? esc_url_raw($google_user->picture) : '';
        if (!empty($user_pic) && !$this->jobsearch_is_valid_domain($user_pic)) {
            $user_pic = '';
        }

        // Generate username
        $username = '';
        if ($name != '') {
            $username = sanitize_user(str_replace(' ', '_', strtolower($name)));
        } else {
            $flusername = $first_name . $last_name;
            $username = sanitize_user(str_replace(' ', '_', strtolower($flusername)));
        }
        
        if ($username == '') {
            $username = 'user_' . rand(10000, 99999);
        }
        
        if (username_exists($username)) {
            $username .= '_' . rand(10000, 99999);
        }

        // Create user with secure password
        $user_pass = wp_generate_password(16, true, true);
        $new_user = wp_create_user($username, $user_pass, $email);

        if (is_wp_error($new_user)) {
            wp_die($new_user->get_error_message());
        }

        // Set user role
        $user_role = 'jobsearch_candidate';
        wp_update_user(array('ID' => $new_user, 'role' => $user_role));

        $user_candidate_id = jobsearch_get_user_candidate_id($new_user);

        // Handle profile picture securely
        if ($user_pic && filter_var($user_pic, FILTER_VALIDATE_URL) && $this->jobsearch_is_valid_domain($user_pic)) {
            jobsearch_upload_attach_with_external_url($user_pic, $user_candidate_id);
        }

        $this->do_apply_job_with_google($new_user);

        // Set user meta
        update_user_meta($new_user, 'first_name', $first_name);
        update_user_meta($new_user, 'last_name', $last_name);
        update_user_meta($new_user, 'jobsearch_google_id', $user_id);

        $candidate_auto_approve = isset($jobsearch_plugin_options['candidate_auto_approve']) ? $jobsearch_plugin_options['candidate_auto_approve'] : '';
        if ($candidate_auto_approve == 'on' || $candidate_auto_approve == 'email') {
            update_post_meta($user_candidate_id, 'jobsearch_field_candidate_approved', 'on');
        }

        $c_user = get_user_by('ID', $new_user);
        do_action('jobsearch_new_user_register', $c_user, $user_pass);
        
        wp_set_auth_cookie($new_user);
    }

    public function do_apply_job_with_google($user_id)
    {
        global $jobsearch_plugin_options;

        if (!isset($_COOKIE['jobsearch_apply_google_jobid']) || !is_numeric($_COOKIE['jobsearch_apply_google_jobid'])) {
            return;
        }

        $job_id = intval($_COOKIE['jobsearch_apply_google_jobid']);
        if ($job_id <= 0 || get_post_type($job_id) !== 'job') {
            return;
        }

        $candidate_auto_approve = isset($jobsearch_plugin_options['candidate_auto_approve']) ? $jobsearch_plugin_options['candidate_auto_approve'] : '';
        $user_is_candidate = jobsearch_user_is_candidate($user_id);

        $apply_job_cond = true;
        if ($candidate_auto_approve != 'on') {
            $apply_job_cond = false;
            if ($user_is_candidate) {
                $candidate_id = jobsearch_get_user_candidate_id($user_id);
                $candidate_status = get_post_meta($candidate_id, 'jobsearch_field_candidate_approved', true);
                if ($candidate_status == 'on') {
                    $apply_job_cond = true;
                }
            }
        }
        if ($candidate_auto_approve == 'email') {
            $apply_job_cond = true;
        }

        if ($user_is_candidate && $apply_job_cond) {
            $candidate_id = jobsearch_get_user_candidate_id($user_id);

            jobsearch_create_user_meta_list($job_id, 'jobsearch-user-jobs-applied-list', $user_id);
            $job_applicants_list = get_post_meta($job_id, 'jobsearch_job_applicants_list', true);
            if ($job_applicants_list != '') {
                $job_applicants_list = explode(',', $job_applicants_list);
                if (!in_array($candidate_id, $job_applicants_list)) {
                    $job_applicants_list[] = $candidate_id;
                }
                $job_applicants_list = implode(',', $job_applicants_list);
            } else {
                $job_applicants_list = $candidate_id;
            }
            update_post_meta($job_id, 'jobsearch_job_applicants_list', $job_applicants_list);
        }

        unset($_COOKIE['jobsearch_apply_google_jobid']);
        setcookie('jobsearch_apply_google_jobid', null, -1, '/');
    }

    public function applying_job_with_google()
    {
        $nonce_val = sanitize_key(wp_unslash($_POST['_nonce']));
        if (!wp_verify_nonce($nonce_val, 'jobsearch_ajax_nonce')) {
            wp_send_json_error(esc_html__('You are not allowed to do this.', 'wp-jobsearch'));
        }
        
        $job_id = isset($_POST['job_id']) ? intval($_POST['job_id']) : 0;
        if ($job_id <= 0 || get_post_type($job_id) !== 'job') {
            wp_send_json_error(esc_html__('Invalid job ID', 'wp-jobsearch'));
        }

        $real_redirect_url = get_permalink($job_id);
        setcookie('jobsearch_apply_google_jobid', $job_id, time() + (180), "/", COOKIE_DOMAIN, is_ssl(), true);
        setcookie('google_redirect_url', $real_redirect_url, time() + (360), "/", COOKIE_DOMAIN, is_ssl(), true);

        $client = new Google_Client();
        $client->setClientId($this->client_id);
        $client->setClientSecret($this->client_secret);
        $client->setRedirectUri($this->redirect_url);
        $client->addScope("email");
        $client->setState($this->state_token);

        $service = new Google_Service_Oauth2($client);
        $authUrl = $client->createAuthUrl();

        wp_send_json_success(array('redirect_url' => $authUrl));
    }

    public function apply_job_with_google($args = array())
    {
        global $jobsearch_plugin_options;
        $google_login = isset($jobsearch_plugin_options['google-social-login']) ? $jobsearch_plugin_options['google-social-login'] : '';
        if ($google_login == 'on') {
            $job_id = isset($args['job_id']) ? intval($args['job_id']) : 0;
            if ($job_id <= 0) {
                return;
            }

            $classes = isset($args['classes']) && !empty($args['classes']) ? esc_attr($args['classes']) : 'jobsearch-applyjob-google-btn';
            $label = isset($args['label']) ? esc_html($args['label']) : '';
            $view = isset($args['view']) ? esc_attr($args['view']) : '';

            switch ($view) {
                case 'job2':
                    echo '<a href="javascript:void(0);" class="' . $classes . '" data-id="' . $job_id . '">' . $label . '</a>';
                    break;
                case 'job3':
                    echo '<li><a href="javascript:void(0);" class="' . $classes . '" data-id="' . $job_id . '"></a></li>';
                    break;
                case 'job4':
                    echo '<a href="javascript:void(0);" class="' . $classes . '" data-id="' . $job_id . '"><i class="fa fa-google"></i> ' . esc_html__('Apply with Google', 'wp-jobsearch') . '</a>';
                    break;
                case 'job5':
                    echo '<li><a href="javascript:void(0);" class="' . $classes . '" data-id="' . $job_id . '"><i class="fa fa-google"></i> ' . esc_html__('Apply with Google', 'wp-jobsearch') . '</a></li>';
                    break;
                default:
                    echo '<li><a href="javascript:void(0);" class="' . $classes . '" data-id="' . $job_id . '"><i class="fa fa-google"></i> ' . esc_html__('Google', 'wp-jobsearch') . '</a></li>';
            }
        }
    }
}

new JobsearchGoogle();