<?php

namespace WeDevs\AppBridge\Core\Auth;

use Hybridauth\Hybridauth;
use WP_Error;
use Exception;

class SocialLogin {

    /**
     * Singleton class instance holder
     *
     * @since 1.0.0
     *
     * @var object
     */
    private static $instance;

    /**
     * Callback url
     *
     * @since 1.0.0
     *
     * @var null
     */
    private $callback = null;

    /**
     * Make a class instance
     *
     * @since 1.0.0
     *
     * @return object
     */
    public static function instance() {
        if ( ! isset( self::$instance ) && ! ( self::$instance instanceof self ) ) {
            self::$instance = new self();
        }

        return self::$instance;
    }

    /**
     * Class constructor
     *
     * @since 1.0.0
     *
     * @return void
     */
    public function __construct() {
        $default_callback = $this->get_page_url( 'myaccount' );
        $this->set_callback( $default_callback );
    }

    public function get_page_url( $page ) {
        if ( function_exists( 'dokan_get_page_url' ) ) {
            return dokan_get_page_url( $page, 'woocommerce' );
        }

        $page_id = wc_get_page_id( $page );

        return get_enclosed( $page_id );
    }

    /**
     * Get setting option
     *
     * @param string $key
     * @param string $section
     * @param mixed  $default_value
     *
     * @return mixed
     */

    public function get_settings_option( $key, $section, $default_value = '' ) {
        if ( function_exists( 'dokan_get_option' ) && apply_filters( 'app_bridge_helper_use_dokan_get_option', true ) ) {
            return dokan_get_option( $key, $section, $default_value );
        }

        $settings = get_option( 'app_bridge_helper_dokan_social_api', [] );

        $social_map = [
            'fb_app_id'           => [ 'facebook', 'id' ],
            'fb_app_secret'       => [ 'facebook', 'secret' ],
            'google_app_id'       => [ 'google', 'id' ],
            'google_app_secret'   => [ 'google', 'secret' ],
            'twitter_app_id'      => [ 'twitter', 'id' ],
            'twitter_app_secret'  => [ 'twitter', 'secret' ],
            'linkedin_app_id'     => [ 'linkedin', 'id' ],
            'linkedin_app_secret' => [ 'linkedin', 'secret' ],
            'apple_service_id'    => [ 'apple', 'id' ],
            'apple_team_id'       => [ 'apple', 'team_id' ],
            'apple_key_id'        => [ 'apple', 'key_id' ],
            'apple_key_content'   => [ 'apple', 'key_content' ],
        ];

        if ( array_key_exists( $key, $social_map ) ) {
            $platform = $social_map[ $key ][0];
            $field    = $social_map[ $key ][1];

            if ( ! empty( $settings[ $platform ][ $field ] ) ) {
                return $settings[ $platform ][ $field ];
            }
        }

        return $default_value;
    }

    /**
     * Is social login enabled or not
     *
     * @since 1.0.0
     *
     * @return bool
     */
    public function is_enabled() {
        $settings = $this->get_settings_option( 'enabled', 'dokan_social_api', 'off' );
        return dokan_validate_boolean( $settings );
    }

    /**
     * Set callback url
     *
     * @since 1.0.0
     *
     * @param string $callback
     *
     * @return void
     */
    public function set_callback( $callback ) {
        $this->callback = $callback;
    }

    /**
     * Get callback url
     *
     * @since 1.0.0
     *
     * @return string
     */
    public function get_callback() {
        return $this->callback;
    }

    /**
     * Get social login providers config
     *
     * @since 1.0.0
     *
     * @return array
     */
    public function get_providers_config() {
        $config = [
            'callback' => $this->get_callback(),
            'providers' => [
                'Facebook'    => [
                    'enabled'        => false,
                    'keys'           => [
                        'id'     => $this->get_settings_option( 'fb_app_id', 'dokan_social_api' ),
                        'secret' => $this->get_settings_option( 'fb_app_secret', 'dokan_social_api' ),
                    ],
                    'trustForwarded' => false,
                    'scope'          => 'email, public_profile',
                ],
                'Google'     => [
                    'enabled' => false,
                    'keys'    => [
                        'id'     => $this->get_settings_option( 'google_app_id', 'dokan_social_api' ),
                        'secret' => $this->get_settings_option( 'google_app_secret', 'dokan_social_api' ),
                    ],
                ],
                'Twitter'    => [
                    'enabled'      => false,
                    'keys'         => [
                        'key'    => $this->get_settings_option( 'twitter_app_id', 'dokan_social_api' ),
                        'secret' => $this->get_settings_option( 'twitter_app_secret', 'dokan_social_api' ),
                    ],
                    'includeEmail' => true,
                ],
                'LinkedIn'   => [
                    'enabled' => false,
                    'keys'    => [
                        'id'     => $this->get_settings_option( 'linkedin_app_id', 'dokan_social_api' ),
                        'secret' => $this->get_settings_option( 'linkedin_app_secret', 'dokan_social_api' ),
                    ],
                ],
                'Apple' => [
                    'enabled' => false,
                    'scope'   => 'name email',
                    'keys'    => [
                        'id'          => $this->get_settings_option( 'apple_service_id', 'dokan_social_api' ),
                        'team_id'     => $this->get_settings_option( 'apple_team_id', 'dokan_social_api' ),
                        'key_id'      => $this->get_settings_option( 'apple_key_id', 'dokan_social_api' ),
                        'key_content' => $this->get_settings_option( 'apple_key_content', 'dokan_social_api' ),
                    ],
                    'verifyTokenSignature' => false,
                    'authorize_url_parameters' => [
                        'response_mode' => 'form_post',
                    ],
                ],
            ],
        ];

        //facebook config from admin
        if ( $config['providers']['Facebook']['keys']['id'] !== '' && $config['providers']['Facebook']['keys']['secret'] !== '' ) {
            $config['providers']['Facebook']['enabled'] = true;
        }

        //google config from admin
        if ( $config['providers']['Google']['keys']['id'] !== '' && $config['providers']['Google']['keys']['secret'] !== '' ) {
            $config['providers']['Google']['enabled'] = true;
        }

        //linkedin config from admin
        if ( $config['providers']['LinkedIn']['keys']['id'] !== '' && $config['providers']['LinkedIn']['keys']['secret'] !== '' ) {
            $config['providers']['LinkedIn']['enabled'] = true;
        }

        //Twitter config from admin
        if ( $config['providers']['Twitter']['keys']['key'] !== '' && $config['providers']['Twitter']['keys']['secret'] !== '' ) {
            $config['providers']['Twitter']['enabled'] = true;
        }

        // apple config from the admin
        if ( $config['providers']['Apple']['keys']['id'] !== '' &&
            $config['providers']['Apple']['keys']['team_id'] !== '' &&
            $config['providers']['Apple']['keys']['key_id'] !== '' &&
            $config['providers']['Apple']['keys']['key_content'] !== ''
        ) {
            $config['providers']['Apple']['enabled'] = true;
        }

        /**
         * Filter the Config array of Hybridauth
         *
         * @since 1.0.0
         *
         * @param array $config
         */
        $config = apply_filters( 'dokan_social_providers_config', $config );

        return $config;
    }

    /**
     * Get WP User from social login access token
     *
     * @since 1.0.0
     *
     * @param string $provider
     * @param string $access_token
     *
     * @return \WP_User|\WP_Error
     */
    public function get_wp_user( $provider, $access_token ) {
        try {
            $config     = $this->get_providers_config();
            $hybridauth = new Hybridauth( $config );

            $adapter = $hybridauth->getAdapter( $provider );
            if ( $provider === 'apple' ) {
                $adapter->setAccessToken( [ 'id_token' => $access_token ] );
            } else {
                $adapter->setAccessToken( [ 'access_token' => $access_token ] );
            }
            $user_profile = $adapter->getUserProfile();

            if ( empty( $user_profile->email ) ) {
                return new WP_Error(
                    'app_bridge_error_hybridauth_authentication',
					// translators: %s: provider name
                    sprintf( __( 'You do not have set your email in your %s account', 'app-bridge' ), $provider )
                );
            }

            $wp_user = get_user_by( 'email', $user_profile->email );

            if ( ! $wp_user ) {
                return $this->register_new_user( $user_profile );
            }

            return $wp_user;
        } catch ( Exception $e ) {
            return new WP_Error( 'app_bridge_error_hybridauth_authentication', $e->getMessage() );
        }
    }

    /**
     * Register a new user
     *
     * @since 1.0.0
     *
     * @param object $user_profile
     *
     * @return \WP_User|\WP_Error
     */
    protected function register_new_user( $user_profile ) {
        $userdata = array(
            'user_login' => dokan_generate_username( ! empty( $user_profile->displayName ) ? $user_profile->displayName : $user_profile->email ), // phpcs:ignore
            'user_email' => $user_profile->email,
            'user_pass'  => wp_generate_password(),
            'first_name' => ! empty( $user_profile->firstName ) ? $user_profile->firstName : 'name1', // phpcs:ignore
            'last_name'  => ! empty( $user_profile->lastName ) ? $user_profile->lastName : 'name2', // phpcs:ignore
            'role'       => 'customer',
        );

        $user_id = wp_insert_user( $userdata );

        if ( is_wp_error( $user_id ) ) {
            return $user_id;
        }

        return get_userdata( $user_id );
    }

    /**
     * Login a WP User
     *
     * @since 1.0.0
     *
     * @param \WP_User $wp_user
     *
     * @return \WP_User
     */
    protected function login_user( $wp_user ) {
        clean_user_cache( $wp_user->ID );
        wp_clear_auth_cookie();
        wp_set_current_user( $wp_user->ID );

        if ( is_ssl() === true ) {
            wp_set_auth_cookie( $wp_user->ID, true, true );
        } else {
            wp_set_auth_cookie( $wp_user->ID, true, false );
        }

        update_user_caches( $wp_user );

        return $wp_user;
    }
}
