<?php

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

class AIEO_Exchanger_Feeds {

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

    
    public static function list_all() {
        global $wpdb;
        $rows = $wpdb->get_results('SELECT * FROM ' . self::table() . ' ORDER BY id DESC', ARRAY_A);
        if (!is_array($rows)) { return array(); }
        foreach ($rows as &$r) { self::decode_row($r); }
        return $rows;
    }

    public static function get($id) {
        global $wpdb;
        $row = $wpdb->get_row($wpdb->prepare('SELECT * FROM ' . self::table() . ' WHERE id = %d', (int) $id), ARRAY_A);
        if (!$row) { return null; }
        self::decode_row($row);
        return $row;
    }

    public static function get_by_slug($slug) {
        global $wpdb;
        $row = $wpdb->get_row($wpdb->prepare('SELECT * FROM ' . self::table() . ' WHERE slug = %s', (string) $slug), ARRAY_A);
        if (!$row) { return null; }
        self::decode_row($row);
        return $row;
    }

    public static function get_by_token($token) {
        global $wpdb;
        $row = $wpdb->get_row($wpdb->prepare('SELECT * FROM ' . self::table() . ' WHERE feed_token = %s', (string) $token), ARRAY_A);
        if (!$row) { return null; }
        self::decode_row($row);
        return $row;
    }

    
    public static function save(array $data) {
        global $wpdb;

        $id = isset($data['id']) ? (int) $data['id'] : 0;
        $slug = sanitize_key((string) ($data['slug'] ?? ''));
        if ($slug === '') { return new WP_Error('invalid_slug', __('Slug is required.', 'ai-eshop-optimizer')); }

        
        $clash = (int) $wpdb->get_var($wpdb->prepare(
            'SELECT id FROM ' . self::table() . ' WHERE slug = %s AND id <> %d LIMIT 1',
            $slug, $id
        ));
        if ($clash) { return new WP_Error('duplicate_slug', __('Another feed already uses this slug.', 'ai-eshop-optimizer')); }

        $token = isset($data['feed_token']) ? (string) $data['feed_token'] : '';
        if (!preg_match('/^[a-f0-9]{64}$/', $token)) {
            $token = self::generate_token();
        }

        $row = array(
            'slug'                  => $slug,
            'label'                 => sanitize_text_field((string) ($data['label'] ?? '')),
            'enabled'               => !empty($data['enabled']) ? 1 : 0,
            'schedule_cron'         => self::sanitize_schedule($data['schedule_cron'] ?? ''),
            'feed_token'            => $token,
            'shard_size'            => max(50, min(2000, (int) ($data['shard_size'] ?? 500))),
            'brand_term_ids'        => self::encode_id_list($data['brand_term_ids']        ?? array()),
            'category_term_ids'     => self::encode_id_list($data['category_term_ids']     ?? array()),
            'need_term_ids'         => self::encode_id_list($data['need_term_ids']         ?? array()),
            'product_ids'           => self::encode_id_list($data['product_ids']           ?? array()),
            'excluded_brand_ids'    => self::encode_id_list($data['excluded_brand_ids']    ?? array()),
            'excluded_category_ids' => self::encode_id_list($data['excluded_category_ids'] ?? array()),
            'excluded_need_ids'     => self::encode_id_list($data['excluded_need_ids']     ?? array()),
            'excluded_product_ids'  => self::encode_id_list($data['excluded_product_ids']  ?? array()),
            'rule_operator'         => self::sanitize_operator($data['rule_operator'] ?? 'AND'),
            'date_from'             => self::sanitize_date($data['date_from'] ?? ''),
            'date_to'               => self::sanitize_date($data['date_to']   ?? ''),
            'min_subtotal'          => isset($data['min_subtotal']) ? (float) $data['min_subtotal'] : 0,
            'price_min'             => isset($data['price_min']) && $data['price_min'] !== '' ? (float) $data['price_min'] : null,
            'price_max'             => isset($data['price_max']) && $data['price_max'] !== '' ? (float) $data['price_max'] : null,
            'push_targets'          => self::encode_push_targets($data['push_targets'] ?? array()),
        );

        if ($id > 0) {
            $wpdb->update(self::table(), $row, array('id' => $id));
            return $id;
        }
        $wpdb->insert(self::table(), $row);
        return (int) $wpdb->insert_id;
    }

    public static function delete($id) {
        global $wpdb;
        $wpdb->delete(self::table(), array('id' => (int) $id));
    }

    public static function record_build_result($id, $status, $built_at = null) {
        global $wpdb;
        $wpdb->update(self::table(), array(
            'last_built_at'     => $built_at ?: current_time('mysql', true),
            'last_build_status' => substr((string) $status, 0, 40),
        ), array('id' => (int) $id));
    }

    public static function rotate_token($id) {
        global $wpdb;
        $token = self::generate_token();
        $wpdb->update(self::table(), array('feed_token' => $token), array('id' => (int) $id));
        return $token;
    }

    
    public static function resolve_product_tokens($raw) {
        $raw = (string) $raw;
        if ($raw === '') { return array(); }
        $parts = preg_split('/[\s,]+/', $raw, -1, PREG_SPLIT_NO_EMPTY);
        $ids = array();
        global $wpdb;
        foreach ($parts as $token) {
            $token = trim((string) $token);
            if ($token === '') { continue; }

            if (ctype_digit($token)) {
                $pid = (int) $token;
                $post = get_post($pid);
                if ($post && in_array($post->post_type, array('product', 'product_variation'), true)) {
                    if ($post->post_type === 'product_variation') { $pid = (int) $post->post_parent; }
                    $ids[$pid] = true; continue;
                }
            }

            
            if (function_exists('wc_get_product_id_by_sku')) {
                $pid = (int) wc_get_product_id_by_sku($token);
                if ($pid > 0) {
                    $post = get_post($pid);
                    if ($post && $post->post_type === 'product_variation') { $pid = (int) $post->post_parent; }
                    if ($pid > 0) { $ids[$pid] = true; continue; }
                }
            }

            
            $pid = (int) $wpdb->get_var($wpdb->prepare(
                "SELECT post_id FROM {$wpdb->postmeta}
                 WHERE meta_key = '_global_unique_id' AND meta_value = %s LIMIT 1",
                $token
            ));
            if ($pid > 0) {
                $post = get_post($pid);
                if ($post && $post->post_type === 'product_variation') { $pid = (int) $post->post_parent; }
                if ($pid > 0) { $ids[$pid] = true; }
            }
        }
        return array_keys($ids);
    }

    

    private static function decode_row(array &$row) {
        foreach (array(
            'brand_term_ids', 'category_term_ids', 'need_term_ids', 'product_ids',
            'excluded_brand_ids', 'excluded_category_ids', 'excluded_need_ids', 'excluded_product_ids',
        ) as $k) {
            $v = $row[$k] ?? '';
            $row[$k] = $v ? (array_values(array_map('intval', (array) json_decode((string) $v, true))) ?: array()) : array();
        }
        $row['push_targets'] = $row['push_targets'] ? (array) json_decode((string) $row['push_targets'], true) : array();
        $row['enabled']       = (int) ($row['enabled'] ?? 0);
        $row['shard_size']    = (int) ($row['shard_size'] ?? 500);
        $row['min_subtotal']  = (float) ($row['min_subtotal'] ?? 0);
    }

    private static function encode_id_list($input) {
        if (!is_array($input)) { return wp_json_encode(array()); }
        $clean = array();
        foreach ($input as $v) {
            $v = (int) $v;
            if ($v > 0) { $clean[$v] = true; }
        }
        return wp_json_encode(array_keys($clean));
    }

    private static function encode_push_targets($input) {
        if (!is_array($input)) { return wp_json_encode(array()); }
        $clean = array();
        foreach ($input as $row) {
            if (!is_array($row)) { continue; }
            $url = isset($row['url']) ? esc_url_raw((string) $row['url']) : '';
            $sec = isset($row['secret']) ? sanitize_text_field((string) $row['secret']) : '';
            if ($url === '' || $sec === '') { continue; }
            $clean[] = array('url' => $url, 'secret' => $sec);
        }
        return wp_json_encode($clean);
    }

    private static function sanitize_operator($op) {
        $op = strtoupper(trim((string) $op));
        return $op === 'OR' ? 'OR' : 'AND';
    }

    private static function sanitize_date($d) {
        $d = trim((string) $d);
        return preg_match('/^\d{4}-\d{2}-\d{2}$/', $d) ? $d : null;
    }

    private static function sanitize_schedule($s) {
        $s = sanitize_key((string) $s);
        $allowed = array('', 'hourly', 'twicedaily', 'daily', 'weekly');
        return in_array($s, $allowed, true) ? $s : '';
    }

    public static function generate_token() {
        return bin2hex(random_bytes(32));
    }

    
    public static function manifest_url(array $feed) {
        return rest_url('aieo/v1/exchanger/' . rawurlencode((string) $feed['slug']) . '/manifest');
    }

    
    public static function storage_path(array $feed) {
        $upload = wp_upload_dir();
        $path = trailingslashit((string) ($upload['basedir'] ?? '')) . 'aieo-dmm/exchanger/' . sanitize_key((string) $feed['slug']);
        if (!file_exists($path)) {
            wp_mkdir_p($path);
            
            @file_put_contents($path . '/index.html', '');
        }
        return $path;
    }
}
