<?php
/**
 * Optional Facebook Login for customer accounts.
 * The provider subject is the durable identity key; email may be unavailable.
 */
if ( ! defined( 'ABSPATH' ) ) { exit; }

class YATOON_Facebook_Identity {
    const STATE_TTL = 10 * MINUTE_IN_SECONDS;

    public static function init() {
        add_action( 'admin_post_nopriv_yatoon_facebook_identity_start', array( __CLASS__, 'start' ) );
        add_action( 'admin_post_yatoon_facebook_identity_start', array( __CLASS__, 'start' ) );
        add_action( 'admin_post_nopriv_yatoon_facebook_identity_callback', array( __CLASS__, 'callback' ) );
        add_action( 'admin_post_yatoon_facebook_identity_callback', array( __CLASS__, 'callback' ) );
        add_action( 'yatoon_booking_created', array( __CLASS__, 'reconcile_customer_link' ), 122 );
    }

    public static function callback_url() {
        return admin_url( 'admin-post.php?action=yatoon_facebook_identity_callback' );
    }

    private static function app_id() { return trim( (string) get_option( 'yatoon_facebook_app_id', '' ) ); }
    private static function app_secret() { return class_exists( 'YATOON_Crypto' ) ? trim( (string) YATOON_Crypto::get_option( 'yatoon_facebook_app_secret', '' ) ) : ''; }

    public static function ready() { return self::app_id() && self::app_secret(); }
    public static function enabled() {
        return class_exists( 'YATOON_Customer_Portal' ) && '1' === (string) get_option( 'yatoon_facebook_identity_enabled', '0' ) && self::ready();
    }

    public static function start_url( $return_url ) {
        if ( ! self::enabled() ) { return ''; }
        return add_query_arg( array(
            'action' => 'yatoon_facebook_identity_start',
            'return_url' => rawurlencode( self::safe_return_url( $return_url ) ),
        ), admin_url( 'admin-post.php' ) );
    }

    public static function button_icon() {
        return '<span class="sbs-facebook-signin-mark" aria-hidden="true"><svg width="19" height="19" style="display:block;width:19px!important;height:19px!important;max-width:19px!important;max-height:19px!important" viewBox="0 0 24 24" focusable="false"><circle cx="12" cy="12" r="12" fill="#1877F2"/><path fill="#fff" d="M13.55 21v-8.2h2.75l.41-3.2h-3.16V7.56c0-.93.26-1.56 1.59-1.56h1.69V3.14A22.8 22.8 0 0 0 14.37 3c-2.44 0-4.11 1.49-4.11 4.21V9.6H7.5v3.2h2.76V21h3.29Z"/></svg></span>';
    }

    public static function save_settings_from_request() {
        update_option( 'yatoon_facebook_identity_enabled', isset( $_POST['yatoon_facebook_identity_enabled'] ) ? '1' : '0', false );
        update_option( 'yatoon_facebook_app_id', sanitize_text_field( wp_unslash( $_POST['yatoon_facebook_app_id'] ?? '' ) ), false );
        $secret = trim( (string) wp_unslash( $_POST['yatoon_facebook_app_secret'] ?? '' ) );
        if ( $secret && class_exists( 'YATOON_Crypto' ) ) { YATOON_Crypto::update_option( 'yatoon_facebook_app_secret', $secret ); }
    }

    public static function render_settings_rows() {
        ?>
        <tr><th><?php esc_html_e( 'Facebook Login', 'yatoon-booking-system' ); ?></th><td><label><input type="checkbox" name="yatoon_facebook_identity_enabled" value="1" <?php checked( get_option( 'yatoon_facebook_identity_enabled', '0' ), '1' ); ?>> <?php esc_html_e( 'Allow customers to sign in with Facebook', 'yatoon-booking-system' ); ?></label><p class="description"><?php esc_html_e( 'Facebook appears only after the App ID and App Secret are saved. Facebook may not return an email; customers can then securely connect existing appointments with an email or text-message code.', 'yatoon-booking-system' ); ?></p>
        <details class="yatoon-identity-guide" <?php echo self::ready() ? '' : 'open'; ?>><summary><?php esc_html_e( 'Facebook setup guide — create the app and register the callback', 'yatoon-booking-system' ); ?></summary><div class="yatoon-identity-guide-body">
        <p class="yatoon-identity-tip"><?php esc_html_e( 'Facebook Login does not charge a per-login fee. Meta may require business verification, app review, a privacy-policy URL, and a data-deletion URL before the app can be available to the public.', 'yatoon-booking-system' ); ?></p>
        <div class="yatoon-identity-guide-actions"><a class="button button-primary" href="https://developers.facebook.com/apps/" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Open Meta Apps', 'yatoon-booking-system' ); ?> ↗</a><a class="button" href="https://developers.facebook.com/docs/facebook-login/web/" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Official Facebook Login instructions', 'yatoon-booking-system' ); ?> ↗</a></div>
        <ol><li><?php esc_html_e( 'Create a Meta developer app for consumer use and add the Facebook Login product.', 'yatoon-booking-system' ); ?></li><li><?php esc_html_e( 'In Facebook Login settings, add the exact Valid OAuth Redirect URI shown below. Keep Client OAuth Login and Web OAuth Login enabled.', 'yatoon-booking-system' ); ?></li><li><?php esc_html_e( 'Complete the app domain, privacy policy, data deletion, and contact details required by Meta. While the app is in Development mode, only app roles and test users can sign in.', 'yatoon-booking-system' ); ?></li><li><?php esc_html_e( 'Copy the App ID and App Secret into the fields below, enable Facebook Login, save changes, and test before switching the Meta app to Live.', 'yatoon-booking-system' ); ?></li></ol>
        <div class="yatoon-identity-copy"><input type="text" readonly value="<?php echo esc_attr( self::callback_url() ); ?>" aria-label="<?php esc_attr_e( 'Facebook valid OAuth redirect URI', 'yatoon-booking-system' ); ?>"><button type="button" class="button yatoon-copy-identity-value"><?php esc_html_e( 'Copy redirect URI', 'yatoon-booking-system' ); ?></button></div>
        </div></details></td></tr>
        <tr><th><?php esc_html_e( 'Facebook App ID', 'yatoon-booking-system' ); ?></th><td><input class="regular-text" name="yatoon_facebook_app_id" value="<?php echo esc_attr( self::app_id() ); ?>"></td></tr>
        <tr><th><?php esc_html_e( 'Facebook App Secret', 'yatoon-booking-system' ); ?></th><td><input class="regular-text" type="password" name="yatoon_facebook_app_secret" value="" autocomplete="new-password"><p class="description"><?php esc_html_e( 'Leave blank to keep the saved encrypted secret.', 'yatoon-booking-system' ); ?></p></td></tr>
        <tr><th><?php esc_html_e( 'Valid OAuth Redirect URI', 'yatoon-booking-system' ); ?></th><td><code><?php echo esc_html( self::callback_url() ); ?></code></td></tr>
        <?php
    }

    public static function start() {
        if ( ! self::enabled() ) { wp_die( esc_html__( 'Facebook Login is not configured.', 'yatoon-booking-system' ), 400 ); }
        $state = wp_generate_password( 48, false, false );
        $return_url = self::safe_return_url( wp_unslash( $_GET['return_url'] ?? home_url( '/' ) ) );
        set_transient( 'yatoon_facebook_state_' . hash( 'sha256', $state ), array( 'return_url' => $return_url, 'fingerprint' => self::fingerprint() ), self::STATE_TTL );
        setcookie( 'yatoon_facebook_state', hash_hmac( 'sha256', $state, wp_salt( 'nonce' ) ), array(
            'expires' => time() + self::STATE_TTL, 'path' => COOKIEPATH ? COOKIEPATH : '/', 'domain' => COOKIE_DOMAIN ? COOKIE_DOMAIN : '',
            'secure' => is_ssl(), 'httponly' => true, 'samesite' => 'Lax',
        ) );
        $url = add_query_arg( array(
            'client_id' => self::app_id(), 'redirect_uri' => self::callback_url(), 'response_type' => 'code',
            'scope' => 'email,public_profile', 'state' => $state,
        ), 'https://www.facebook.com/dialog/oauth' );
        wp_redirect( $url ); // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect -- fixed Meta OAuth endpoint.
        exit;
    }

    public static function callback() {
        $state = sanitize_text_field( wp_unslash( $_GET['state'] ?? '' ) );
        $key = 'yatoon_facebook_state_' . hash( 'sha256', $state );
        $pending = $state ? get_transient( $key ) : false;
        delete_transient( $key );
        $cookie = sanitize_text_field( wp_unslash( $_COOKIE['yatoon_facebook_state'] ?? '' ) );
        setcookie( 'yatoon_facebook_state', '', array( 'expires' => time() - HOUR_IN_SECONDS, 'path' => COOKIEPATH ? COOKIEPATH : '/', 'domain' => COOKIE_DOMAIN ? COOKIE_DOMAIN : '', 'secure' => is_ssl(), 'httponly' => true, 'samesite' => 'Lax' ) );
        $expected = $state ? hash_hmac( 'sha256', $state, wp_salt( 'nonce' ) ) : '';
        if ( ! is_array( $pending ) || ! $cookie || ! hash_equals( $expected, $cookie ) || ! hash_equals( (string) ( $pending['fingerprint'] ?? '' ), self::fingerprint() ) ) { self::redirect_error( home_url( '/' ), 'invalid_state' ); }
        $return_url = self::safe_return_url( $pending['return_url'] ?? home_url( '/' ) );
        if ( isset( $_GET['error'] ) ) { self::redirect_error( $return_url, 'access_denied' ); }
        $token_response = wp_remote_post( 'https://graph.facebook.com/oauth/access_token', array( 'timeout' => 15, 'body' => array(
            'client_id' => self::app_id(), 'client_secret' => self::app_secret(), 'redirect_uri' => self::callback_url(),
            'code' => sanitize_text_field( wp_unslash( $_GET['code'] ?? '' ) ),
        ) ) );
        if ( is_wp_error( $token_response ) || 200 !== wp_remote_retrieve_response_code( $token_response ) ) { self::redirect_error( $return_url, 'token_exchange' ); }
        $token_body = json_decode( wp_remote_retrieve_body( $token_response ), true );
        $access_token = sanitize_text_field( $token_body['access_token'] ?? '' );
        if ( ! $access_token ) { self::redirect_error( $return_url, 'token_exchange' ); }
        $profile_response = wp_remote_get( add_query_arg( 'fields', 'id,name,email', 'https://graph.facebook.com/me' ), array( 'timeout' => 15, 'headers' => array( 'Authorization' => 'Bearer ' . $access_token ) ) );
        $profile = ! is_wp_error( $profile_response ) && 200 === wp_remote_retrieve_response_code( $profile_response ) ? json_decode( wp_remote_retrieve_body( $profile_response ), true ) : null;
        $subject = sanitize_text_field( $profile['id'] ?? '' );
        if ( ! is_array( $profile ) || ! $subject ) { self::redirect_error( $return_url, 'invalid_profile' ); }
        $claims = array( 'sub' => $subject, 'email' => sanitize_email( $profile['email'] ?? '' ), 'name' => sanitize_text_field( $profile['name'] ?? '' ) );
        $portal = class_exists( 'YATOON_Customer_Portal' ) ? YATOON_Customer_Portal::get_instance() : null;
        $customer = $portal ? $portal->login_from_facebook( $claims ) : new WP_Error( 'portal_unavailable' );
        if ( is_wp_error( $customer ) ) { self::redirect_error( $return_url, $customer->get_error_code() ); }
        self::remember_link( absint( $customer['local_client_id'] ?? 0 ), $claims, sanitize_text_field( $customer['square_id'] ?? '' ) );
        $handoff = $portal->create_login_handoff( $customer );
        $redirect_args = array( 'yatoon_facebook_login' => 'success' );
        if ( $handoff ) { $redirect_args['yatoon_customer_handoff'] = rawurlencode( $handoff ); }
        wp_safe_redirect( add_query_arg( $redirect_args, $return_url ) );
        exit;
    }

    private static function remember_link( $account_id, array $claims, $external_id = '' ) {
        global $wpdb;
        $table = $wpdb->prefix . 'yatoon_identity_links';
        $id = $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$table} WHERE account_type='customer' AND provider='facebook' AND provider_subject=%s LIMIT 1", $claims['sub'] ) );
        $data = array( 'account_id' => absint( $account_id ), 'verified_email' => sanitize_email( $claims['email'] ?? '' ), 'external_account_id' => sanitize_text_field( $external_id ), 'last_login_at' => current_time( 'mysql', true ) );
        if ( $id ) { $wpdb->update( $table, $data, array( 'id' => absint( $id ) ), array( '%d', '%s', '%s', '%s' ), array( '%d' ) ); }
        else { $wpdb->insert( $table, array_merge( $data, array( 'account_type' => 'customer', 'provider' => 'facebook', 'provider_subject' => $claims['sub'], 'created_at' => current_time( 'mysql', true ) ) ) ); }
    }

    public static function reconcile_customer_link( $booking ) {
        $portal = class_exists( 'YATOON_Customer_Portal' ) ? YATOON_Customer_Portal::get_instance() : null;
        $customer = $portal ? (array) $portal->current_customer() : array();
        if ( 'facebook' !== ( $customer['identity_provider'] ?? '' ) || empty( $customer['identity_sub'] ) ) { return; }
        $email = sanitize_email( $booking['customer_email'] ?? $customer['email'] ?? '' );
        if ( ! $email ) { return; }
        global $wpdb;
        $client_id = (int) $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$wpdb->prefix}yatoon_clients WHERE LOWER(customer_email)=LOWER(%s) ORDER BY id DESC LIMIT 1", $email ) );
        if ( $client_id ) { $wpdb->update( $wpdb->prefix . 'yatoon_identity_links', array( 'account_id' => $client_id, 'verified_email' => $email ), array( 'account_type' => 'customer', 'provider' => 'facebook', 'provider_subject' => sanitize_text_field( $customer['identity_sub'] ) ) ); }
    }

    private static function safe_return_url( $url ) {
        $fallback = home_url( '/' );
        $url = wp_validate_redirect( esc_url_raw( rawurldecode( (string) $url ) ), $fallback );
        return 0 === strpos( $url, home_url() ) ? $url : $fallback;
    }
    private static function fingerprint() {
        $ua = substr( sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ?? '' ) ), 0, 255 );
        return hash_hmac( 'sha256', $ua, wp_salt( 'nonce' ) );
    }
    private static function redirect_error( $return_url, $code ) {
        wp_safe_redirect( add_query_arg( 'yatoon_identity_error', sanitize_key( $code ), self::safe_return_url( $return_url ) ) );
        exit;
    }
}
