<?php

if (!defined('ABSPATH')) { exit; }

class AIEO_SSO_Migrator {

    
    const PROVIDER_MAP = array(
        'google'    => 'google',
        'facebook'  => 'facebook',
        'twitter'   => 'twitter',
        'linkedin'  => 'linkedin',
        'amazon'    => null,    
        'paypal'    => null,    
        'disqus'    => null,    
        'vkontakte' => null,    
    );

    
    public static function audit() {
        global $wpdb;

        $providers = array();
        foreach (self::PROVIDER_MAP as $legacy => $ours) {
            $row = get_option('wc_social_login_' . $legacy . '_settings', null);
            if (!is_array($row)) { continue; }
            $providers[$legacy] = array(
                'enabled'   => !empty($row['enabled']) && $row['enabled'] === 'yes',
                'has_id'    => !empty($row['id']),
                'has_secret'=> !empty($row['secret']),
                'maps_to'   => $ours,
            );
        }

        $linked_users = (int) $wpdb->get_var(
            "SELECT COUNT(DISTINCT user_id) FROM {$wpdb->usermeta} WHERE meta_key LIKE '\\_wc\\_social\\_login\\_%\\_profile'"
        );

        return array(
            'providers'    => $providers,
            'linked_users' => $linked_users,
            'has_display'  => is_array(get_option('wc_social_login_display', null)),
            'has_text'     => (string) get_option('wc_social_login_text', '') !== '',
        );
    }

    
    public static function run_settings() {
        $existing = get_option(AIEO_SSO_Buttons_Data::OPTION_KEY, array());
        if (!is_array($existing)) { $existing = array(); }
        if (empty($existing['providers']) || !is_array($existing['providers'])) {
            $existing['providers'] = array();
        }
        if (empty($existing['intents']) || !is_array($existing['intents'])) {
            $existing['intents'] = array();
        }

        $updated = 0;
        foreach (self::PROVIDER_MAP as $legacy => $ours) {
            if ($ours === null) { continue; }
            $row = get_option('wc_social_login_' . $legacy . '_settings', null);
            if (!is_array($row)) { continue; }

            $current = isset($existing['providers'][$ours]) && is_array($existing['providers'][$ours])
                ? $existing['providers'][$ours]
                : array();

            
            $patch = array(
                'enabled'       => isset($current['enabled'])       ? (bool) $current['enabled']       : !empty($row['enabled']) && $row['enabled'] === 'yes',
                'client_id'     => isset($current['client_id'])     && $current['client_id']     !== '' ? $current['client_id']     : (string) ($row['id']     ?? ''),
                'client_secret' => isset($current['client_secret']) && $current['client_secret'] !== '' ? $current['client_secret'] : (string) ($row['secret'] ?? ''),
                'button_text'   => isset($current['button_text'])   && $current['button_text']   !== '' ? $current['button_text']   : (string) ($row['login_button_text'] ?? ''),
            );
            $existing['providers'][$ours] = $patch;
            $updated++;
        }

        
        $display = get_option('wc_social_login_display', array());
        if (is_array($display) && !empty($display)) {
            $intents_defaults = array(
                'login'      => true,
                'register'   => true,
                'my_account' => in_array('my_account', $display, true),
                'checkout'   => in_array('checkout', $display, true) || in_array('checkout_notice', $display, true),
                'newsletter' => false, 
            );
            foreach ($intents_defaults as $intent => $val) {
                if (!isset($existing['intents'][$intent])) {
                    $existing['intents'][$intent] = $val;
                }
            }
        }

        
        if (empty($existing['intro_text'])) {
            $existing['intro_text'] = (string) get_option('wc_social_login_text', '');
        }

        
        if (!isset($existing['force_ssl_callback'])) {
            $existing['force_ssl_callback'] = (string) get_option('wc_social_login_force_ssl_callback_url', 'no') === 'yes';
        }

        AIEO_SSO_Buttons_Data::save_settings($existing);
        return array('providers_migrated' => $updated, 'settings' => $existing);
    }

    
    public static function run_users($batch_size = 500, $cursor = 0) {
        global $wpdb;
        $batch_size = max(50, min(5000, (int) $batch_size));
        $cursor     = max(0, (int) $cursor);

        
        $profile_keys = array();
        foreach (self::PROVIDER_MAP as $legacy => $ours) {
            if ($ours === null) { continue; }
            $profile_keys[$legacy] = '_wc_social_login_' . $legacy . '_profile';
        }
        if (empty($profile_keys)) {
            return array('processed' => 0, 'linked' => 0, 'skipped_no_uid' => 0, 'decode_failed' => 0, 'next_cursor' => null, 'done' => true);
        }

        
        
        $placeholders = implode(',', array_fill(0, count($profile_keys), '%s'));
        $params = array_merge(array_values($profile_keys), array($cursor, $batch_size));

        
        $user_ids = $wpdb->get_col($wpdb->prepare(
            "SELECT DISTINCT user_id FROM {$wpdb->usermeta}
              WHERE meta_key IN ($placeholders)
                AND user_id > %d
              ORDER BY user_id ASC LIMIT %d",
            ...$params
        ));
        $user_ids = array_map('intval', (array) $user_ids);

        if (empty($user_ids)) {
            return array('processed' => 0, 'linked' => 0, 'skipped_no_uid' => 0, 'decode_failed' => 0, 'next_cursor' => null, 'done' => true);
        }

        
        $avatar_keys = array();
        foreach (self::PROVIDER_MAP as $legacy => $ours) {
            if ($ours === null) { continue; }
            $avatar_keys[$legacy] = '_wc_social_login_' . $legacy . '_profile_image';
        }
        $all_keys = array_merge(array_values($profile_keys), array_values($avatar_keys));
        $key_placeholders = implode(',', array_fill(0, count($all_keys), '%s'));
        $id_placeholders  = implode(',', array_fill(0, count($user_ids),  '%d'));
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT user_id, meta_key, meta_value FROM {$wpdb->usermeta}
              WHERE user_id IN ($id_placeholders)
                AND meta_key IN ($key_placeholders)",
            ...array_merge($user_ids, $all_keys)
        ), ARRAY_A);

        
        $by_user = array();
        foreach ($rows as $r) {
            $by_user[(int) $r['user_id']][$r['meta_key']] = (string) $r['meta_value'];
        }

        $processed = 0; $linked = 0; $skipped_no_uid = 0; $decode_failed = 0;
        $next_cursor = $cursor;

        foreach ($user_ids as $user_id) {
            $next_cursor = max($next_cursor, (int) $user_id);
            $processed++;

            $user_meta = $by_user[$user_id] ?? array();

            foreach (self::PROVIDER_MAP as $legacy => $ours) {
                if ($ours === null) { continue; }
                $profile_key = $profile_keys[$legacy];
                if (empty($user_meta[$profile_key])) { continue; }

                $profile = self::decode_legacy_profile($user_meta[$profile_key]);
                if ($profile === null) {
                    $decode_failed++;
                    continue;
                }

                $uid = self::extract_field($profile, array('identifier', 'id', 'provider_uid', 'sub'));
                if ($uid === '') {
                    $skipped_no_uid++;
                    continue;
                }
                $email  = self::extract_field($profile, array('email', 'emailVerified'));
                $avatar = '';
                if (!empty($user_meta[$avatar_keys[$legacy]])) {
                    $avatar = (string) $user_meta[$avatar_keys[$legacy]];
                }

                AIEO_SSO_Account_Linker::write_link_meta($user_id, $ours, $uid, $email, $avatar);
                $linked++;
            }
        }

        $done = count($user_ids) < $batch_size;
        return array(
            'processed'      => $processed,
            'linked'         => $linked,
            'skipped_no_uid' => $skipped_no_uid,
            'decode_failed'  => $decode_failed,
            'next_cursor'    => $done ? null : $next_cursor,
            'done'           => $done,
        );
    }

    
    private static function decode_legacy_profile($raw) {
        if (!is_string($raw) || $raw === '') { return null; }

        
        if (preg_match('/^a:\d+:\{/', $raw)) {
            $arr = @unserialize($raw);
            return is_array($arr) ? $arr : null;
        }

        
        
        
        $obj = @unserialize($raw);
        if (is_object($obj) && !($obj instanceof \__PHP_Incomplete_Class)) {
            return $obj;
        }

        
        
        $patched = preg_replace('/O:\d+:"[^"]+":/', 'O:8:"stdClass":', $raw);
        if ($patched === null || $patched === $raw && !is_string($obj)) {
            return null;
        }
        $obj = @unserialize($patched);
        return is_object($obj) ? $obj : (is_array($obj) ? $obj : null);
    }

    
    private static function extract_field($profile, array $fields) {
        foreach ($fields as $f) {
            if (is_object($profile) && isset($profile->$f) && $profile->$f !== '' && $profile->$f !== null) {
                return (string) $profile->$f;
            }
            if (is_array($profile) && isset($profile[$f]) && $profile[$f] !== '' && $profile[$f] !== null) {
                return (string) $profile[$f];
            }
        }
        return '';
    }
}
