<?php

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

abstract class AIEO_Push_Trigger_CartAbandonment_Base extends AIEO_Push_Trigger_Base {

    
    abstract protected function hours_since_add();

    public function dedup_days() { return 1; }
    public function cap_per_day() { return 2; }
    public function cap_per_week() { return 4; }

    public function produce_candidates($limit = 200) {
        global $wpdb;
        $tbl_e   = $wpdb->prefix . 'aieo_addcart_events';
        $tbl_sub = $wpdb->prefix . 'aieo_push_subscriptions';
        $tbl_p   = $wpdb->posts;
        $limit   = max(1, (int) $limit);
        $hours   = max(1, (int) $this->hours_since_add());
        $window_start = $hours;
        $window_end   = $hours + 4;

        
        
        
        
        
        
        
        
        $subs = $wpdb->get_results(
            "SELECT subscription_id, user_id, session_token
             FROM {$tbl_sub}
             WHERE status = 'active'
             LIMIT 5000",
            ARRAY_A
        );
        if (empty($subs)) { return array(); }

        $subs_by_user  = array();
        $subs_by_token = array();
        foreach ($subs as $s) {
            $uid = (int) $s['user_id'];
            $tok = (string) $s['session_token'];
            $sub_row = array('subscription_id' => (int) $s['subscription_id'], 'user_id' => $uid);
            if ($uid > 0) {
                $subs_by_user[$uid][] = $sub_row;
            } elseif ($tok !== '') {
                $subs_by_token[$tok][] = $sub_row;
            }
        }
        if (empty($subs_by_user) && empty($subs_by_token)) { return array(); }

        
        
        
        $events = array();

        if (!empty($subs_by_user)) {
            $user_ids = array_keys($subs_by_user);
            $in_users = implode(',', array_map('intval', $user_ids));
            $logged_in = $wpdb->get_results($wpdb->prepare(
                "SELECT e.user_id, e.product_id,
                        ROUND(MAX(e.unit_price), 2) AS unit_price,
                        MAX(e.ts_added) AS ts_added
                 FROM {$tbl_e} e
                 WHERE e.order_id = 0
                   AND e.user_id IN ({$in_users})
                   AND e.ts_added <= DATE_SUB(UTC_TIMESTAMP(), INTERVAL %d HOUR)
                   AND e.ts_added >  DATE_SUB(UTC_TIMESTAMP(), INTERVAL %d HOUR)
                 GROUP BY e.user_id, e.product_id
                 ORDER BY ts_added DESC",
                $window_start, $window_end
            ), ARRAY_A);
            foreach ($logged_in as $e) {
                $uid = (int) $e['user_id'];
                $events[] = array(
                    'sub_rows'   => isset($subs_by_user[$uid]) ? $subs_by_user[$uid] : array(),
                    'product_id' => (int) $e['product_id'],
                    'unit_price' => (float) $e['unit_price'],
                    'ts_added'   => (string) $e['ts_added'],
                );
            }
        }

        if (!empty($subs_by_token)) {
            $tokens = array_keys($subs_by_token);
            $token_placeholders = implode(',', array_fill(0, count($tokens), '%s'));
            $args = array_merge($tokens, array($window_start, $window_end));
            $anon = $wpdb->get_results($wpdb->prepare(
                "SELECT e.session_id, e.product_id,
                        ROUND(MAX(e.unit_price), 2) AS unit_price,
                        MAX(e.ts_added) AS ts_added
                 FROM {$tbl_e} e
                 WHERE e.order_id = 0
                   AND e.user_id = 0
                   AND e.session_id IN ({$token_placeholders})
                   AND e.ts_added <= DATE_SUB(UTC_TIMESTAMP(), INTERVAL %d HOUR)
                   AND e.ts_added >  DATE_SUB(UTC_TIMESTAMP(), INTERVAL %d HOUR)
                 GROUP BY e.session_id, e.product_id
                 ORDER BY ts_added DESC",
                $args
            ), ARRAY_A);
            foreach ($anon as $e) {
                $tok = (string) $e['session_id'];
                $events[] = array(
                    'sub_rows'   => isset($subs_by_token[$tok]) ? $subs_by_token[$tok] : array(),
                    'product_id' => (int) $e['product_id'],
                    'unit_price' => (float) $e['unit_price'],
                    'ts_added'   => (string) $e['ts_added'],
                );
            }
        }

        if (empty($events)) { return array(); }

        
        $pids = array_values(array_unique(array_map(
            static function ($e) { return (int) $e['product_id']; },
            $events
        )));
        if (empty($pids)) { return array(); }
        $in_pids = implode(',', $pids);
        $titles = $wpdb->get_results(
            "SELECT ID, post_title FROM {$tbl_p}
             WHERE post_status = 'publish'
               AND post_type IN ('product', 'product_variation')
               AND ID IN ({$in_pids})",
            ARRAY_A
        );
        $title_by_pid = array();
        foreach ($titles as $t) {
            $title_by_pid[(int) $t['ID']] = (string) $t['post_title'];
        }

        
        usort($events, static function ($a, $b) {
            return strcmp($b['ts_added'], $a['ts_added']);
        });

        
        $out = array();
        $seen = array();
        foreach ($events as $ev) {
            $pid = $ev['product_id'];
            if (!isset($title_by_pid[$pid])) { continue; }
            foreach ($ev['sub_rows'] as $sub_row) {
                $key = $sub_row['subscription_id'] . ':' . $pid;
                if (isset($seen[$key])) { continue; }
                $seen[$key] = true;

                $url = (string) get_permalink($pid);
                $out[] = array(
                    'subscription_id'   => $sub_row['subscription_id'],
                    'user_id'           => $sub_row['user_id'],
                    'target_product_id' => $pid,
                    'target_url'        => $url ? $url . '?aieo_resume_cart=' . $pid : home_url('/cart/'),
                    'payload_data'      => array(
                        'product_name' => (string) $title_by_pid[$pid],
                        'unit_price'   => (float)  $ev['unit_price'],
                    ),
                );
                if (count($out) >= $limit) { break 2; }
            }
        }

        return $out;
    }
}
