<?php
/**
 * election-v6-features.php — GIS هوادار، انتخاب صندوق، زنجیره انبار، شهرستان/کمیته، SMS onboarding
 */
if ( ! defined( 'ABSPATH' ) ) exit;

trait Election_V6_Features {

    public const MAX_STATIONS_PER_SUPPORTER = 3;

    public const COUNTY_ZONES = [
        'ouz'       => [ 'name' => 'شهرستان اوز',       'icon' => '🏜️', 'district_codes' => [ 'D-1', 'D-2' ] ],
        'juyom'     => [ 'name' => 'شهرستان جویم',     'icon' => '🌾', 'district_codes' => [ 'D-2' ] ],
        'khanj'     => [ 'name' => 'شهرستان خنج',      'icon' => '🏔️', 'district_codes' => [ 'D-3' ] ],
        'gerash'    => [ 'name' => 'شهرستان گراش',     'icon' => '🌊', 'district_codes' => [ 'D-3', 'D-4' ] ],
        'larestan'  => [ 'name' => 'شهرستان لارستان',  'icon' => '🏛️', 'district_codes' => [ 'D-4' ] ],
        'shiraz'    => [ 'name' => 'شیراز (مرکز)',     'icon' => '🗳️', 'district_codes' => [ 'D-1', 'D-2', 'D-3', 'D-4' ] ],
    ];

    public const COMMITTEE_TYPES = [
        'youth'      => [ 'title' => 'جوانان',        'icon' => '🎓' ],
        'women'      => [ 'title' => 'بانوان',        'icon' => '👩' ],
        'trades'     => [ 'title' => 'اصناف',         'icon' => '🏪' ],
        'engineers'  => [ 'title' => 'مهندسان',       'icon' => '⚙️' ],
        'clerics'    => [ 'title' => 'روحانیون',      'icon' => '🕌' ],
        'teachers'   => [ 'title' => 'فرهنگیان',      'icon' => '📚' ],
        'doctors'    => [ 'title' => 'پزشکان',        'icon' => '⚕️' ],
        'workers'    => [ 'title' => 'کارگران',       'icon' => '🔧' ],
    ];

    public static function onboarding_table(): string {
        global $wpdb;
        return $wpdb->prefix . 'election_onboarding';
    }

    public static function supporter_map_data( int $uid ): array {
        $stations  = self::user_stations( $uid );
        $pickable  = self::list_pickable_stations( $uid );
        $pois      = self::list_pois( null, $uid );
        $banners   = self::list_banner_spots( null, self::portal_mode( $uid ) === 'supporter' ? $uid : null );
        $segments  = self::list_segments_for_map( $uid );
        $districts = self::list_districts();

        $markers = [];
        foreach ( $stations as $s ) {
            if ( empty( $s['lat'] ) || empty( $s['lng'] ) ) continue;
            $markers[] = [
                'type' => 'station', 'id' => (int) $s['id'], 'lat' => (float) $s['lat'], 'lng' => (float) $s['lng'],
                'title' => $s['code'] . ' — ' . $s['name'], 'meta' => $s['neighborhood'] ?? '',
                'mine'  => true,
            ];
        }
        foreach ( $pickable as $s ) {
            if ( empty( $s['lat'] ) || empty( $s['lng'] ) ) continue;
            if ( ! empty( $s['is_mine'] ) ) continue;
            $markers[] = [
                'type' => 'station_available', 'id' => (int) $s['id'],
                'lat' => (float) $s['lat'], 'lng' => (float) $s['lng'],
                'title' => $s['code'] . ' — ' . $s['name'], 'meta' => 'قابل انتخاب',
            ];
        }
        foreach ( $pois as $i => $p ) {
            $sid = (int) ( $p['station_id'] ?? 0 );
            $st  = null;
            foreach ( $stations as $s ) {
                if ( (int) $s['id'] === $sid ) { $st = $s; break; }
            }
            if ( ! $st || empty( $st['lat'] ) ) continue;
            $off = ( $i % 5 ) * 0.0012;
            $markers[] = [
                'type'  => 'poi', 'id' => (int) $p['id'],
                'lat'   => (float) $st['lat'] + $off, 'lng' => (float) $st['lng'] + $off * 0.7,
                'title' => $p['name'], 'meta' => $p['poi_type_label'] ?? '',
            ];
        }
        foreach ( $banners as $i => $b ) {
            $st = self::get_station_row( (int) $b['station_id'] );
            if ( ! $st || empty( $st['lat'] ) ) continue;
            $markers[] = [
                'type'  => 'banner', 'id' => (int) $b['id'],
                'lat'   => (float) $st['lat'] - 0.001 - $i * 0.0003,
                'lng'   => (float) $st['lng'] + 0.001,
                'title' => $b['location_desc'], 'meta' => $b['status_label'] ?? '',
            ];
        }
        foreach ( $segments as $seg ) {
            if ( empty( $seg['lat'] ) || empty( $seg['lng'] ) ) continue;
            $markers[] = [
                'type'  => 'segment', 'id' => (int) $seg['id'],
                'lat'   => (float) $seg['lat'], 'lng' => (float) $seg['lng'],
                'title' => $seg['code'], 'meta' => $seg['neighborhood'] ?? '',
            ];
        }

        $blocks = [];
        if ( self::gis_tables_exist() ) {
            global $wpdb;
            $pre = $wpdb->prefix;
            if ( $wpdb->get_var( "SHOW TABLES LIKE '{$pre}gis_block_stats'" ) === $pre . 'gis_block_stats' ) {
                $blocks = $wpdb->get_results(
                    "SELECT block_code, neighborhood_id, center_lat, center_lng,
                            total_parcels AS parcel_count, cnt_apartment AS apt_count
                     FROM {$pre}gis_block_stats WHERE center_lat IS NOT NULL AND center_lng IS NOT NULL
                     ORDER BY total_parcels DESC LIMIT 40",
                    ARRAY_A
                ) ?: [];
            }
        }

        return [
            'read_only'  => ! self::can_manage( $uid ),
            'center'     => self::map_center_from_markers( $markers ),
            'markers'    => $markers,
            'blocks'     => $blocks,
            'stats'      => [
                'stations'  => count( $stations ),
                'pois'      => count( $pois ),
                'banners'   => count( $banners ),
                'segments'  => count( $segments ),
                'target_segments' => 1011,
            ],
        ];
    }

    private static function map_center_from_markers( array $markers ): array {
        if ( ! $markers ) {
            return [ 'lat' => 29.5918, 'lng' => 52.5837, 'zoom' => 12 ];
        }
        $lat = array_sum( array_column( $markers, 'lat' ) ) / count( $markers );
        $lng = array_sum( array_column( $markers, 'lng' ) ) / count( $markers );
        return [ 'lat' => round( $lat, 6 ), 'lng' => round( $lng, 6 ), 'zoom' => 13 ];
    }

    private static function get_station_row( int $id ): ?array {
        global $wpdb;
        $row = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM " . self::stations_table() . " WHERE id = %d", $id
        ), ARRAY_A );
        return $row ?: null;
    }

    public static function list_segments_for_map( int $uid ): array {
        global $wpdb;
        $t = self::segments_table();
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$t}'" ) !== $t ) {
            return [];
        }
        $sup = self::get_supporter_by_user( $uid );
        $nbs = [];
        if ( $sup && ! empty( $sup['branch']['zone']['neighborhoods'] ) ) {
            $nbs = (array) $sup['branch']['zone']['neighborhoods'];
        }
        if ( $nbs ) {
            $ph = implode( ',', array_fill( 0, count( $nbs ), '%s' ) );
            return $wpdb->get_results( $wpdb->prepare(
                "SELECT id, code, neighborhood, voter_count, lat, lng FROM {$t}
                 WHERE neighborhood IN ($ph) AND lat IS NOT NULL ORDER BY code LIMIT 80",
                ...$nbs
            ), ARRAY_A ) ?: [];
        }
        return $wpdb->get_results(
            "SELECT id, code, neighborhood, voter_count, lat, lng FROM {$t}
             WHERE lat IS NOT NULL ORDER BY code LIMIT 50",
            ARRAY_A
        ) ?: [];
    }

    public static function list_pickable_stations( int $uid ): array {
        $all   = self::list_stations_enriched();
        $mine  = self::user_station_ids( $uid );
        $ust   = self::user_stations_table();
        global $wpdb;
        $counts = [];
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$ust}'" ) === $ust ) {
            $rows = $wpdb->get_results(
                "SELECT station_id, COUNT(*) AS c FROM {$ust} GROUP BY station_id", ARRAY_A
            ) ?: [];
            foreach ( $rows as $r ) {
                $counts[ (int) $r['station_id'] ] = (int) $r['c'];
            }
        }
        $out = [];
        foreach ( $all as $s ) {
            $sid = (int) $s['id'];
            $out[] = array_merge( $s, [
                'is_mine'           => in_array( $sid, $mine, true ),
                'supporter_count'   => $counts[ $sid ] ?? 0,
                'can_pick'          => in_array( $sid, $mine, true ) || count( $mine ) < self::MAX_STATIONS_PER_SUPPORTER,
            ] );
        }
        return $out;
    }

    public static function pick_stations( int $uid, array $station_ids, string $mode = 'add' ): array {
        if ( ! self::get_supporter_by_user( $uid ) && ! self::can_manage( $uid ) ) {
            if ( empty( self::user_station_ids( $uid ) ) && ! acl_user_can( $uid, 'election.supporter' ) ) {
                return [ 'success' => false, 'message' => 'فقط هواداران می‌توانند صندوق انتخاب کنند' ];
            }
        }
        $station_ids = array_values( array_unique( array_map( 'intval', $station_ids ) ) );
        if ( ! $station_ids ) {
            return [ 'success' => false, 'message' => 'صندوق انتخاب نشده' ];
        }
        $current = $mode === 'replace' ? [] : self::user_station_ids( $uid );
        $merged  = array_values( array_unique( array_merge( $current, $station_ids ) ) );
        if ( count( $merged ) > self::MAX_STATIONS_PER_SUPPORTER ) {
            return [
                'success' => false,
                'message' => 'حداکثر ' . self::MAX_STATIONS_PER_SUPPORTER . ' صندوق مجاز است',
            ];
        }
        global $wpdb;
        $st = self::stations_table();
        foreach ( $merged as $sid ) {
            if ( ! (int) $wpdb->get_var( $wpdb->prepare( "SELECT id FROM {$st} WHERE id=%d", $sid ) ) ) {
                return [ 'success' => false, 'message' => "صندوق #{$sid} نامعتبر" ];
            }
        }
        return self::assign_stations_to_user( $uid, $merged, 'supporter' );
    }

    public static function issue_warehouse_and_ship( int $uid, array $data ): array {
        $station_id = (int) ( $data['station_id'] ?? 0 );
        $to_user    = (int) ( $data['to_user_id'] ?? 0 );
        $items      = $data['items'] ?? [];
        if ( ! is_array( $items ) || ! $items ) {
            $items = [ [
                'item_id' => (int) ( $data['item_id'] ?? 0 ),
                'qty'     => max( 1, (int) ( $data['qty'] ?? 1 ) ),
            ] ];
        }
        if ( ! $station_id ) {
            return [ 'success' => false, 'message' => 'صندوق مقصد الزامی است' ];
        }
        $recipient = $to_user ?: $uid;
        $lines     = [];
        $move_ids  = [];

        foreach ( $items as $line ) {
            $res = self::issue_warehouse_item( $uid, [
                'item_id'    => (int) ( $line['item_id'] ?? 0 ),
                'qty'        => max( 1, (int) ( $line['qty'] ?? 1 ) ),
                'station_id' => $station_id,
                'to_user_id' => $recipient,
                'notes'      => $data['notes'] ?? '',
            ] );
            if ( empty( $res['success'] ) ) {
                return $res;
            }
            $move_ids[] = (int) ( $res['id'] ?? 0 );
            global $wpdb;
            $item = $wpdb->get_row( $wpdb->prepare(
                "SELECT * FROM " . self::warehouse_table() . " WHERE id=%d", (int) $line['item_id']
            ), ARRAY_A );
            $lines[] = [
                'item_id' => (int) $line['item_id'],
                'sku'     => $item['sku'] ?? '',
                'name'    => $item['name'] ?? '',
                'qty'     => (int) $line['qty'],
            ];
        }

        global $wpdb;
        $sht = self::shipments_table();
        $st  = self::get_station_row( $station_id );
        $title = 'محموله انبار → ' . ( $st['code'] ?? $station_id );
        $wpdb->insert( $sht, [
            'station_id'         => $station_id,
            'user_id'            => $recipient,
            'package_id'         => null,
            'phase'              => self::current_phase(),
            'title'              => $title,
            'status'             => 'shipped',
            'warehouse_move_id'  => $move_ids[0] ?? null,
            'items_json'         => wp_json_encode( $lines, JSON_UNESCAPED_UNICODE ),
            'shipped_at'         => current_time( 'mysql' ),
            'created_at'         => current_time( 'mysql' ),
        ] );
        $ship_id = (int) $wpdb->insert_id;
        $mt = self::warehouse_moves_table();
        foreach ( $move_ids as $mid ) {
            if ( $mid ) {
                $wpdb->update( $mt, [ 'shipment_id' => $ship_id ], [ 'id' => $mid ] );
            }
        }
        self::seed_tasks_for_user_stations( $recipient, [ $station_id ] );

        return [
            'success'     => true,
            'shipment_id' => $ship_id,
            'items'       => $lines,
            'move_ids'    => $move_ids,
        ];
    }

    public static function list_shipment_chain( int $uid ): array {
        global $wpdb;
        $sht = self::shipments_table();
        $mt  = self::warehouse_moves_table();
        if ( $wpdb->get_var( "SHOW TABLES LIKE '{$sht}'" ) !== $sht ) {
            return [];
        }
        $shipments = self::list_shipments( $uid );
        foreach ( $shipments as &$s ) {
            $s['items'] = json_decode( $s['items_json'] ?? '[]', true ) ?: [];
            $mid = (int) ( $s['warehouse_move_id'] ?? 0 );
            if ( $mid && $wpdb->get_var( "SHOW TABLES LIKE '{$mt}'" ) === $mt ) {
                $s['warehouse_move'] = $wpdb->get_row( $wpdb->prepare(
                    "SELECT * FROM {$mt} WHERE id=%d", $mid
                ), ARRAY_A );
            }
        }
        return $shipments;
    }

    public static function county_portal_data( int $uid ): array {
        global $wpdb;
        $districts = self::list_districts();
        $by_code   = [];
        foreach ( $districts as $d ) {
            $by_code[ $d['code'] ?? '' ] = $d;
        }
        $zones = [];
        foreach ( self::COUNTY_ZONES as $slug => $z ) {
            $dids = [];
            foreach ( $z['district_codes'] as $code ) {
                if ( isset( $by_code[ $code ] ) ) {
                    $dids[] = (int) $by_code[ $code ]['id'];
                }
            }
            $zones[] = array_merge( $z, [
                'slug'          => $slug,
                'district_ids'  => $dids,
                'station_count' => self::count_stations_in_districts( $dids ),
                'segment_count' => self::count_segments_in_districts( $dids ),
            ] );
        }
        return [
            'counties'    => $zones,
            'branches'    => self::list_branches_summary(),
            'supporters'  => (int) $wpdb->get_var( "SELECT COUNT(*) FROM " . self::supporters_table() . " WHERE is_active=1" ),
            'segments'    => (int) $wpdb->get_var( "SELECT COUNT(*) FROM " . self::segments_table() ),
            'target'      => 1011,
            'stations'    => count( self::list_stations_enriched() ),
        ];
    }

    private static function count_stations_in_districts( array $district_ids ): int {
        if ( ! $district_ids ) return 0;
        global $wpdb;
        $ph = implode( ',', array_fill( 0, count( $district_ids ), '%d' ) );
        return (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT COUNT(*) FROM " . self::stations_table() . " WHERE district_id IN ($ph)", ...$district_ids
        ) );
    }

    private static function count_segments_in_districts( array $district_ids ): int {
        global $wpdb;
        $st = self::stations_table();
        $seg = self::segments_table();
        if ( ! $district_ids ) {
            return (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$seg}" );
        }
        $ph = implode( ',', array_fill( 0, count( $district_ids ), '%d' ) );
        return (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT COUNT(*) FROM {$seg} s
             INNER JOIN {$st} st ON st.id = s.station_id
             WHERE st.district_id IN ($ph)", ...$district_ids
        ) );
    }

    public static function list_branches_summary(): array {
        global $wpdb;
        $bt = self::branches_table();
        $st = self::supporters_table();
        $rows = $wpdb->get_results(
            "SELECT b.*, (SELECT COUNT(*) FROM {$st} sup WHERE sup.branch_id=b.id AND sup.is_active=1) AS supporter_count
             FROM {$bt} b WHERE b.is_active=1 ORDER BY b.id",
            ARRAY_A
        ) ?: [];
        return array_map( [ __CLASS__, 'fmt_branch' ], $rows );
    }

    public static function committee_portal_data( int $uid ): array {
        $committees = [];
        foreach ( self::COMMITTEE_TYPES as $slug => $c ) {
            $committees[] = array_merge( $c, [
                'slug'        => $slug,
                'work_count'  => self::dept_work_count( 'committees' ),
                'sample_task' => self::committee_sample_task( $slug ),
            ] );
        }
        return [
            'committees' => $committees,
            'segments'   => self::segment_count(),
            'dept_work'  => self::list_dept_work( $uid, 'committees' ),
        ];
    }

    private static function segment_count(): int {
        global $wpdb;
        return (int) $wpdb->get_var( "SELECT COUNT(*) FROM " . self::segments_table() );
    }

    private static function site_election_url(): string {
        return '/acc-engine/election.php';
    }

    private static function committee_sample_task( string $slug ): string {
        $map = [
            'youth'     => 'جلسه کمیته جوانان — رای‌زنی دانشگاه',
            'women'     => 'جلسه بانوان — معالی‌آباد',
            'trades'    => 'رای‌زنی با اصناف زند',
            'engineers' => 'نشست مهندسان — طرح توسعه',
            'clerics'   => 'هماهنگی با هیئت‌های مذهبی',
            'teachers'  => 'فرهنگیان — آموزش و پرورش',
            'doctors'   => 'پزشکان — بهداشت و درمان',
            'workers'   => 'کارگران — واحدهای تولیدی',
        ];
        return $map[ $slug ] ?? 'فعالیت کمیته';
    }

    public static function request_onboarding( string $phone, ?int $invited_by = null ): array {
        global $wpdb;
        $phone = self::normalize_phone( $phone );
        if ( ! $phone ) {
            return [ 'success' => false, 'message' => 'شماره موبایل نامعتبر' ];
        }
        $t = self::onboarding_table();
        $code = (string) wp_rand( 100000, 999999 );
        $token = wp_generate_password( 32, false );
        $wpdb->insert( $t, [
            'phone'       => $phone,
            'otp_code'    => $code,
            'token'       => $token,
            'status'      => 'pending',
            'invited_by'  => $invited_by,
            'expires_at'  => gmdate( 'Y-m-d H:i:s', time() + 600 ),
            'created_at'  => current_time( 'mysql' ),
        ] );
        require_once ACC_PATH . 'includes/helpers/acc-sms.php';
        $demo = self::otp_demo_mode();
        if ( $demo ) {
            $site = self::site_election_url();
            $msg  = "سامانه هوادران انتخابات\nکد ورود: {$code}\n{$site}";
            $send = Acc_SMS::send( $phone, $msg );
        } else {
            $send = Acc_SMS::send_otp( $phone, $code );
        }
        self::queue_sms( [
            'phone'   => $phone,
            'message' => $demo ? "OTP demo: {$code}" : 'OTP via provider',
            'user_id' => $invited_by,
            'send'    => false,
        ] );
        $out = [
            'success'   => true,
            'token'     => $token,
            'sms'       => $send,
            'demo_mode' => $demo,
            'message'   => 'کد تأیید ارسال شد',
        ];
        if ( $demo ) {
            $out['demo_code'] = $code;
        }
        return $out;
    }

    public static function verify_onboarding( string $phone, string $code, string $token = '' ): array {
        global $wpdb;
        $phone = self::normalize_phone( $phone );
        $t = self::onboarding_table();
        $row = $wpdb->get_row( $wpdb->prepare(
            "SELECT * FROM {$t} WHERE phone=%s AND status='pending' ORDER BY id DESC LIMIT 1", $phone
        ), ARRAY_A );
        if ( ! $row ) {
            return [ 'success' => false, 'message' => 'درخواست یافت نشد' ];
        }
        if ( $token && $row['token'] !== $token ) {
            return [ 'success' => false, 'message' => 'توکن نامعتبر' ];
        }
        if ( strtotime( $row['expires_at'] ) < time() ) {
            return [ 'success' => false, 'message' => 'کد منقضی شده' ];
        }
        if ( $row['otp_code'] !== $code ) {
            return [ 'success' => false, 'message' => 'کد اشتباه است' ];
        }
        $wpdb->update( $t, [ 'status' => 'verified', 'verified_at' => current_time( 'mysql' ) ], [ 'id' => $row['id'] ] );
        return [ 'success' => true, 'token' => $row['token'], 'phone' => $phone ];
    }

    public static function complete_onboarding( string $phone, string $code, string $display_name ): array {
        $v = self::verify_onboarding( $phone, $code );
        if ( empty( $v['success'] ) ) {
            return $v;
        }
        global $wpdb;
        $phone = $v['phone'];
        $login = 'election_sup_' . substr( preg_replace( '/\D/', '', $phone ), -8 );
        $exists = (int) $wpdb->get_var( $wpdb->prepare(
            "SELECT ID FROM {$wpdb->users} WHERE user_login=%s", $login
        ) );
        if ( $exists ) {
            $uid = $exists;
            $login = $wpdb->get_var( $wpdb->prepare( "SELECT user_login FROM {$wpdb->users} WHERE ID=%d", $uid ) );
        } else {
            $pass = 'Election' . wp_rand( 1000, 9999 );
            $uid  = (int) $wpdb->get_var( "SELECT COALESCE(MAX(ID),0) FROM {$wpdb->users}" ) + 1;
            $wpdb->insert( "{$wpdb->users}", [
                'ID' => $uid, 'user_login' => $login, 'user_pass' => wp_hash_password( $pass ),
                'user_nicename' => sanitize_title( $login ), 'user_email' => $login . '@election.local',
                'user_registered' => current_time( 'mysql' ), 'display_name' => $display_name ?: 'هوادار',
                'user_status' => 0,
            ] );
            $rid = (int) $wpdb->get_var( "SELECT id FROM {$wpdb->prefix}acl_roles WHERE slug='election_supporter'" );
            if ( $rid ) {
                $wpdb->insert( "{$wpdb->prefix}acl_user_roles", [
                    'user_id' => $uid, 'role_id' => $rid, 'scope_type' => 'global', 'granted_by' => 1,
                ] );
            }
            $bt = self::branches_table();
            $branch_id = (int) $wpdb->get_var( "SELECT id FROM {$bt} WHERE is_active=1 ORDER BY id LIMIT 1" );
            $wpdb->insert( self::supporters_table(), [
                'user_id' => $uid, 'branch_id' => $branch_id ?: null,
                'segment_ids_json' => '[]', 'is_active' => 1,
                'joined_at' => current_time( 'mysql' ),
            ] );
            $msg = "خوش آمدید!\nکاربر: {$login}\nرمز: {$pass}\n" . self::site_election_url();
            require_once ACC_PATH . 'includes/helpers/acc-sms.php';
            Acc_SMS::send( $phone, $msg );
        }
        $wpdb->update( self::onboarding_table(), [ 'status' => 'completed', 'user_id' => $uid ], [
            'phone' => $phone, 'status' => 'verified',
        ] );
        return [
            'success'  => true,
            'user_id'  => $uid,
            'login'    => $login,
            'message'  => 'ثبت‌نام تکمیل شد — وارد شوید',
        ];
    }

    public static function normalize_phone( string $phone ): string {
        $p = preg_replace( '/\D/', '', $phone );
        if ( str_starts_with( $p, '98' ) && strlen( $p ) === 12 ) {
            $p = '0' . substr( $p, 2 );
        }
        if ( str_starts_with( $p, '9' ) && strlen( $p ) === 10 ) {
            $p = '0' . $p;
        }
        return ( strlen( $p ) === 11 && str_starts_with( $p, '09' ) ) ? $p : '';
    }

    public static function admin_send_onboarding( int $admin_uid, array $data ): array {
        if ( ! self::can_manage( $admin_uid ) ) {
            return [ 'success' => false, 'message' => 'دسترسی ندارید' ];
        }
        return self::request_onboarding( $data['phone'] ?? '', $admin_uid );
    }
}
