<?php

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

class AIEO_DMM_User_Behavior_Metrics {

    const CACHE_GROUP = 'aieo_dmm';
    const CACHE_TTL   = HOUR_IN_SECONDS;

    public static function table() {
        global $wpdb;
        return $wpdb->prefix . 'aieo_dmm_user_behavior_metrics';
    }

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

        $cache_key = 'aieo_ubm:' . $user_id;
        $cached = wp_cache_get($cache_key, self::CACHE_GROUP);
        if (is_array($cached)) { return $cached; }

        global $wpdb;
        $row = $wpdb->get_row($wpdb->prepare(
            'SELECT * FROM ' . self::table() . ' WHERE user_id = %d LIMIT 1',
            $user_id
        ), ARRAY_A);
        if (!is_array($row)) { $row = self::defaults($user_id); }
        else {
            $row['user_id']             = (int)   $row['user_id'];
            $row['total_orders']        = (int)   $row['total_orders'];
            $row['total_cancellations'] = (int)   $row['total_cancellations'];
            $row['cancellation_rate']   = (float) $row['cancellation_rate'];
            $row['risk_band']           = (int)   $row['risk_band'];
        }
        wp_cache_set($cache_key, $row, self::CACHE_GROUP, self::CACHE_TTL);
        return $row;
    }

    
    public static function risk_band($user_id) {
        $row = self::get($user_id);
        $band = (int) $row['risk_band'];
        return (int) apply_filters('aieo_dmm_user_risk_band', $band, $user_id, $row);
    }

    
    public static function compute_band($cancellation_rate, $total_orders) {
        $thresholds = (array) apply_filters('aieo_dmm_user_risk_thresholds', array(
            'min_orders'    => 3,        
            'elevated_rate' => 0.05,     
            'high_rate'     => 0.15,     
        ));
        $min_orders    = max(1, (int) ($thresholds['min_orders']    ?? 3));
        $elevated_rate = (float) ($thresholds['elevated_rate'] ?? 0.05);
        $high_rate     = (float) ($thresholds['high_rate']     ?? 0.15);

        if ((int) $total_orders < $min_orders) { return 0; }
        if ($cancellation_rate >= $high_rate)     { return 2; }
        if ($cancellation_rate >= $elevated_rate) { return 1; }
        return 0;
    }

    public static function recompute($user_id) {
        $user_id = (int) $user_id;
        if ($user_id <= 0) { return; }
        global $wpdb;

        $oc = $wpdb->prefix . 'aieo_dmm_order_cancellations';

        
        
        
        
        
        
        
        
        
        
        
        
        
        $weights = (array) apply_filters('aieo_dmm_ubm_kind_weights', array(1 => 0.7, 2 => 1.0, 3 => 1.5));
        $w_returned = (float) ($weights[1] ?? 0.7);
        $w_kept     = (float) ($weights[2] ?? 1.0);
        $w_refused  = (float) ($weights[3] ?? 1.5);

        $total_cancellations = (int) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(*) FROM {$oc} WHERE user_id = %d AND event_kind > 0",
            $user_id
        ));
        $weighted_score = (float) $wpdb->get_var($wpdb->prepare(
            "SELECT SUM(CASE event_kind WHEN 1 THEN %f WHEN 2 THEN %f WHEN 3 THEN %f ELSE 0 END)
               FROM {$oc} WHERE user_id = %d AND event_kind > 0",
            $w_returned, $w_kept, $w_refused, $user_id
        ));
        $last_cancelled_at = $wpdb->get_var($wpdb->prepare(
            "SELECT MAX(cancelled_at) FROM {$oc} WHERE user_id = %d AND event_kind > 0",
            $user_id
        ));
        $top_reason_slug = $wpdb->get_var($wpdb->prepare(
            "SELECT reason_slug FROM {$oc}
              WHERE user_id = %d AND event_kind > 0
              GROUP BY reason_slug
              ORDER BY COUNT(*) DESC
              LIMIT 1",
            $user_id
        ));

        
        $total_orders = self::count_user_orders($user_id);

        
        
        $cancellation_rate = $total_orders > 0
            ? round((float) $weighted_score / (float) $total_orders, 4)
            : 0.0;
        $risk_band = self::compute_band($cancellation_rate, $total_orders);

        $row = array(
            'user_id'             => $user_id,
            'total_orders'        => $total_orders,
            'total_cancellations' => $total_cancellations,
            'cancellation_rate'   => $cancellation_rate,
            'last_cancelled_at'   => $last_cancelled_at ?: null,
            'top_reason_slug'     => $top_reason_slug ?: null,
            'risk_band'           => $risk_band,
            'computed_at'         => current_time('mysql', true),
        );

        $tbl = self::table();
        $exists = (int) $wpdb->get_var($wpdb->prepare(
            "SELECT 1 FROM {$tbl} WHERE user_id = %d",
            $user_id
        ));
        if ($exists) {
            $wpdb->update($tbl, $row, array('user_id' => $user_id));
        } else {
            $wpdb->insert($tbl, $row);
        }
        wp_cache_delete('aieo_ubm:' . $user_id, self::CACHE_GROUP);
        return $row;
    }

    
    private static function count_user_orders($user_id) {
        global $wpdb;
        $hpos = $wpdb->prefix . 'wc_orders';
        if ($wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $hpos)) === $hpos) {
            return (int) $wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM {$hpos} WHERE customer_id = %d",
                $user_id
            ));
        }
        return (int) $wpdb->get_var($wpdb->prepare(
            "SELECT COUNT(DISTINCT pm.post_id)
               FROM {$wpdb->postmeta} pm
               JOIN {$wpdb->posts} p ON p.ID = pm.post_id AND p.post_type = 'shop_order'
              WHERE pm.meta_key = '_customer_user' AND pm.meta_value = %d",
            $user_id
        ));
    }

    public static function defaults($user_id) {
        return array(
            'user_id'             => (int) $user_id,
            'total_orders'        => 0,
            'total_cancellations' => 0,
            'cancellation_rate'   => 0.0,
            'last_cancelled_at'   => null,
            'top_reason_slug'     => null,
            'risk_band'           => 0,
            'computed_at'         => null,
        );
    }

    
    public static function backfill_all() {
        global $wpdb;
        $oc = $wpdb->prefix . 'aieo_dmm_order_cancellations';
        $lr = $wpdb->prefix . 'aieo_dmm_order_line_refunds';

        $user_ids = array();
        $rows = $wpdb->get_col("SELECT DISTINCT user_id FROM {$oc} WHERE user_id > 0");
        foreach ((array) $rows as $uid) {
            $uid = (int) $uid;
            if ($uid > 0) { $user_ids[$uid] = true; }
        }
        $rows = $wpdb->get_col("SELECT DISTINCT user_id FROM {$lr} WHERE user_id > 0");
        foreach ((array) $rows as $uid) {
            $uid = (int) $uid;
            if ($uid > 0) { $user_ids[$uid] = true; }
        }

        $count = 0;
        foreach (array_keys($user_ids) as $uid) {
            self::recompute($uid);
            $count++;
        }
        return $count;
    }

    
    public static function recompute_stale($stale_hours = 24, $limit = 200) {
        global $wpdb;
        $tbl = self::table();
        $ids = $wpdb->get_col($wpdb->prepare(
            "SELECT user_id FROM {$tbl}
              WHERE computed_at < DATE_SUB(NOW(), INTERVAL %d HOUR)
              ORDER BY computed_at ASC
              LIMIT %d",
            (int) $stale_hours, (int) $limit
        ));
        $count = 0;
        foreach ((array) $ids as $uid) {
            self::recompute((int) $uid);
            $count++;
        }
        return $count;
    }

    public static function bootstrap() {
        static $done = false;
        if ($done) { return; }
        $done = true;
        add_action('aieo_dmm_recompute_behavior_metrics_for_user',
            array(__CLASS__, 'recompute'), 10, 1);
    }
}
