<?php
/**
 * svc-algorithm.php — الگوریتم جامع ارائه خدمات HVAC (Spec A)
 * دروازه ورود · مسیرهای تفکیک‌شده · تحلیل مشاوره · اولویت · تأیید هزینه
 */
if ( ! defined( 'ABSPATH' ) ) exit;

class Svc_Algorithm {

    /** ۷ مسیر اصلی سند + مسیرهای تکمیلی */
    public static function entry_routes(): array {
        return [
            'phone_consult'      => [ 'icon' => '📞', 'title' => 'مشاوره فنی تلفنی',     'group' => 'consult' ],
            'online_consult'     => [ 'icon' => '💻', 'title' => 'مشاوره فنی آنلاین',    'group' => 'consult' ],
            'repair'             => [ 'icon' => '🛠', 'title' => 'تعمیر و سرویس',        'group' => 'repair' ],
            'pm'                 => [ 'icon' => '📅', 'title' => 'نگهداری دوره‌ای PM',   'group' => 'pm' ],
            'parts_supply'       => [ 'icon' => '🔩', 'title' => 'تأمین قطعات',          'group' => 'parts' ],
            'equipment_purchase' => [ 'icon' => '🏭', 'title' => 'خرید تجهیزات',         'group' => 'equipment' ],
            'site_visit'         => [ 'icon' => '🔍', 'title' => 'بازدید کارشناس',       'group' => 'visit' ],
            'contract_support'   => [ 'icon' => '📋', 'title' => 'پشتیبانی قراردادی',    'group' => 'contract' ],
            'troubleshooting'    => [ 'icon' => '⚡', 'title' => 'عیب‌یابی',             'group' => 'consult' ],
            'overhaul'           => [ 'icon' => '⚙️', 'title' => 'اورهال',               'group' => 'repair' ],
            'install'            => [ 'icon' => '🏗', 'title' => 'نصب و راه‌اندازی',      'group' => 'equipment' ],
        ];
    }

    /** فیلدهای wizard به تفکیک مسیر */
    public static function wizard_fields( string $service_type ): array {
        $common = [
            [ 'key' => 'name',  'label' => 'نام *', 'type' => 'text', 'required' => true ],
            [ 'key' => 'phone', 'label' => 'موبایل *', 'type' => 'tel', 'required' => true, 'dir' => 'ltr' ],
            [ 'key' => 'site_label', 'label' => 'موضع / آدرس *', 'type' => 'text', 'required' => true ],
        ];
        $device = [
            [ 'key' => 'device_type', 'label' => 'نوع دستگاه', 'type' => 'select', 'options' => [ 'چیلر', 'سردخانه', 'ویترین', 'هواساز', 'داکت اسپلیت', 'روفتاپ', 'سایر' ] ],
            [ 'key' => 'brand', 'label' => 'برند', 'type' => 'text' ],
            [ 'key' => 'model', 'label' => 'مدل', 'type' => 'text' ],
            [ 'key' => 'capacity', 'label' => 'ظرفیت', 'type' => 'text' ],
            [ 'key' => 'refrigerant', 'label' => 'نوع مبرد', 'type' => 'text' ],
            [ 'key' => 'year_built', 'label' => 'سال ساخت', 'type' => 'number' ],
            [ 'key' => 'install_location', 'label' => 'محل نصب', 'type' => 'text' ],
        ];

        $phone_consult = array_merge( $common, $device, [
            [ 'key' => 'error_code', 'label' => 'کد خطا (Error Code)', 'type' => 'text' ],
            [ 'key' => 'complaint_text', 'label' => 'شرح مشکل *', 'type' => 'textarea', 'required' => true ],
            [ 'key' => 'ambient_temp', 'label' => 'دمای محیط (°C)', 'type' => 'number' ],
            [ 'key' => 'suction_pressure', 'label' => 'فشار ساکشن', 'type' => 'text' ],
            [ 'key' => 'discharge_pressure', 'label' => 'فشار دیسشارژ', 'type' => 'text' ],
        ] );
        $repair = array_merge( $common, $device, [
            [ 'key' => 'priority', 'label' => 'اولویت *', 'type' => 'select', 'required' => true, 'options' => [ 'normal' => 'عادی', 'urgent' => 'اضطراری' ] ],
            [ 'key' => 'error_code', 'label' => 'کد خطا', 'type' => 'text' ],
            [ 'key' => 'complaint_text', 'label' => 'شرح مشکل *', 'type' => 'textarea', 'required' => true ],
        ] );
        $equipment_purchase = array_merge( $common, [
            [ 'key' => 'project_city', 'label' => 'شهر پروژه *', 'type' => 'text', 'required' => true ],
            [ 'key' => 'application', 'label' => 'کاربرد', 'type' => 'select', 'options' => [ 'سردخانه', 'چیلر', 'هواساز', 'اتاق تمیز', 'صنعتی', 'بیمارستانی', 'غذایی' ] ],
            [ 'key' => 'required_capacity', 'label' => 'ظرفیت مورد نیاز', 'type' => 'text' ],
            [ 'key' => 'budget_range', 'label' => 'بودجه تقریبی (تومان)', 'type' => 'text' ],
            [ 'key' => 'space_constraints', 'label' => 'محدودیت فضا / برق', 'type' => 'textarea' ],
            [ 'key' => 'complaint_text', 'label' => 'توضیحات پروژه', 'type' => 'textarea' ],
        ] );

        $by_type = [
            'phone_consult'      => $phone_consult,
            'online_consult'     => $phone_consult,
            'troubleshooting'    => $phone_consult,
            'repair'             => $repair,
            'overhaul'           => $repair,
            'pm'                 => array_merge( $common, $device, [
                [ 'key' => 'operating_hours', 'label' => 'ساعت کارکرد دستگاه', 'type' => 'number' ],
                [ 'key' => 'pm_plan', 'label' => 'بازه PM *', 'type' => 'select', 'required' => true, 'options' => [
                    'monthly' => 'ماهانه', 'quarterly' => 'سه‌ماهه', 'semi_annual' => 'شش‌ماهه', 'annual' => 'سالانه',
                ] ],
            ] ),
            'parts_supply'       => array_merge( $common, [
                [ 'key' => 'device_type', 'label' => 'نوع دستگاه', 'type' => 'text' ],
                [ 'key' => 'brand', 'label' => 'برند', 'type' => 'text' ],
                [ 'key' => 'model', 'label' => 'مدل', 'type' => 'text' ],
                [ 'key' => 'part_number', 'label' => 'شماره فنی قطعه (Part No)', 'type' => 'text' ],
                [ 'key' => 'part_qty', 'label' => 'تعداد', 'type' => 'number', 'default' => 1 ],
                [ 'key' => 'complaint_text', 'label' => 'توضیحات', 'type' => 'textarea' ],
            ] ),
            'equipment_purchase' => $equipment_purchase,
            'install'            => $equipment_purchase,
            'site_visit'         => array_merge( $common, $device, [
                [ 'key' => 'complaint_text', 'label' => 'هدف بازدید *', 'type' => 'textarea', 'required' => true ],
            ] ),
            'contract_support'   => array_merge( $common, [
                [ 'key' => 'contract_no', 'label' => 'شماره قرارداد', 'type' => 'text' ],
                [ 'key' => 'company', 'label' => 'نام شرکت / سازمان', 'type' => 'text' ],
                [ 'key' => 'complaint_text', 'label' => 'شرح درخواست پشتیبانی *', 'type' => 'textarea', 'required' => true ],
            ] ),
        ];

        return $by_type[ $service_type ] ?? array_merge( $common, $device, [
            [ 'key' => 'complaint_text', 'label' => 'شرح', 'type' => 'textarea' ],
        ] );
    }

    /** بررسی کامل بودن اطلاعات — سین‌جیم */
    public static function validate_payload( string $service_type, array $data ): array {
        $missing = [];
        foreach ( self::wizard_fields( $service_type ) as $f ) {
            if ( empty( $f['required'] ) ) continue;
            $v = $data[ $f['key'] ] ?? '';
            if ( $v === '' || $v === null ) {
                $missing[] = $f['label'];
            }
        }
        return [ 'complete' => empty( $missing ), 'missing' => $missing ];
    }

    /** تشخیص نوع خدمت از متن آزاد (دستیار HVAC) */
    public static function detect_service_intent( string $text ): array {
        $t = mb_strtolower( trim( $text ) );
        $rules = [
            [ 'parts_supply',       90, [ 'قطعه', 'کمپرسور zr', 'zr190', 'پارت نامبر', 'part no', 'تأمین قطعه', 'سفارش قطعه' ] ],
            [ 'equipment_purchase', 88, [ 'خرید چیلر', 'خرید تجهیز', 'پروژه جدید', 'ظرفیت سرمایش', 'محاسبه بار', 'سفارش چیلر' ] ],
            [ 'contract_support',   86, [ 'قرارداد', 'تحت پوشش', 'ادعا', 'claim', 'sla', 'پشتیبانی قراردادی' ] ],
            [ 'pm',                 84, [ 'نگهداری', 'pm', 'سرویس دوره‌ای', 'ماهانه', 'سه‌ماهه', 'پیشگیرانه' ] ],
            [ 'site_visit',         82, [ 'بازدید', 'کارشناس بیاید', 'عکس و ویدیو', 'بازرسی محل' ] ],
            [ 'phone_consult',      80, [ 'مشاوره', 'کد خطا', 'فشار ساکشن', 'کندانس', 'high condensing', 'تشخیص' ] ],
            [ 'repair',             78, [ 'تعمیر', 'روشن نمی‌شود', 'خراب', 'کنتاکتور', 'اورژانس', 'قطع شده' ] ],
        ];
        $best = [ 'service_type' => 'phone_consult', 'confidence' => 40, 'matched' => [] ];
        foreach ( $rules as [ $type, $base, $keys ] ) {
            $hit = [];
            foreach ( $keys as $k ) {
                if ( $k !== '' && mb_strpos( $t, $k ) !== false ) {
                    $hit[] = $k;
                }
            }
            if ( ! $hit ) continue;
            $score = min( 99, $base + ( count( $hit ) - 1 ) * 4 );
            if ( $score > $best['confidence'] ) {
                $best = [ 'service_type' => $type, 'confidence' => $score, 'matched' => $hit ];
            }
        }
        $routes = self::entry_routes();
        $type = $best['service_type'];
        $followups = match ( $type ) {
            'phone_consult' => [ 'برند و مدل دستگاه؟', 'کد خطا روی پنل چیست؟', 'فشار ساکشن و دیسشارژ را دارید؟' ],
            'repair'        => [ 'اولویت اضطراری است؟', 'آخرین سرویس کی بوده؟', 'آدرس دقیق محل؟' ],
            'pm'            => [ 'تعداد دستگاه‌ها؟', 'بازه PM مورد نظر؟', 'ساعت کارکرد تقریبی؟' ],
            'parts_supply'  => [ 'شماره فنی قطعه؟', 'تعداد؟', 'برند دستگاه؟' ],
            'equipment_purchase' => [ 'شهر پروژه؟', 'مساحت / بار سرمایشی؟', 'ساعات کارکرد روزانه؟' ],
            'site_visit'    => [ 'هدف بازدید؟', 'زمان ترجیحی؟', 'آدرس مجموعه؟' ],
            'contract_support' => [ 'شماره قرارداد؟', 'آیا قطعه خارج از پوشش است؟', 'شرح ادعا؟' ],
            default => [ 'نوع دستگاه؟', 'شرح مشکل را دقیق‌تر بگویید.' ],
        };
        $estimates = [
            'phone_consult' => 1200000, 'repair' => 4500000, 'pm' => 8500000,
            'parts_supply' => 18000000, 'equipment_purchase' => 0, 'site_visit' => 2500000,
            'contract_support' => 0,
        ];
        return [
            'service_type'       => $type,
            'service_label'      => $routes[ $type ]['title'] ?? $type,
            'confidence'         => $best['confidence'],
            'matched_keywords'   => $best['matched'],
            'follow_up_questions'=> $followups,
            'cost_estimate'      => $estimates[ $type ] ?? 500000,
            'suggest_technician' => in_array( $type, [ 'repair', 'site_visit', 'contract_support' ], true ),
            'tech_specialty'     => ( str_contains( $t, 'اسکرو' ) || str_contains( $t, 'screw' ) || str_contains( $t, 'چیلر' ) )
                ? 'چیلر اسکرو' : 'عمومی HVAC',
        ];
    }

    /** تحلیل مشاوره — rule-based (Spec ۲ و ۹) */
    public static function analyze_consult( array $data ): array {
        $error = strtoupper( trim( (string) ( $data['error_code'] ?? '' ) ) );
        $text  = mb_strtolower( (string) ( $data['complaint_text'] ?? '' ) );
        $tips  = [];
        $actions = [];
        $estimate = 0;
        $probabilities = [];

        $suction = self::_parse_pressure( $data['suction_pressure'] ?? '' );
        $discharge = self::_parse_pressure( $data['discharge_pressure'] ?? '' );
        $ambient = (float) ( $data['ambient_temp'] ?? 0 );

        $error_map = [
            'E1' => 'احتمال کمبود گاز یا نشتی — بررسی فشار و نشتی‌یابی',
            'E2' => 'مشکل سنسور دما — کالیبراسیون یا تعویض سنسور',
            'HP' => 'فشار بالا — بررسی کندانسور و فن',
            'LP' => 'فشار پایین — کمبود گاز یا گرفتگی فیلتر',
            'AL' => 'آلارم کمپرسور — اورلود یا خازن استارت',
            'HIGH CONDENSING' => 'فشار کندانس بالا — کندانسور کثیف، فن یا شارژ بیش از حد',
            'HIGH CONDENSING PRESSURE' => 'فشار کندانس بالا — کندانسور کثیف، فن یا شارژ بیش از حد',
        ];
        foreach ( $error_map as $code => $hint ) {
            if ( $code !== '' && str_contains( $error, $code ) ) {
                $tips[] = "کد {$code}: {$hint}";
                $estimate += 1500000;
            }
        }

        $high_cond = str_contains( $error, 'CONDENS' )
            || str_contains( $text, 'کندانس' )
            || str_contains( $text, 'condensing' )
            || str_contains( $text, 'فشار بالا' )
            || ( $discharge !== null && $discharge >= 11.5 );

        if ( $high_cond ) {
            $tips[] = 'تشخیص اولیه: High Condensing Pressure — فشار دیسشارژ غیرعادی.';
            if ( $suction !== null ) {
                $tips[] = "فشار ساکشن گزارش‌شده: {$suction} bar" . ( $suction < 4 ? ' (نسبتاً پایین برای R134a)' : '' );
            }
            if ( $discharge !== null ) {
                $tips[] = "فشار دیسشارژ گزارش‌شده: {$discharge} bar" . ( $discharge >= 12 ? ' (بالا)' : '' );
            }
            if ( $ambient > 0 ) {
                $tips[] = "دمای محیط: {$ambient}°C";
            }
            $probabilities = [
                [ 'cause' => 'کثیفی کندانسور (Dirty Condenser)', 'pct' => 45, 'action' => 'شستشوی کویل کندانسور و بررسی جریان هوا' ],
                [ 'cause' => 'خرابی یا ضعف فن کندانسور', 'pct' => 30, 'action' => 'تست آمپر فن، بلبرینگ و کنترلر' ],
                [ 'cause' => 'شارژ بیش از حد مبرد (Overcharge)', 'pct' => 25, 'action' => 'توزین گاز و تخلیه تا مقدار استاندارد' ],
            ];
            $actions[] = 'بازرسی بصری کویل کندانسور';
            $actions[] = 'اندازه‌گیری جریان فن و اختلاف دمای هوا';
            $actions[] = 'مقایسه فشار با جدول اشباع R134a';
            $estimate = max( $estimate, 2200000 );
        }

        if ( str_contains( $text, 'دمای بالا' ) || str_contains( $text, 'گرم' ) ) {
            $tips[] = 'دمای بالا: فیلتر، کمپرسور، یا گاز را بررسی کنید.';
            $actions[] = 'تست فشار ساکشن/دیسشارژ';
            $estimate += 800000;
        }
        if ( str_contains( $text, 'آلارم' ) || str_contains( $text, 'خاموش' ) || str_contains( $text, 'trip' ) || str_contains( $text, 'قطع' ) ) {
            $tips[] = 'احتمال خرابی الکتریکی یا کمپرسور.';
            $actions[] = 'بازدید کارشناس توصیه می‌شود';
            $estimate += 2000000;
        }
        if ( empty( $tips ) ) {
            $tips[] = 'اطلاعات کافی برای تشخیص قطعی نیست — کارشناس بررسی می‌کند.';
            $actions[] = 'ثبت بازدید یا مشاوره تلفنی';
            $estimate = 500000;
        }

        $validation = self::validate_payload( $data['service_type'] ?? 'phone_consult', $data );
        $outcome = $validation['complete'] && ( count( $tips ) >= 2 || ! empty( $probabilities ) )
            ? 'guide_and_estimate' : 'need_more_info';

        return [
            'outcome'         => $outcome,
            'tips'            => array_values( array_unique( $tips ) ),
            'suggested_tests' => array_values( array_unique( $actions ) ),
            'probabilities'   => $probabilities,
            'cost_estimate'   => $estimate,
            'dispatch_needed' => $outcome !== 'need_more_info' && $estimate >= 1500000,
            'missing_fields'  => $validation['missing'],
            'payment_hint'    => $estimate > 0
                ? 'پس از تأیید تخمین، پرداخت مشاوره و صدور گزارش کارشناس انجام می‌شود.'
                : '',
        ];
    }

    private static function _parse_pressure( $raw ): ?float {
        if ( $raw === null || $raw === '' ) return null;
        if ( is_numeric( $raw ) ) return (float) $raw;
        if ( preg_match( '/([\d.]+)/', (string) $raw, $m ) ) {
            return (float) $m[1];
        }
        return null;
    }

    /** تخمین هزینه تعمیر */
    public static function estimate_repair_cost( array $data ): float {
        $base = 1200000;
        if ( ( $data['priority'] ?? '' ) === 'urgent' ) $base *= 1.35;
        $analysis = self::analyze_consult( $data );
        return max( $base, (float) ( $analysis['cost_estimate'] ?? $base ) );
    }

    /** پیشنهاد قطعات سازگار (rule-based) */
    public static function suggest_parts( string $brand, string $model ): array {
        $brand = mb_strtolower( $brand );
        $suggestions = [];
        if ( str_contains( $brand, 'carrier' ) || str_contains( $brand, 'کریر' ) ) {
            $suggestions = [ 'فیلتر کمپرسور', 'کنترلر Carrier', 'گاز R410A' ];
        } elseif ( str_contains( $brand, 'turbo' ) ) {
            $suggestions = [ 'ترموستات دیجیتال', 'فن کندانسور', 'گاز R134a' ];
        } else {
            $suggestions = [ 'فیلتر هوا', 'کنتاکتور', 'گاز مبرد استاندارد' ];
        }
        if ( $model ) {
            $suggestions[] = "قطعات سازگار با مدل {$model}";
        }
        return $suggestions;
    }

    /** استعلام قطعه — موجود / ناموجود */
    public static function quote_parts( array $data ): array {
        global $wpdb;
        $part_no = sanitize_text_field( $data['part_number'] ?? '' );
        $qty     = max( 1, (int) ( $data['part_qty'] ?? 1 ) );
        $in_stock = false;
        $price = 0;
        $stock_qty = 0;

        if ( $part_no ) {
            $inv_table = $wpdb->prefix . 'inv_products';
            $has_inv   = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $inv_table ) ) === $inv_table;
            $row       = null;
            if ( $has_inv ) {
                $cols = array_column( $wpdb->get_results( "SHOW COLUMNS FROM {$inv_table}", ARRAY_A ) ?: [], 'Field' );
                $col_set = array_flip( $cols );
                $price_col = isset( $col_set['sale_price'] ) ? 'p.sale_price'
                    : ( isset( $col_set['price'] ) ? 'p.price' : null );
                $sku_clause = isset( $col_set['sku'] )
                    ? 'p.sku LIKE %s OR p.name LIKE %s'
                    : 'p.name LIKE %s';
                if ( $price_col ) {
                    $stock_join = $wpdb->get_var( $wpdb->prepare(
                        'SHOW TABLES LIKE %s', $wpdb->prefix . 'inv_stock'
                    ) ) === $wpdb->prefix . 'inv_stock'
                        ? "LEFT JOIN {$wpdb->prefix}inv_stock s ON s.product_id = p.id"
                        : '';
                    $stock_sel = $stock_join ? 'COALESCE(s.qty,0) AS stock_qty' : '0 AS stock_qty';
                    $sql = "SELECT p.id, p.name, {$stock_sel}, {$price_col} AS sale_price
                            FROM {$inv_table} p {$stock_join}
                            WHERE {$sku_clause} LIMIT 1";
                    if ( isset( $col_set['sku'] ) ) {
                        $row = $wpdb->get_row( $wpdb->prepare(
                            $sql,
                            '%' . $wpdb->esc_like( $part_no ) . '%',
                            '%' . $wpdb->esc_like( $part_no ) . '%'
                        ), ARRAY_A );
                    } else {
                        $row = $wpdb->get_row( $wpdb->prepare(
                            $sql,
                            '%' . $wpdb->esc_like( $part_no ) . '%'
                        ), ARRAY_A );
                    }
                }
            }
            if ( $row ) {
                $stock_qty = (int) $row['stock_qty'];
                $in_stock  = $stock_qty >= $qty;
                $price     = (float) ( $row['sale_price'] ?? 0 ) * $qty;
            }
        }

        require_once ACC_PATH . 'includes/helpers/svc-supplier.php';
        $all = method_exists( 'Svc_Supplier', 'match_catalog_all' )
            ? Svc_Supplier::match_catalog_all( $part_no, $qty )
            : array_filter( [ Svc_Supplier::match_catalog( $part_no, $qty ) ] );
        $suppliers = [];
        foreach ( $all as $row ) {
            if ( ! is_array( $row ) ) continue;
            $suppliers[] = [
                'supplier_id'   => (int) ( $row['supplier_user_id'] ?? 0 ),
                'supplier_name' => $row['company_name'] ?? '',
                'catalog_id'    => (int) ( $row['id'] ?? 0 ),
                'catalog_name'  => $row['name'] ?? '',
                'sku'           => $row['sku'] ?? $part_no,
                'price'         => (float) ( $row['price'] ?? 0 ) * $qty,
                'unit_price'    => (float) ( $row['price'] ?? 0 ),
                'warranty_months' => (int) ( $row['warranty_months'] ?? $row['lead_days'] ?? 0 ) ?: 6,
                'lead_days'     => max( 1, (int) ( $row['lead_days'] ?? 5 ) ),
                'rating'        => (float) ( $row['rating'] ?? 4.2 ),
                'in_stock'      => ! empty( $row['in_stock'] ),
                'stock_qty'     => (int) ( $row['stock_qty'] ?? 0 ),
            ];
        }

        if ( ! $in_stock ) {
            $match = $all[0] ?? null;
            if ( $match ) {
                $sup_price = (float) ( $match['price'] ?? 0 ) * $qty;
                $eta       = max( 1, (int) ( $match['lead_days'] ?? 5 ) );
                return [
                    'status'         => 'supplier_catalog',
                    'in_stock'       => ! empty( $match['in_stock'] ),
                    'stock_qty'      => (int) ( $match['stock_qty'] ?? 0 ),
                    'price'          => $sup_price,
                    'eta_days'       => $eta,
                    'deposit_pct'    => 30,
                    'supplier_id'    => (int) ( $match['supplier_user_id'] ?? 0 ),
                    'supplier_name'  => $match['company_name'] ?? '',
                    'catalog_id'     => (int) ( $match['id'] ?? 0 ),
                    'catalog_name'   => $match['name'] ?? '',
                    'suppliers'      => $suppliers,
                    'message'        => count( $suppliers ) > 1
                        ? ( 'مقایسه ' . count( $suppliers ) . ' تأمین‌کننده — پیش‌فاکتور از بهترین قیمت صادر می‌شود.' )
                        : 'قطعه از کاتالوگ تأمین‌کننده یافت شد — پیش‌فاکتور صادر می‌شود.',
                ];
            }
            return [
                'status'      => 'supplier_required',
                'in_stock'    => false,
                'stock_qty'   => $stock_qty,
                'price'       => 0,
                'eta_days'    => 5,
                'deposit_pct' => 30,
                'suppliers'   => [],
                'message'     => 'قطعه در انبار موجود نیست — سفارش از تأمین‌کننده ثبت می‌شود.',
            ];
        }

        return [
            'status'     => 'in_stock',
            'in_stock'   => true,
            'stock_qty'  => $stock_qty,
            'price'      => $price,
            'suppliers'  => $suppliers,
            'message'    => 'قطعه موجود است — پیش‌فاکتور صادر می‌شود.',
        ];
    }

    /** هشدار مصرفی PM */
    public static function consumption_alerts( int $device_id ): array {
        global $wpdb;
        $dev = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM {$wpdb->prefix}svc_devices WHERE id=%d", $device_id
        ), ARRAY_A );
        if ( ! $dev ) return [];

        $hours = (int) ( $dev['operating_hours'] ?? 0 );
        $alerts = [];
        if ( $hours > 8000 ) $alerts[] = [ 'type' => 'filter', 'msg' => 'زمان تعویض فیلتر هوا' ];
        if ( $hours > 12000 ) $alerts[] = [ 'type' => 'oil', 'msg' => 'بررسی روغن کمپرسور' ];
        if ( $hours > 16000 ) $alerts[] = [ 'type' => 'overhaul', 'msg' => 'اورهال دوره‌ای پیشنهاد می‌شود' ];
        return $alerts;
    }

    public static function build_extra_data( array $payload ): string {
        $keys = [
            'error_code', 'ambient_temp', 'suction_pressure', 'discharge_pressure',
            'priority', 'operating_hours', 'pm_plan', 'part_number', 'part_qty',
            'project_city', 'application', 'required_capacity', 'budget_range',
            'space_constraints', 'contract_no', 'year_built', 'consult_result',
            'parts_quote', 'cost_estimate', 'photo_refs',
        ];
        $extra = [];
        foreach ( $keys as $k ) {
            if ( isset( $payload[ $k ] ) && $payload[ $k ] !== '' && $payload[ $k ] !== null ) {
                $extra[ $k ] = $payload[ $k ];
            }
        }
        return wp_json_encode( $extra, JSON_UNESCAPED_UNICODE );
    }

    public static function decode_extra( ?string $json ): array {
        if ( ! $json ) return [];
        $d = json_decode( $json, true );
        return is_array( $d ) ? $d : [];
    }
}
