<?php

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

class AIEO_SSO_Account_Linker {

    
    public static function find_or_create(string $provider, array $profile) {
        $uid    = (string) ($profile['provider_uid'] ?? '');
        $email  = (string) ($profile['email']        ?? '');
        $first  = (string) ($profile['first_name']   ?? '');
        $last   = (string) ($profile['last_name']    ?? '');
        $avatar = (string) ($profile['avatar']       ?? '');
        if ($uid === '') {
            return new WP_Error('sso_no_provider_uid', __('Provider profile is missing a stable identifier.', 'ai-eshop-optimizer'));
        }

        
        $existing = self::find_by_provider_uid($provider, $uid);
        if ($existing) {
            self::write_link_meta($existing, $provider, $uid, $email, $avatar);
            self::fill_customer_fields_if_empty($existing, $first, $last, $email);
            return $existing;
        }

        
        if ($email !== '' && self::email_link_allowed($email)) {
            $user = get_user_by('email', $email);
            if ($user) {
                self::write_link_meta($user->ID, $provider, $uid, $email, $avatar);
                self::fill_customer_fields_if_empty($user->ID, $first, $last, $email);
                
                do_action('aieo_sso_user_linked_by_email', $user->ID, $provider, $profile);
                return $user->ID;
            }
        }

        
        $created_email = $email !== '' ? $email : sprintf('%s_%s@no-email.invalid', $provider, $uid);
        $created_login = self::pick_unique_login($provider, $first, $last, $email);
        $password      = wp_generate_password(32, true, true);
        $user_id       = wc_create_new_customer($created_email, $created_login, $password);
        if (is_wp_error($user_id)) { return $user_id; }
        $user_id = (int) $user_id;

        self::write_link_meta($user_id, $provider, $uid, $email, $avatar);
        self::fill_customer_fields_if_empty($user_id, $first, $last, $email);
        
        do_action('aieo_sso_user_created', $user_id, $provider, $profile);
        return $user_id;
    }

    
    public static function find_by_provider_uid(string $provider, string $uid) {
        $users = get_users(array(
            'meta_key'   => '_aieo_social_' . sanitize_key($provider) . '_uid',
            'meta_value' => $uid,
            'number'     => 1,
            'fields'     => 'ID',
        ));
        if (!empty($users)) { return (int) $users[0]; }
        return null;
    }

    
    public static function write_link_meta(int $user_id, string $provider, string $uid, string $email, string $avatar) {
        $provider = sanitize_key($provider);
        update_user_meta($user_id, '_aieo_social_' . $provider . '_uid',       $uid);
        if ($email !== '') {
            update_user_meta($user_id, '_aieo_social_' . $provider . '_email', $email);
        }
        if ($avatar !== '') {
            update_user_meta($user_id, '_aieo_social_' . $provider . '_avatar', $avatar);
        }
        update_user_meta($user_id, '_aieo_social_' . $provider . '_linked_at', gmdate('Y-m-d H:i:s'));
    }

    
    public static function unlink(int $user_id, string $provider) {
        $provider = sanitize_key($provider);
        delete_user_meta($user_id, '_aieo_social_' . $provider . '_uid');
        delete_user_meta($user_id, '_aieo_social_' . $provider . '_email');
        delete_user_meta($user_id, '_aieo_social_' . $provider . '_avatar');
        delete_user_meta($user_id, '_aieo_social_' . $provider . '_linked_at');
        do_action('aieo_sso_user_unlinked', $user_id, $provider);
    }

    
    public static function fill_customer_fields_if_empty(int $user_id, string $first, string $last, string $email) {
        $assignments = array(
            'first_name'           => $first,
            'last_name'            => $last,
            'billing_first_name'   => $first,
            'billing_last_name'    => $last,
            'shipping_first_name'  => $first,
            'shipping_last_name'   => $last,
            'billing_email'        => $email,
        );
        foreach ($assignments as $meta_key => $new_val) {
            if ($new_val === '') { continue; }
            $current = (string) get_user_meta($user_id, $meta_key, true);
            if ($current === '') {
                update_user_meta($user_id, $meta_key, $new_val);
            }
        }
    }

    
    private static function email_link_allowed(string $email) {
        $user = get_user_by('email', $email);
        if (!$user) { return true; } 
        $roles = (array) $user->roles;

        $allowed = apply_filters('aieo_sso_find_by_email_allowed_roles', array());
        if (is_array($allowed) && !empty($allowed)) {
            foreach ($roles as $role) {
                if (in_array($role, $allowed, true)) { return true; }
            }
            return false;
        }

        $settings = class_exists('AIEO_SSO_Buttons_Data') ? AIEO_SSO_Buttons_Data::get_settings() : array();
        if (array_key_exists('blocked_roles', $settings) && is_array($settings['blocked_roles'])) {
            $blocked = array_values(array_filter(array_map('sanitize_key', $settings['blocked_roles'])));
        } else {
            $blocked = self::default_blocked_roles();
        }
        $blocked = apply_filters('aieo_sso_find_by_email_blocked_roles', $blocked);

        foreach ($roles as $role) {
            if (in_array($role, (array) $blocked, true)) { return false; }
        }
        return true;
    }

    
    public static function default_blocked_roles() {
        return array(
            'administrator',
            'editor',
            'author',
            'contributor',
            'shop_manager',
            'aioseo_manager',
            'aioseo_editor',
        );
    }

    private static function pick_unique_login(string $provider, string $first, string $last, string $email) {
        $base = '';
        if ($email !== '' && strpos($email, '@') !== false) {
            $base = sanitize_user(strstr($email, '@', true), true);
        }
        if ($base === '') {
            $base = sanitize_user($first . $last, true);
        }
        if ($base === '') {
            $base = $provider . '_' . substr(md5(uniqid('', true)), 0, 8);
        }
        $login = $base;
        $i = 1;
        while (username_exists($login)) {
            $login = $base . $i;
            $i++;
            if ($i > 1000) { $login = $provider . '_' . substr(md5(uniqid('', true)), 0, 12); break; }
        }
        return $login;
    }
}
