<?php
/**
 * sync-user-profile  (hourly)
 *
 * Pulls per-user contact + demographic fields out of WordPress user records
 * (and usermeta — phone, address, postcode, country, DOB if collected) and
 * pushes them to wpdeploy as canonical profile rows. Watermarked on the
 * latest user_registered/usermeta change since last successful sync.
 */

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

require_once __DIR__ . '/class-sync-base.php';

class AF_Profile_Sync extends AF_Sync_Base {

    protected $endpoint     = 'sync-user-profile';
    protected $cron_hook    = 'auctionforge_sync_user_profile';
    protected $cron_schedule = 'hourly';
    protected $batch_size   = 200;
    protected $health_key   = 'user-profile';

    protected function read_batch() {
        global $wpdb;

        $watermark = get_option('auctionforge_profile_sync_watermark', '2000-01-01 00:00:00');

        // We snapshot users whose registration or any usermeta change is newer
        // than the watermark. usermeta has no timestamp so we fall back to a
        // simpler "all users" walk on first run + incremental on user_registered.
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT ID, user_email, user_registered, display_name
               FROM {$wpdb->users}
              WHERE user_registered >= %s
              ORDER BY user_registered ASC
              LIMIT %d",
            $watermark, $this->batch_size
        ), ARRAY_A);

        if (empty($rows)) return array();

        // Hydrate usermeta for each user (phone, billing_*, etc).
        foreach ($rows as &$r) {
            $uid = (int) $r['ID'];
            $r['first_name']   = get_user_meta($uid, 'first_name', true);
            $r['last_name']    = get_user_meta($uid, 'last_name', true);
            $r['phone']        = self::pick_meta($uid, array('billing_phone', 'phone', 'mobile_phone', 'auctionforge_phone'));
            $r['address_1']    = self::pick_meta($uid, array('billing_address_1', 'billing_address1', 'address_1'));
            $r['address_2']    = self::pick_meta($uid, array('billing_address_2', 'billing_address2', 'address_2'));
            $r['city']         = self::pick_meta($uid, array('billing_city', 'city'));
            $r['region']       = self::pick_meta($uid, array('billing_state', 'state', 'region'));
            $r['postcode']     = self::pick_meta($uid, array('billing_postcode', 'postcode', 'zip'));
            $r['country']      = self::pick_meta($uid, array('billing_country', 'country'));
            $r['dob']          = self::pick_meta($uid, array('dob', 'date_of_birth', 'birthday'));
            $r['gender']       = self::pick_meta($uid, array('gender'));
        }
        unset($r);

        return $rows;
    }

    protected function build_payload($rows) {
        // Normalize PII at write-time so wpdeploy stores clean values.
        foreach ($rows as &$r) {
            $r['user_email'] = strtolower(trim((string) $r['user_email']));
            $r['phone']      = self::normalize_phone($r['phone'], $r['country']);
            $r['postcode']   = strtoupper(preg_replace('/\s+/', '', (string) $r['postcode']));
            $r['country']    = strtoupper(substr((string) $r['country'], 0, 2));
        }
        unset($r);

        return array('records' => $rows);
    }

    protected function mark_synced($rows, $response) {
        if (empty($rows)) return;
        // Watermark is the latest user_registered we've shipped.
        $latest = end($rows);
        if (!empty($latest['user_registered'])) {
            update_option('auctionforge_profile_sync_watermark', $latest['user_registered'], 'no');
        }
    }

    private static function pick_meta($uid, $keys) {
        foreach ($keys as $k) {
            $v = get_user_meta($uid, $k, true);
            if (!empty($v)) return $v;
        }
        return '';
    }

    /**
     * UK-aware phone normalization to E.164. If we can't make sense of it
     * we hand back the original, lightly trimmed.
     */
    private static function normalize_phone($raw, $country = '') {
        $raw = trim((string) $raw);
        if ($raw === '') return '';

        // Strip everything except digits and leading +.
        $digits = preg_replace('/[^\d+]/', '', $raw);

        // Already E.164.
        if (strlen($digits) > 0 && $digits[0] === '+') return $digits;

        $cc = strtoupper(substr((string) $country, 0, 2));
        // UK convention: 07XXXXXXXXX → +447XXXXXXXXX
        if (($cc === 'GB' || $cc === 'UK' || $cc === '') && strlen($digits) === 11 && substr($digits, 0, 2) === '07') {
            return '+44' . substr($digits, 1);
        }
        if (($cc === 'GB' || $cc === 'UK') && strlen($digits) === 10 && substr($digits, 0, 1) === '7') {
            return '+44' . $digits;
        }

        // Fallback — return digits with a leading + so it at least looks
        // like E.164 to downstream consumers.
        return strlen($digits) >= 7 ? '+' . $digits : $raw;
    }
}
