<?php

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

class AIEO_DMM_User_FP {

    
    private static $l1 = array();

    
    public static function get($user_id) {
        $user_id = (int) $user_id;
        if (isset(self::$l1[$user_id])) {
            return self::$l1[$user_id];
        }

        if ($user_id <= 0) {
            
            return self::$l1[0] = self::compute_guest();
        }

        global $wpdb;
        $table = $wpdb->prefix . 'aieo_dmm_user_fp';
        if (!self::table_exists($table)) {
            return self::$l1[$user_id] = self::compute_guest();
        }

        
        $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$table} WHERE user_id = %d", $user_id), ARRAY_A);
        $current_key = self::current_version_key();

        if (!$row || !isset($row['fp_version_key']) || $row['fp_version_key'] !== $current_key) {
            $row = self::compute($user_id, $current_key);
        } else {
            $row = self::hydrate_row($row);
        }

        self::$l1[$user_id] = $row;
        return $row;
    }

    
    public static function compute($user_id, $version_key = null) {
        $user_id = (int) $user_id;
        if ($user_id <= 0) {
            return self::compute_guest();
        }
        if ($version_key === null) {
            $version_key = self::current_version_key();
        }

        $user = get_userdata($user_id);
        if (!$user) {
            return self::compute_guest();
        }

        $roles = is_array($user->roles) ? $user->roles : array();
        sort($roles);
        $role_hash = substr(md5(implode(',', $roles)), 0, 12);

        $enabled_roles = array();
        if (class_exists('AIEO_DMM_Settings')) {
            $enabled_roles = (array) AIEO_DMM_Settings::get('enabled_roles', array());
        }

        $enabled_role_column = '';
        foreach ($roles as $r) {
            if (in_array($r, $enabled_roles, true)) {
                
                $clean = strtolower(preg_replace('/[^a-z0-9_]/', '_', $r));
                if ($clean === '') { $clean = 'r'; }
                if (preg_match('/^[0-9]/', $clean)) { $clean = 'r_' . $clean; }
                $enabled_role_column = $clean;
                break;
            }
        }

        list($loyalty_class_ids, $loyalty_sum) = self::compute_loyalty($user_id);

        $data = array(
            'user_id'                => $user_id,
            'role_hash'              => $role_hash,
            'enabled_role_column'    => $enabled_role_column,
            'loyalty_class_ids'      => wp_json_encode($loyalty_class_ids),
            'loyalty_extra_pct_sum'  => (float) $loyalty_sum,
            'personal_extra_pct'     => 0.0,
            'brand_overrides'        => wp_json_encode(new stdClass()),
            'sequence_pct'           => 0.0,
            'sequence_expires_at'    => null,
            'fp_version_key'         => (string) $version_key,
            'computed_at'            => current_time('mysql', true),
        );
        $formats = array('%d', '%s', '%s', '%s', '%f', '%f', '%s', '%f', '%s', '%s', '%s');

        global $wpdb;
        $table = $wpdb->prefix . 'aieo_dmm_user_fp';
        $wpdb->replace($table, $data, $formats);

        return self::hydrate_row($data);
    }

    
    private static function compute_guest() {
        return self::hydrate_row(array(
            'user_id'               => 0,
            'role_hash'             => substr(md5('guest'), 0, 12),
            'enabled_role_column'   => '',
            'loyalty_class_ids'     => '[]',
            'loyalty_extra_pct_sum' => 0.0,
            'personal_extra_pct'    => 0.0,
            'brand_overrides'       => '{}',
            'sequence_pct'          => 0.0,
            'sequence_expires_at'   => null,
            'fp_version_key'        => self::current_version_key(),
            'computed_at'           => current_time('mysql', true),
        ));
    }

    
    public static function on_user_change($user_id) {
        $user_id = (int) $user_id;
        if ($user_id <= 0) { return; }
        self::compute($user_id);
    }

    public static function clear_memo() {
        self::$l1 = array();
    }

    
    
    

    
    private static function compute_loyalty($user_id) {
        global $wpdb;
        $assign = $wpdb->prefix . 'aieo_dmm_loyalty_assignments';
        $defs   = $wpdb->prefix . 'aieo_dmm_loyalty_classes';
        if (!self::table_exists($assign) || !self::table_exists($defs)) {
            return array(array(), 0.0);
        }
        
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT d.id, d.extra_percent
             FROM {$assign} a
             INNER JOIN {$defs} d ON d.id = a.class_id
             WHERE a.user_id = %d AND d.enabled = 1",
            $user_id
        ), ARRAY_A);

        $ids = array();
        $sum = 0.0;
        if (is_array($rows)) {
            foreach ($rows as $r) {
                $ids[] = (int) $r['id'];
                $sum  += (float) $r['extra_percent'];
            }
        }
        return array($ids, $sum);
    }

    
    private static function current_version_key() {
        $domains = array('brands', 'gifts', 'loyalty', 'prices', 'needs', 'shipping');
        $parts = array();
        foreach ($domains as $d) {
            $parts[] = (int) get_option('aieo_dmm_cache_v_' . $d, 1);
        }
        return implode(':', $parts);
    }

    private static function hydrate_row($row) {
        if (!is_array($row)) { return null; }
        $row['user_id']               = (int) ($row['user_id'] ?? 0);
        $row['role_hash']             = (string) ($row['role_hash'] ?? '');
        $row['enabled_role_column']   = (string) ($row['enabled_role_column'] ?? '');
        $row['loyalty_extra_pct_sum'] = (float) ($row['loyalty_extra_pct_sum'] ?? 0);
        $row['personal_extra_pct']    = (float) ($row['personal_extra_pct'] ?? 0);
        $row['sequence_pct']          = (float) ($row['sequence_pct'] ?? 0);
        $row['loyalty_class_ids']     = self::decode_int_list($row['loyalty_class_ids'] ?? '');
        $decoded_overrides = is_array($row['brand_overrides'] ?? null)
            ? $row['brand_overrides']
            : (is_string($row['brand_overrides'] ?? '') ? json_decode((string) $row['brand_overrides'], true) : null);
        $row['brand_overrides'] = is_array($decoded_overrides) ? $decoded_overrides : array();
        return $row;
    }

    private static function decode_int_list($raw) {
        if (is_array($raw)) { return array_map('intval', $raw); }
        if (!is_string($raw) || $raw === '') { return array(); }
        $decoded = json_decode($raw, true);
        return is_array($decoded) ? array_map('intval', $decoded) : array();
    }

    private static function table_exists($table) {
        static $memo = array();
        if (isset($memo[$table])) { return $memo[$table]; }
        global $wpdb;
        $found = $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = %s",
            $table
        ));
        return $memo[$table] = ((int) $found) > 0;
    }
}
