<?php
$sub_menu = '600100';
include_once('./_common.php');

if (isset($_REQUEST['sort']) && !preg_match("/(--|#|\/\*|\*\/)/", $_REQUEST['sort'])) {
    $sort = trim($_REQUEST['sort']);
    $sort = preg_replace("/[\<\>\'\"\\\'\\\"\%\=\(\)\s]/", "", $sort);
} else {
    $sort = '';
}
if (isset($_REQUEST['sortodr'])) {
    $sortodr = preg_match("/^(asc|desc)$/i", $_REQUEST['sortodr']) ? $_REQUEST['sortodr'] : '';
} else {
    $sortodr = '';
}

if (!defined('G5_USE_SHOP') || !G5_USE_SHOP)
    die('<p>쇼핑몰 설치 후 이용해 주십시오.</p>');

if (!defined('_SHOP_')) define('_SHOP_', true);
if (!defined('IS_SHOP')) define('IS_SHOP', true);
if (!defined('APMS_PARTNER_DIR')) {
    define('APMS_PARTNER_DIR', G5_SHOP_DIR.'/partner');
    define('APMS_PARTNER_PATH', G5_PATH.'/'.APMS_PARTNER_DIR);
    define('APMS_PARTNER_URL', G5_URL.'/'.APMS_PARTNER_DIR);
    define('APMS_PARTNER_HTTPS_URL', https_url(APMS_PARTNER_DIR, true));
}

if($is_guest) {
    $returnUrl = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http')
        . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
    alert('로그인해 주세요.', APMS_PARTNER_URL.'/login.php?returnUrl='.urlencode($returnUrl));
}

$is_auth = ($is_admin === 'super');
$is_seller = (defined('IS_SELLER') && IS_SELLER) ? true : false;
$is_partner = (defined('IS_PARTNER') && IS_PARTNER) ? true : false;

if(!$is_auth && !$is_seller && !$is_partner) {
    alert('판매자(셀러/파트너) 또는 관리자만 이용 가능합니다.', APMS_PARTNER_URL);
}

function h($str) {
    return htmlspecialchars((string)$str, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

function ai_rand_str($len = 8) {
    $chars = 'abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789';
    $max = strlen($chars) - 1;
    $out = '';
    for($i = 0; $i < $len; $i++) {
        $out .= $chars[random_int(0, $max)];
    }
    return $out;
}

function ai_pick_protocol_image($protocol) {
    $protocol = (string)$protocol;
    if(stripos($protocol, 'IKEv2') !== false) return 'img_os/IKEv2.png';
    if(stripos($protocol, 'L2TP') !== false) return 'img_os/L2TP_IPsec.png';
    if(stripos($protocol, 'OpenVPN') !== false) return 'img_os/OpenVPN.png';
    if(stripos($protocol, 'PPTP') !== false) return 'img_os/PPTP.png';
    if(stripos($protocol, 'WireGuard') !== false) return 'img_os/WireGuard.png';
    return 'img_os/Etc_VPN.png';
}

function ai_protocol_aliases($protocol) {
    $p = trim((string)$protocol);
    if($p === '') return array();

    $aliases = array();
    $aliases[] = $p;
    $aliases[] = str_replace('-VPN-', '-', $p);
    $aliases[] = str_replace('VPN-', '', $p);
    $aliases[] = str_replace('-VPN', '', $p);

    $uniq = array();
    foreach($aliases as $a) {
        $a = trim((string)$a);
        if($a === '') continue;
        $k = strtolower($a);
        if(!isset($uniq[$k])) {
            $uniq[$k] = $a;
        }
    }

    return array_values($uniq);
}

function ai_generate_it_id_from_counter($tableName, $max_len = 20) {
    $max_len = (int)$max_len;
    if($max_len < 1) {
        $max_len = 20;
    }

    for($t = 0; $t < 30; $t++) {
        // vpn-mall.php 참조: 품번 카운터 증가 후 사용
        sql_query(" UPDATE g5_shop_item_it_id_counter SET it_id_last = it_id_last + 1 ");
        $it_id_last = sql_fetch(" SELECT it_id_last FROM g5_shop_item_it_id_counter ", false);

        $candidate = isset($it_id_last['it_id_last']) ? trim((string)$it_id_last['it_id_last']) : '';
        if($candidate === '') {
            continue;
        }

        if(strlen($candidate) > $max_len) {
            $candidate = substr($candidate, 0, $max_len);
        }

        $exists = sql_fetch(" select it_id from {$tableName} where it_id = '".sql_real_escape_string($candidate)."' ", false);
        if(!$exists || empty($exists['it_id'])) {
            return $candidate;
        }
    }

    return '';
}

function ai_load_shop_sync_secret() {
    if(isset($_SERVER['IKEV2_SHOP_SYNC_SHARED_SECRET'])) {
        $s = trim((string)$_SERVER['IKEV2_SHOP_SYNC_SHARED_SECRET']);
        if($s !== '') return $s;
    }
    if(isset($_ENV['IKEV2_SHOP_SYNC_SHARED_SECRET'])) {
        $s = trim((string)$_ENV['IKEV2_SHOP_SYNC_SHARED_SECRET']);
        if($s !== '') return $s;
    }
    if(function_exists('getenv')) {
        $s = getenv('IKEV2_SHOP_SYNC_SHARED_SECRET');
        if(is_string($s) && trim($s) !== '') return trim($s);
    }
    $envPath = dirname(__DIR__) . '/.env';
    if(is_file($envPath) && is_readable($envPath)) {
        $lines = @file($envPath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        if(is_array($lines)) {
            foreach($lines as $line) {
                $line = trim((string)$line);
                if($line === '' || strpos($line, '#') === 0) continue;
                $pos = strpos($line, '=');
                if($pos === false) continue;
                $k = trim(substr($line, 0, $pos));
                if($k !== 'IKEV2_SHOP_SYNC_SHARED_SECRET') continue;
                $v = trim(substr($line, $pos + 1));
                if(strlen($v) >= 2 && (($v[0] === '"' && substr($v,-1) === '"') || ($v[0] === "'" && substr($v,-1) === "'"))) {
                    $v = substr($v, 1, -1);
                }
                if($v !== '') return $v;
            }
        }
    }
    return '';
}

function ai_call_ikev2_delete_user($serverIp, $vpnUserId, $mbId, $secret) {
    $serverIp  = trim((string)$serverIp);
    $vpnUserId = trim((string)$vpnUserId);
    if($serverIp === '' || $vpnUserId === '' || $secret === '') {
        return array('ok' => false, 'error' => 'missing_params', 'http_code' => 0, 'transport_error' => '');
    }

    $hasScheme = (bool)preg_match('#^https?://#i', $serverIp);
    $base = $hasScheme ? rtrim($serverIp, '/') : 'https://' . rtrim($serverIp, '/');
    $primaryEndpoint = $base . '/IKEv2SellerOffice4U/vpn_users.php';

    $postFields = array(
        'action'      => 'delete_user',
        'user_id'     => $vpnUserId,
        'sync_origin' => 'shop_backend',
        'reason'      => 'ai_bulk_test_cleanup',
        'mb_id'       => $mbId,
        'deleted_at'  => date('Y-m-d H:i:s'),
    );
    $payloadStr = http_build_query($postFields, '', '&');
    $signature  = hash_hmac('sha256', $payloadStr, $secret);
    $postFields['sync_signature'] = $signature;
    $requestPayload = http_build_query($postFields, '', '&');

    $httpHeaders = array(
        'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
        'Accept: application/json',
        'X-Requested-With: XMLHttpRequest',
        'X-VPN-Sync-Origin: shop_backend',
        'X-VPN-Sync-Signature: ' . $signature,
    );

    $endpoints = array($primaryEndpoint);
    if(stripos($primaryEndpoint, 'https://') === 0) {
        $endpoints[] = 'http://' . substr($primaryEndpoint, 8);
    }

    $lastCode = 0;
    $lastError = '';
    $lastRaw = '';
    $lastJson = null;
    $success = false;

    foreach($endpoints as $ep) {
        $raw = '';
        $code = 0;
        $terror = '';

        if(function_exists('curl_init')) {
            $ch = curl_init($ep);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
            curl_setopt($ch, CURLOPT_TIMEOUT, 10);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeaders);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $requestPayload);
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
            $raw = curl_exec($ch);
            if($raw === false) {
                $terror = (string)curl_error($ch);
                $raw = '';
            }
            $code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
        } else {
            $ctx = stream_context_create(array('http' => array(
                'method'        => 'POST',
                'header'        => implode("\r\n", $httpHeaders),
                'content'       => $requestPayload,
                'timeout'       => 10,
                'ignore_errors' => true,
            )));
            $rawResp = @file_get_contents($ep, false, $ctx);
            if($rawResp === false) {
                $terror = 'file_get_contents_failed';
                $raw = '';
            } else {
                $raw = (string)$rawResp;
            }
            if(isset($http_response_header) && is_array($http_response_header)) {
                foreach($http_response_header as $hl) {
                    if($code === 0 && preg_match('/^HTTP\/\S+\s+(\d{3})/i', $hl, $m)) {
                        $code = (int)$m[1];
                    }
                }
            }
        }

        $lastCode = $code;
        $lastError = $terror;
        $lastRaw = $raw;

        if($terror === '' && $code >= 200 && $code < 300) {
            $dec = json_decode($raw, true);
            if(is_array($dec)) {
                $lastJson = $dec;
                $isOk = !empty($dec['success'])
                    || strtolower(trim((string)($dec['result'] ?? ''))) === 'success'
                    || strtolower(trim((string)($dec['status'] ?? ''))) === 'success';
                if($isOk) {
                    $success = true;
                    break;
                }
                // API returned JSON but not success – don't retry on fallback endpoint
                break;
            }
        }
    }

    $errLabel = '';
    if(!$success) {
        if($lastError !== '') {
            $errLabel = 'network_error: ' . $lastError;
        } elseif($lastCode === 0) {
            $errLabel = 'no_response';
        } else {
            $errLabel = 'http_' . $lastCode;
            if(is_array($lastJson) && isset($lastJson['error'])) {
                $errLabel .= ' / ' . (string)$lastJson['error'];
            }
        }
    }

    return array(
        'ok'              => $success,
        'endpoint'        => $primaryEndpoint,
        'http_code'       => $lastCode,
        'transport_error' => $lastError,
        'raw_snippet'     => strlen($lastRaw) > 300 ? substr($lastRaw, 0, 300) . '…' : $lastRaw,
        'json'            => $lastJson,
        'error'           => $errLabel,
    );
}

$run_result = null;
$delete_result = null;

$vpn_protocol_options = array(
    'IKEv2-VPN-Client',
    'L2TP-VPN-Client',
    'OpenVPN-VPN-Client',
    'WireGuard-VPN-Client',
    'PPTP-VPN-Client'
);

$selected_vpn_protocol = 'IKEv2-VPN-Client';
$selected_grade = '';
$input_hour_price = 0;
$input_install_price = 0;

$member_options = array();
$selected_mb_id = isset($member['mb_id']) ? trim((string)$member['mb_id']) : '';

if($is_auth) {
    $mb_result = sql_query(" select mb_id, mb_nick from {$g5['member_table']} where mb_id <> '' and (mb_leave_date = '' or mb_leave_date is null) order by mb_id asc ", false);
    if($mb_result) {
        while($mb_row = sql_fetch_array($mb_result)) {
            $member_options[] = $mb_row;
        }
    }
} else {
    $member_options[] = array(
        'mb_id' => $selected_mb_id,
        'mb_nick' => isset($member['mb_nick']) ? $member['mb_nick'] : ''
    );
}

if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['do_bulk_delete_ai']) && $_POST['do_bulk_delete_ai'] === '1') {
    $selected_vpn_protocol = isset($_POST['vpn_protocol']) ? trim((string)$_POST['vpn_protocol']) : 'IKEv2-VPN-Client';
    if(!in_array($selected_vpn_protocol, $vpn_protocol_options, true)) {
        $selected_vpn_protocol = 'IKEv2-VPN-Client';
    }

    $posted_mb_id = isset($_POST['target_mb_id']) ? trim((string)$_POST['target_mb_id']) : '';
    $posted_mb_id = preg_replace('/[^A-Za-z0-9_\-]/', '', $posted_mb_id);

    if($is_auth) {
        if($posted_mb_id === '') {
            alert('삭제할 회원ID를 선택해 주세요.');
        }
        $target_member = sql_fetch(" select mb_id, mb_nick from {$g5['member_table']} where mb_id = '".sql_real_escape_string($posted_mb_id)."' ");
        if(!$target_member || empty($target_member['mb_id'])) {
            alert('선택한 회원ID를 찾을 수 없습니다.');
        }
        $selected_mb_id = $target_member['mb_id'];
    } else {
        $selected_mb_id = isset($member['mb_id']) ? trim((string)$member['mb_id']) : '';
    }

    $confirm_delete = isset($_POST['confirm_delete_text']) ? trim((string)$_POST['confirm_delete_text']) : '';
    if($confirm_delete !== 'DELETEAI') {
        alert('삭제 확인 문자열 DELETEAI 를 입력해 주세요.');
    }

    $aliases = ai_protocol_aliases($selected_vpn_protocol);
    $alias_sql = array();
    foreach($aliases as $a) {
        $alias_sql[] = "'".sql_real_escape_string($a)."'";
    }
    if(!count($alias_sql)) {
        $alias_sql[] = "'".sql_real_escape_string($selected_vpn_protocol)."'";
    }

    $where = array();
    $where[] = "it_spec_sales_type = 'vpn-mall'";
    $where[] = "pt_id = '".sql_real_escape_string($selected_mb_id)."'";
    $where[] = "(it_shop_memo like '[AI_BULK_VPN_TEST]%' OR pt_tag like '%AI_BULK_VPN_TEST%')";
    $where[] = "it_spec_os in (".implode(',', $alias_sql).")";

    $sql_pick = " select it_id from {$g5['g5_shop_item_table']} where ".implode(' and ', $where)." order by it_id asc ";
    $res_pick = sql_query($sql_pick, false);

    $delete_ids = array();
    if($res_pick) {
        while($row = sql_fetch_array($res_pick)) {
            if(!empty($row['it_id'])) $delete_ids[] = $row['it_id'];
        }
    }

    $deleted = array();
    $failed = array();
    $deleted_orders = 0;
    $deleted_vpnid = false;
    $deleted_queues = array();
    $ikev2_delete_results = array();

    if(count($delete_ids) > 0) {
        // Build IN clause for bulk operations
        $in_parts = array();
        foreach($delete_ids as $iid) {
            $in_parts[] = "'" . sql_real_escape_string($iid) . "'";
        }
        $in_clause = implode(',', $in_parts);

        // Step A: Extract VPN targets (server_ip + vpn_user_id) from it_spec_remote_sw
        $vpn_targets  = array();  // [{it_id, it_name, server_ip, vpn_user_id}] – deduped by (server_ip|vpn_user_id)
        $vpn_user_ids = array();
        $target_seen  = array();
        $items_sw_res = sql_query(" SELECT it_id, it_name, it_spec_remote_sw FROM {$g5['g5_shop_item_table']} WHERE it_id IN ({$in_clause}) ", false);
        if($items_sw_res) {
            while($ir = sql_fetch_array($items_sw_res)) {
                $rsw = isset($ir['it_spec_remote_sw']) ? (string)$ir['it_spec_remote_sw'] : '';
                if($rsw === '') continue;
                $rd = json_decode($rsw, true);
                if(!is_array($rd)) continue;
                foreach($rd as $re) {
                    if(!is_array($re)) continue;
                    $server_ip    = '';
                    $vpn_user_id  = '';
                    foreach($re as $k => $v) {
                        if(preg_match('/^RemoteIP__\d+$/', $k)) {
                            $server_ip = trim((string)$v);
                        }
                        if(preg_match('/_ID__\d+$/', $k)) {
                            $vpn_user_id = trim((string)$v);
                        }
                    }
                    if($vpn_user_id !== '') $vpn_user_ids[] = $vpn_user_id;
                    if($server_ip !== '' && $vpn_user_id !== '') {
                        $tkey = $server_ip . '|' . $vpn_user_id;
                        if(!isset($target_seen[$tkey])) {
                            $target_seen[$tkey] = true;
                            $vpn_targets[] = array(
                                'it_id'       => isset($ir['it_id'])   ? (string)$ir['it_id']   : '',
                                'it_name'     => isset($ir['it_name']) ? (string)$ir['it_name'] : '',
                                'server_ip'   => $server_ip,
                                'vpn_user_id' => $vpn_user_id,
                            );
                        }
                    }
                }
            }
        }
        $vpn_user_ids = array_unique($vpn_user_ids);

        // Step B: Collect od_ids linked to these items (for order and vpnid_list deletion)
        $od_ids = array();
        $cart_od_res = sql_query(" SELECT DISTINCT od_id FROM {$g5['g5_shop_cart_table']} WHERE it_id IN ({$in_clause}) AND od_id <> '' ", false);
        if($cart_od_res) {
            while($cr = sql_fetch_array($cart_od_res)) {
                if(!empty($cr['od_id'])) $od_ids[] = $cr['od_id'];
            }
        }
        $od_ids = array_unique($od_ids);

        // Step C: Delete from provisioning queues and history
        $queue_tables = array(
            'app_ikev2_provision_queue',
            'app_ikev2_provision_history',
            'app_ikev2_vpnid_sync_queue',
            'app_ikev2_id_conflict_history',
        );
        foreach($queue_tables as $qtbl) {
            $tbl_exists = sql_fetch(" SHOW TABLES LIKE '".sql_real_escape_string($qtbl)."' ", false);
            if($tbl_exists) {
                sql_query(" DELETE FROM `{$qtbl}` WHERE it_id IN ({$in_clause}) ", false);
                $deleted_queues[] = $qtbl;
            }
        }

        // Step D: Delete from vpnid_list (app profile list)
        $vpnid_tbl = sql_fetch(" SHOW TABLES LIKE 'vpnid_list' ", false);
        if($vpnid_tbl) {
            $vpnid_od_col = sql_fetch(" SHOW COLUMNS FROM vpnid_list LIKE 'od_id' ", false);
            if($vpnid_od_col && !empty($vpnid_od_col['Field']) && count($od_ids) > 0) {
                $od_parts = array();
                foreach($od_ids as $oid) {
                    $od_parts[] = "'" . sql_real_escape_string($oid) . "'";
                }
                sql_query(" DELETE FROM vpnid_list WHERE od_id IN (" . implode(',', $od_parts) . ") ", false);
                $deleted_vpnid = true;
            } elseif(count($vpn_user_ids) > 0) {
                $uid_parts = array();
                foreach($vpn_user_ids as $uid) {
                    $uid_parts[] = "'" . sql_real_escape_string($uid) . "'";
                }
                $vpnid_mb_col = sql_fetch(" SHOW COLUMNS FROM vpnid_list LIKE 'mb_id' ", false);
                if($vpnid_mb_col && !empty($vpnid_mb_col['Field'])) {
                    sql_query(" DELETE FROM vpnid_list WHERE mb_id = '" . sql_real_escape_string($selected_mb_id) . "' AND vpn_user_id IN (" . implode(',', $uid_parts) . ") ", false);
                } else {
                    sql_query(" DELETE FROM vpnid_list WHERE vpn_user_id IN (" . implode(',', $uid_parts) . ") ", false);
                }
                $deleted_vpnid = true;
            }
            // Also clean vpnid_list_log
            $vpnid_log_tbl = sql_fetch(" SHOW TABLES LIKE 'vpnid_list_log' ", false);
            if($vpnid_log_tbl && count($od_ids) > 0) {
                $od_parts = array();
                foreach($od_ids as $oid) {
                    $od_parts[] = "'" . sql_real_escape_string($oid) . "'";
                }
                $vpnid_log_od_col = sql_fetch(" SHOW COLUMNS FROM vpnid_list_log LIKE 'od_id' ", false);
                if($vpnid_log_od_col && !empty($vpnid_log_od_col['Field'])) {
                    sql_query(" DELETE FROM vpnid_list_log WHERE od_id IN (" . implode(',', $od_parts) . ") ", false);
                }
            }
        }

        // Step E: Delete orders where ALL cart items belong to these AI test items
        if(count($od_ids) > 0) {
            $orders_to_delete = array();
            foreach($od_ids as $oid) {
                if($oid === '') continue;
                $safe_oid = sql_real_escape_string($oid);
                $total_cnt = sql_fetch(" SELECT COUNT(*) as cnt FROM {$g5['g5_shop_cart_table']} WHERE od_id = '{$safe_oid}' ", false);
                $ai_cnt   = sql_fetch(" SELECT COUNT(*) as cnt FROM {$g5['g5_shop_cart_table']} WHERE od_id = '{$safe_oid}' AND it_id IN ({$in_clause}) ", false);
                if($total_cnt && $ai_cnt && (int)$total_cnt['cnt'] > 0 && (int)$total_cnt['cnt'] === (int)$ai_cnt['cnt']) {
                    $orders_to_delete[] = $oid;
                }
            }
            if(count($orders_to_delete) > 0) {
                $del_od_parts = array();
                foreach($orders_to_delete as $o) {
                    $del_od_parts[] = "'" . sql_real_escape_string($o) . "'";
                }
                sql_query(" DELETE FROM {$g5['g5_shop_order_table']} WHERE od_id IN (" . implode(',', $del_od_parts) . ") ", false);
                $deleted_orders = count($orders_to_delete);
            }
        }

        // Step F: Delete all cart rows for these items (all statuses, not just '쇼핑')
        sql_query(" DELETE FROM {$g5['g5_shop_cart_table']} WHERE it_id IN ({$in_clause}) ", false);

        // Step G: Delete VPN users from IKEv2 server's ipsec.secrets
        $ikev2_secret = ai_load_shop_sync_secret();
        foreach($vpn_targets as $target) {
            $sip = $target['server_ip'];
            $uid = $target['vpn_user_id'];
            if($ikev2_secret === '') {
                $ikev2_delete_results[] = array(
                    'it_id'       => $target['it_id'],
                    'it_name'     => $target['it_name'],
                    'server_ip'   => $sip,
                    'vpn_user_id' => $uid,
                    'ok'          => false,
                    'http_code'   => 0,
                    'error'       => 'no_shared_secret (IKEV2_SHOP_SYNC_SHARED_SECRET 미설정)',
                    'needs_manual' => true,
                );
                continue;
            }
            $ret = ai_call_ikev2_delete_user($sip, $uid, $selected_mb_id, $ikev2_secret);
            $ikev2_delete_results[] = array(
                'it_id'           => $target['it_id'],
                'it_name'         => $target['it_name'],
                'server_ip'       => $sip,
                'vpn_user_id'     => $uid,
                'ok'              => !empty($ret['ok']),
                'http_code'       => $ret['http_code'],
                'error'           => $ret['error'],
                'transport_error' => $ret['transport_error'],
                'raw_snippet'     => $ret['raw_snippet'],
                'needs_manual'    => empty($ret['ok']),
            );
        }
    }

    // Per-item: delete item relations, options, events, and item itself (with verify)
    foreach($delete_ids as $del_it_id) {
        $safe_id = sql_real_escape_string($del_it_id);
        sql_query(" delete from {$g5['g5_shop_item_relation_table']} where it_id = '{$safe_id}' or it_id2 = '{$safe_id}' ", false);
        sql_query(" delete from {$g5['g5_shop_item_option_table']} where it_id = '{$safe_id}' ", false);
        sql_query(" delete from {$g5['g5_shop_event_item_table']} where it_id = '{$safe_id}' ", false);
        $ok_del = sql_query(" delete from {$g5['g5_shop_item_table']} where it_id = '{$safe_id}' ", false);

        if($ok_del === false) {
            $failed[] = array(
                'it_id' => $del_it_id,
                'error' => function_exists('sql_error_info') ? sql_error_info() : 'delete failed'
            );
        } else {
            $chk = sql_fetch(" select it_id from {$g5['g5_shop_item_table']} where it_id = '{$safe_id}' ", false);
            if($chk && !empty($chk['it_id'])) {
                $failed[] = array(
                    'it_id' => $del_it_id,
                    'error' => 'delete verify failed'
                );
            } else {
                $deleted[] = $del_it_id;
            }
        }
    }

    $ikev2_ok_count     = 0;
    $ikev2_fail_count   = 0;
    $ikev2_manual_items = array();
    foreach($ikev2_delete_results as $ir) {
        if(!empty($ir['ok'])) {
            $ikev2_ok_count++;
        } else {
            $ikev2_fail_count++;
            if(!empty($ir['needs_manual'])) {
                $ikev2_manual_items[] = $ir;
            }
        }
    }

    $delete_result = array(
        'target_mb_id'        => $selected_mb_id,
        'vpn_protocol'        => $selected_vpn_protocol,
        'picked'              => count($delete_ids),
        'deleted'             => count($deleted),
        'failed'              => count($failed),
        'deleted_orders'      => $deleted_orders,
        'deleted_vpnid'       => $deleted_vpnid,
        'deleted_queues'      => $deleted_queues,
        'deleted_ids'         => $deleted,
        'failed_rows'         => $failed,
        'ikev2_delete_results' => $ikev2_delete_results,
        'ikev2_ok_count'      => $ikev2_ok_count,
        'ikev2_fail_count'    => $ikev2_fail_count,
        'ikev2_manual_items'  => $ikev2_manual_items,
        'list_url'            => APMS_PARTNER_URL . '/?ap=list_vpn'
    );

} else if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['do_bulk_create']) && $_POST['do_bulk_create'] === '1') {
    $count = isset($_POST['count']) ? (int)$_POST['count'] : 5;
    if($count < 1) $count = 1;
    if($count > 500) $count = 500;

    $prefix = isset($_POST['prefix']) ? trim((string)$_POST['prefix']) : 'v';
    $prefix = preg_replace('/[^A-Za-z0-9_\-]/', '', $prefix);
    if($prefix === '') $prefix = 'v';

    $selected_vpn_protocol = isset($_POST['vpn_protocol']) ? trim((string)$_POST['vpn_protocol']) : 'IKEv2-VPN-Client';
    if(!in_array($selected_vpn_protocol, $vpn_protocol_options, true)) {
        $selected_vpn_protocol = 'IKEv2-VPN-Client';
    }

    $_vpn_grade_allowed = array('BASIC', 'PLUS', 'PRO', 'ULTRA', 'MAX');
    $selected_grade = isset($_POST['it_spec_grade']) ? strtoupper(trim((string)$_POST['it_spec_grade'])) : '';
    if(!in_array($selected_grade, $_vpn_grade_allowed, true)) $selected_grade = '';

    $input_hour_price = isset($_POST['it_hour_price']) ? (float)$_POST['it_hour_price'] : 0.0;
    if($input_hour_price < 0) $input_hour_price = 0.0;
    if($input_hour_price > 99999) $input_hour_price = 99999.0;

    $input_install_price = isset($_POST['it_install_price']) ? (int)$_POST['it_install_price'] : 0;
    if($input_install_price < 0) $input_install_price = 0;
    if($input_install_price > 99999) $input_install_price = 99999;

    $confirm_text = isset($_POST['confirm_text']) ? trim((string)$_POST['confirm_text']) : '';
    if($confirm_text !== 'CREATE') {
        alert('확인 문자열 CREATE 를 입력해 주세요.');
    }

    $posted_mb_id = isset($_POST['target_mb_id']) ? trim((string)$_POST['target_mb_id']) : '';
    $posted_mb_id = preg_replace('/[^A-Za-z0-9_\-]/', '', $posted_mb_id);

    if($is_auth) {
        if($posted_mb_id === '') {
            alert('생성할 회원ID를 선택해 주세요.');
        }
        $target_member = sql_fetch(" select mb_id, mb_nick from {$g5['member_table']} where mb_id = '".sql_real_escape_string($posted_mb_id)."' ");
        if(!$target_member || empty($target_member['mb_id'])) {
            alert('선택한 회원ID를 찾을 수 없습니다.');
        }
        $selected_mb_id = $target_member['mb_id'];
        $selected_mb_nick = isset($target_member['mb_nick']) ? $target_member['mb_nick'] : '';
    } else {
        $selected_mb_id = isset($member['mb_id']) ? trim((string)$member['mb_id']) : '';
        $selected_mb_nick = isset($member['mb_nick']) ? trim((string)$member['mb_nick']) : '';
    }

    // 기존 VPN 상품을 템플릿으로 사용 (없으면 빈 배열로 시작 — 모든 필수 필드는 아래서 명시적으로 설정)
    $template = sql_fetch(" select * from {$g5['g5_shop_item_table']} where it_spec_sales_type = 'vpn-mall' order by it_time desc limit 1 ");
    if(!$template || empty($template['it_id'])) {
        $template = array();
    }

    // it_id 컬럼 최대 길이 감지(예: varchar(20))
    $it_id_max_len = 20;
    $it_id_col = sql_fetch(" SHOW COLUMNS FROM {$g5['g5_shop_item_table']} LIKE 'it_id' ", false);
    if(isset($it_id_col['Type']) && preg_match('/(?:var)?char\((\d+)\)/i', (string)$it_id_col['Type'], $m)) {
        $detected_len = (int)$m[1];
        if($detected_len > 0) {
            $it_id_max_len = $detected_len;
        }
    }

    // 현재 DB 스키마 기준으로 실제 존재하는 컬럼만 INSERT 대상에 포함
    $item_table_columns = array();
    $item_table_column_list = sql_field_names($g5['g5_shop_item_table']);
    if(is_array($item_table_column_list)) {
        foreach($item_table_column_list as $col_name) {
            $item_table_columns[(string)$col_name] = true;
        }
    }

    $categories = array();
    $cat_result = sql_query(" select ca_id, ca_name from {$g5['g5_shop_category_table']} where ca_id like '3020%' and length(ca_id) = 6 and ca_use = '1' order by ca_order, ca_id ", false);
    if($cat_result) {
        while($row = sql_fetch_array($cat_result)) {
            $categories[] = $row;
        }
    }

    if(!count($categories)) {
        $fallback_ca_id3 = isset($template['ca_id3']) ? (string)$template['ca_id3'] : '302010';
        $categories[] = array('ca_id' => ($fallback_ca_id3 ?: '302010'), 'ca_name' => 'IKEv2-Client');
    }

    $category_map = array();
    foreach($categories as $row_cat) {
        $cat_name = isset($row_cat['ca_name']) ? trim((string)$row_cat['ca_name']) : '';
        $cat_id = isset($row_cat['ca_id']) ? trim((string)$row_cat['ca_id']) : '';
        if($cat_name === '' || $cat_id === '') continue;
        $category_map[strtolower($cat_name)] = $cat_id;
    }

    $selected_ca_id3 = '';
    $protocol_aliases = ai_protocol_aliases($selected_vpn_protocol);
    foreach($protocol_aliases as $alias) {
        $key = strtolower($alias);
        if(isset($category_map[$key])) {
            $selected_ca_id3 = $category_map[$key];
            break;
        }
    }
    if($selected_ca_id3 === '' && isset($template['ca_id3'])) {
        $selected_ca_id3 = trim((string)$template['ca_id3']);
    }
    if($selected_ca_id3 === '') {
        $selected_ca_id3 = '302010';
    }

    // 테스트용 고정 엔드포인트(실제 IKEv2 서버)
    $endpoint_pool = array(
        array('ip' => '183.108.10.158', 'country_name' => 'Korea, Republic of', 'country_code' => 'KR', 'city' => 'Seoul', 'lat' => 37.5665, 'lng' => 126.9780)
    );




    // g5_shop_item NOT NULL DEFAULT-없는 컬럼 기본값 (템플릿이 없을 때 INSERT 실패 방지)
    $base_defaults = array(
        'it_origin_store_from_api'  => '',
        'it_basic'                  => '',
        'it_explan'                 => '',
        'it_explan2'                => '',
        'it_mobile_explan'          => '',
        'it_head_html'              => '',
        'it_tail_html'              => '',
        'it_mobile_head_html'       => '',
        'it_mobile_tail_html'       => '',
        'it_info_value'             => '',
        'it_use_avg'                => '0.0',
        'it_shop_memo'              => '',
        'it_1'                      => '1',
        'pt_explan'                 => '',
        'pt_mobile_explan'          => '',
        'getsitename'               => '',
        'reseller_on'               => '0',
        'market_on'                 => '0',
        'auction_on'                => '0',
        'it_spec_mainboard'         => '',
        'it_spec_ram_type'          => '',
        'it_spec_ssd_type'          => '',
        'it_spec_hdd_type'          => '',
        'it_spec_remote_sw'         => '[]',
        'it_install_price'          => '0',
        'it_spec_from_datetime_org' => '',
        'it_spec_to_datetime_org'   => '',
        'it_is_hour_sale_price'     => '0',
        'rank_of_item_tbl'          => '0',
        'rank_of_item_tbl_percent'  => '0',
        'rank_of_all_db'            => '0',
        'estimated_price_of_item'   => '0',
        'ai_suggested_price'        => '0',
        'it_billing_plan'           => '',
        'it_billing_traffic_cost'   => '0',
        'it_billing_time_cost'      => '0',
    );

    $created_ids = array();
    $failed = array();
    $failed_details = array();

    for($i = 1; $i <= $count; $i++) {
        // 기본값 위에 템플릿 값을 덮어씌움 (템플릿이 없으면 기본값만 사용)
        $base = array_merge($base_defaults, $template);

        $ca_id3 = $selected_ca_id3;
        $protocol = $selected_vpn_protocol;

        $endpoint = isset($endpoint_pool[0]) ? $endpoint_pool[0] : array(
            'ip' => '183.108.10.158',
            'country_name' => 'Korea, Republic of',
            'country_code' => 'KR',
            'city' => 'Seoul',
            'lat' => 37.5665,
            'lng' => 126.9780
        );

        $remote_user = strtolower(ai_rand_str(6));
        $remote_pass = ai_rand_str(10);

        $remote_data = array(
            array(
                'RemoteIP__0' => $endpoint['ip'],
                'RemoteIP_CountryName__0' => $endpoint['country_name'],
                'RemoteIP_CountryCode__0' => $endpoint['country_code'],
                'RemoteIP_City__0' => $endpoint['city'],
                'RemoteIP_Latitude__0' => $endpoint['lat'],
                'RemoteIP_Longitude__0' => $endpoint['lng'],
                'Program__0' => $protocol,
                $protocol . '_ID__0' => $remote_user,
                $protocol . '_PWD__0' => $remote_pass
            )
        );

        $new_it_id = ai_generate_it_id_from_counter($g5['g5_shop_item_table'], $it_id_max_len);
        if($new_it_id === '') {
            $failed[] = 'counter_failed_' . $i;
            $failed_details[] = array(
                'it_id' => 'counter_failed_' . $i,
                'stage' => 'counter',
                'error' => function_exists('sql_error_info') ? sql_error_info() : 'failed to generate it_id from counter',
                'sql' => 'UPDATE/SELECT g5_shop_item_it_id_counter'
            );
            continue;
        }

        $base['it_id'] = $new_it_id;
        $base['pt_num'] = (string)(time() + $i);
        $base['it_time'] = G5_TIME_YMDHIS;
        $base['it_update_time'] = G5_TIME_YMDHIS;

        $base['ca_id'] = substr($ca_id3, 0, 2);
        $base['ca_id2'] = substr($ca_id3, 0, 4);
        $base['ca_id3'] = $ca_id3;

        $base['it_name'] = 'VPN-' . $new_it_id;
        $base['it_basic'] = $protocol . ' 테스트 상품';
        $base['it_explan2'] = 'AI 테스트 자동 등록 데이터입니다. (' . date('Y-m-d H:i:s') . ')';

        $base['it_price'] = (string)($input_hour_price > 0 ? $input_hour_price : (float)random_int(1, 300));
        $base['it_install_price'] = (string)($input_install_price > 0 ? $input_install_price : random_int(0, 50));
        $base['it_stock_qty'] = '99999';
        $base['it_noti_qty'] = '0';
        $base['it_use'] = '1';
        $base['it_soldout'] = '0';
        $base['pt_show'] = '0';
        $base['pt_reserve_use'] = '0';
        $base['pt_reserve'] = '0';
        $base['pt_end'] = '0';
        $base['pt_it'] = '2';

        $base['it_spec_sales_type'] = 'vpn-mall';
        $base['pt_id'] = $selected_mb_id;
        $base['it_spec_partner_id'] = $selected_mb_id;

        $base['it_spec_os'] = $protocol;
        $base['it_spec_mgr_nickname'] = $selected_mb_nick ? $selected_mb_nick : $selected_mb_id;
        $base['it_spec_app_ver'] = 'v0.0.0';
        $base['it_spec_remote_sw'] = json_encode($remote_data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        $base['it_spec_remote_ip_country_code'] = $endpoint['country_code'];
        $base['it_img1'] = ai_pick_protocol_image($protocol);

        // 계약일시 컬럼은 주문 확정 시점에만 채워져야 하므로, 템플릿 값 복사를 방지하기 위해 항상 초기화
        $base['it_spec_from_datetime'] = '';
        $base['it_spec_from_datetime_org'] = '';
        $base['it_spec_to_datetime'] = '';
        $base['it_spec_to_datetime_org'] = '';
        $base['it_spec_buyer_mb_id'] = '';
        $base['it_spec_buyer_mb_name'] = '';

        $base['it_is_hour_sale'] = '1';
        $base['it_is_hour_sale_price'] = $base['it_price'];
        $base['it_buy_min_qty'] = '1';
        $base['it_buy_max_qty'] = '8760';

        $base['it_1'] = '1';
        $base['it_2'] = '1';
        $base['it_3'] = '0';
        $base['it_4'] = '6';
        $base['it_5'] = '20';
        $base['it_6'] = '200';
        $base['it_7'] = '0';
        $base['it_8'] = '0';
        $base['it_9'] = '0';
        $base['it_10'] = '0';
        $base['it_billing_plan'] = 'monthly';
        $base['it_billing_traffic_cost'] = '0';
        $base['it_billing_time_cost'] = '0';

        $base['it_spec_grade'] = $selected_grade;

        $base['it_sum_qty'] = '0';

        $base['it_ip'] = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '';
        $base['it_shop_memo'] = '[AI_BULK_VPN_TEST] protocol=' . $protocol . '; created_at=' . date('Y-m-d H:i:s') . '; batch_no=' . $i;
        $base['pt_tag'] = 'AI_BULK_VPN_TEST,VPN_TEST';

        $set_parts = array();
        foreach($base as $col => $val) {
            if($col === 'it_id') {
                continue;
            }
            if(!isset($item_table_columns[$col])) {
                continue;
            }
            if(is_null($val)) {
                $val = '';
            }
            $set_parts[] = "`{$col}`='" . sql_real_escape_string((string)$val) . "'";
        }

        $sql = " insert into {$g5['g5_shop_item_table']} set `it_id`='" . sql_real_escape_string($new_it_id) . "', " . implode(",\n", $set_parts);
        $ins = sql_query($sql, false);

        if($ins === false) {
            $failed[] = $new_it_id;
            $failed_details[] = array(
                'it_id' => $new_it_id,
                'stage' => 'insert',
                'error' => function_exists('sql_error_info') ? sql_error_info() : 'unknown database error',
                'sql' => substr($sql, 0, 1200)
            );
            continue;
        }

        $ok = sql_fetch(" select it_id from {$g5['g5_shop_item_table']} where it_id = '".sql_real_escape_string($new_it_id)."' ", false);
        if($ok && !empty($ok['it_id'])) {
            $created_ids[] = $new_it_id;
        } else {
            $failed[] = $new_it_id;
            $failed_details[] = array(
                'it_id' => $new_it_id,
                'stage' => 'verify',
                'error' => function_exists('sql_error_info') ? sql_error_info() : 'insert verify failed',
                'sql' => "select it_id from {$g5['g5_shop_item_table']} where it_id = '".sql_real_escape_string($new_it_id)."'"
            );
        }
    }

    $run_result = array(
        'requested' => $count,
        'target_mb_id' => $selected_mb_id,
        'vpn_protocol' => $selected_vpn_protocol,
        'created' => count($created_ids),
        'failed' => count($failed),
        'created_ids' => $created_ids,
        'failed_ids' => $failed,
        'failed_details' => $failed_details,
        'list_url' => APMS_PARTNER_URL . '/?ap=list_vpn'
    );
}
$g5['title'] = 'VPN AI 테스트 상품 일괄 생성·삭제';
include_once('./admin.head.php');
?>
<style>
/* ── AI Bulk 페이지 기본 (라이트) ── */
.aib { max-width: 860px; }

.aib-section {
    border: 1px solid #d0d0d0;
    border-radius: 6px;
    padding: 20px 24px 16px;
    margin-bottom: 20px;
    background: #fff;
}
.aib-section h2,
.aib-section h3 {
    margin: 0 0 6px;
    font-size: 15px;
    font-weight: 700;
    color: #222;
}
.aib-section .aib-desc {
    margin: 0 0 16px;
    font-size: 13px;
    color: #555;
    line-height: 1.5;
}
.aib-section .aib-warn {
    color: #b00020;
    font-weight: 700;
    font-size: 13px;
    margin: 0 0 16px;
}
.aib-row {
    display: flex;
    align-items: center;
    margin-bottom: 12px;
}
.aib-row label {
    flex: 0 0 180px;
    font-size: 13px;
    font-weight: 600;
    padding-right: 12px;
    line-height: 34px;
    color: #333;
}
.aib-row input[type="text"],
.aib-row input[type="number"],
.aib-row select {
    flex: 0 0 320px;
    height: 34px;
    padding: 0 8px;
    font-size: 13px;
    border: 1px solid #bbb;
    border-radius: 4px;
    box-sizing: border-box;
    background: #fff;
    color: #222;
}
.aib-row select { padding: 0 6px; }
.aib-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 16px;
    padding-top: 14px;
    border-top: 1px solid #e8e8e8;
}
.aib-btn {
    height: 36px;
    padding: 0 18px;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    border-radius: 4px;
    border: 1px solid #999;
    background: #f0f0f0;
    color: #333;
}
.aib-btn:hover { background: #e0e0e0; }
.aib-btn-danger {
    background: #a61b29;
    color: #fff !important;
    border-color: #8c1522;
}
.aib-btn-danger:hover { background: #8c1522; }
.aib-link { font-size: 13px; color: #1a6abf; text-decoration: none; }
.aib-link:hover { text-decoration: underline; }
.aib-result h3 { font-size: 14px; margin: 0 0 10px; }
.aib-result p { margin: 4px 0; font-size: 13px; }
.aib .ok { color: #0b7a25; font-weight: 700; }
.aib .warn { color: #b00020; font-weight: 700; }
.aib code { background: #f0f0f0; padding: 1px 5px; border-radius: 3px; font-size: 12px; color: #c7254e; }
.aib .aib-list {
    max-height: 200px;
    overflow: auto;
    border: 1px dashed #ccc;
    padding: 8px 10px;
    background: #fafafa;
    font-size: 12px;
    border-radius: 4px;
    margin-top: 6px;
    white-space: pre;
    color: #333;
}
.aib .aib-list.err { border-color: #d9a3aa; background: #fff7f8; }

/* ── 다크모드 오버라이드 ── */
[data-theme="dark"] .aib-section {
    background: #252526 !important;
    border-color: #454545 !important;
}
[data-theme="dark"] .aib-section h2,
[data-theme="dark"] .aib-section h3 {
    color: #c8c8c8 !important;
}
[data-theme="dark"] .aib-section .aib-desc {
    color: #9a9a9a !important;
}
[data-theme="dark"] .aib-section .aib-warn {
    color: #ff8080 !important;
}
[data-theme="dark"] .aib-row label {
    color: #cccccc !important;
}
[data-theme="dark"] .aib-row input[type="text"],
[data-theme="dark"] .aib-row input[type="number"],
[data-theme="dark"] .aib-row select {
    background: #3c3c3c !important;
    border-color: #555 !important;
    color: #cccccc !important;
}
[data-theme="dark"] .aib-actions {
    border-top-color: #454545 !important;
}
[data-theme="dark"] .aib-btn {
    background: #3c3c3c !important;
    border-color: #555 !important;
    color: #cccccc !important;
}
[data-theme="dark"] .aib-btn:hover {
    background: #4a4a4a !important;
}
[data-theme="dark"] .aib .ok { color: #4adb90 !important; }
[data-theme="dark"] .aib .warn { color: #ff9090 !important; }
[data-theme="dark"] .aib code {
    background: #2d2d2d !important;
    color: #f97583 !important;
}
[data-theme="dark"] .aib .aib-list {
    background: #1e1e1e !important;
    border-color: #454545 !important;
    color: #cccccc !important;
}
[data-theme="dark"] .aib .aib-list.err {
    background: #2d1616 !important;
    border-color: #7a2020 !important;
}
[data-theme="dark"] .aib-result-ok-row { background: #1a2f1a !important; }
[data-theme="dark"] .aib-result-fail-row { background: #2d1616 !important; }
[data-theme="dark"] .aib table th { background: #2d2d2d !important; color: #aaa !important; }
[data-theme="dark"] .aib table td { background: #252526 !important; color: #bbb !important; border-color: #454545 !important; }
[data-theme="dark"] .aib .aib-manual-box {
    background: #2d1616 !important;
    border-color: #7a2020 !important;
}
[data-theme="dark"] .aib .aib-manual-box h4 { color: #ff8080 !important; }
[data-theme="dark"] .aib .aib-manual-box p { color: #aaa !important; }

/* ── 로딩 오버레이 ── */
#aib-loading-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 99999;
    background: rgba(0,0,0,.48);
    flex-direction: column;
    align-items: center;
    justify-content: center;
}
#aib-loading-overlay.active { display: flex; }
.aib-loading-box {
    background: #fff;
    border-radius: 10px;
    padding: 32px 40px 28px;
    text-align: center;
    box-shadow: 0 8px 32px rgba(0,0,0,.22);
    min-width: 260px;
}
.aib-loading-box .aib-spinner {
    width: 44px; height: 44px;
    border: 5px solid #e0e0e0;
    border-top-color: #0e639c;
    border-radius: 50%;
    animation: aib-spin .8s linear infinite;
    margin: 0 auto 16px;
}
@keyframes aib-spin { to { transform: rotate(360deg); } }
.aib-loading-box p {
    margin: 0;
    font-size: 14px;
    font-weight: 600;
    color: #333;
}
.aib-progress-wrap {
    width: 200px;
    height: 6px;
    background: #e0e0e0;
    border-radius: 3px;
    margin: 14px auto 0;
    overflow: hidden;
}
.aib-progress-bar {
    height: 100%;
    width: 0%;
    background: linear-gradient(90deg, #0e639c, #3794ff);
    border-radius: 3px;
    animation: aib-progress 2.4s ease-in-out infinite;
}
@keyframes aib-progress {
    0%   { width: 0%;   margin-left: 0; }
    50%  { width: 70%;  margin-left: 15%; }
    100% { width: 0%;   margin-left: 100%; }
}

/* ── 결과 토스트 ── */
#aib-toast {
    display: none;
    position: fixed;
    top: 18px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 99998;
    min-width: 280px;
    max-width: 480px;
    padding: 13px 20px 13px 16px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    box-shadow: 0 4px 18px rgba(0,0,0,.18);
    cursor: pointer;
    animation: aib-toast-in .3s ease;
}
@keyframes aib-toast-in {
    from { opacity:0; transform: translateX(-50%) translateY(-12px); }
    to   { opacity:1; transform: translateX(-50%) translateY(0); }
}
#aib-toast.ok  { background: #1a7f3c; color: #fff; }
#aib-toast.err { background: #a61b29; color: #fff; }
#aib-toast .aib-toast-close {
    float: right;
    margin-left: 14px;
    opacity: .7;
    font-size: 15px;
    line-height: 1;
}
[data-theme="dark"] .aib-loading-box { background: #252526; }
[data-theme="dark"] .aib-loading-box p { color: #ccc; }
[data-theme="dark"] .aib-loading-box .aib-spinner { border-color: #454545; border-top-color: #3794ff; }
[data-theme="dark"] .aib-progress-wrap { background: #3c3c3c; }
</style>

<!-- 로딩 오버레이 -->
<div id="aib-loading-overlay">
    <div class="aib-loading-box">
        <div class="aib-spinner"></div>
        <p id="aib-loading-msg">처리 중입니다…</p>
        <div class="aib-progress-wrap"><div class="aib-progress-bar"></div></div>
    </div>
</div>
<!-- 결과 토스트 -->
<div id="aib-toast"></div>

<div class="aib">

    <div class="aib-section">
        <h2>VPN AI 테스트 상품 일괄 생성</h2>
        <p class="aib-desc">수동 등록 페이지(<code><?php echo h(APMS_PARTNER_URL.'/?ap=list_vpn'); ?></code>) 테스트용으로 VPN 상품을 대량 생성합니다.</p>
        <p class="aib-warn">주의: 실제 상품 테이블에 저장됩니다. 테스트 환경에서만 사용하세요.</p>
        <form id="aib-form-create" method="post" autocomplete="off">
            <input type="hidden" name="do_bulk_create" value="1">
            <div class="aib-row">
                <label for="count">생성 개수 (1~500)</label>
                <input type="number" id="count" name="count" min="1" max="500" value="5" required>
            </div>
            <div class="aib-row">
                <label for="prefix">상품코드 prefix</label>
                <input type="text" id="prefix" name="prefix" value="v" required>
            </div>
            <div class="aib-row">
                <label for="vpn_protocol">VPN-CLIENT 종류</label>
                <select id="vpn_protocol" name="vpn_protocol" required>
                    <?php foreach($vpn_protocol_options as $opt_protocol) {
                        $p_sel = ($opt_protocol === $selected_vpn_protocol) ? ' selected' : '';
                    ?>
                    <option value="<?php echo h($opt_protocol); ?>"<?php echo $p_sel; ?>><?php echo h($opt_protocol); ?></option>
                    <?php } ?>
                </select>
            </div>
            <div class="aib-row">
                <label for="it_spec_grade">상품 등급</label>
                <select id="it_spec_grade" name="it_spec_grade">
                    <option value=""<?php echo ($selected_grade === '') ? ' selected' : ''; ?>>-- 미지정 --</option>
                    <?php foreach(array('BASIC','PLUS','PRO','ULTRA','MAX') as $gv) { ?>
                    <option value="<?php echo $gv; ?>"<?php echo ($selected_grade === $gv) ? ' selected' : ''; ?>><?php echo $gv; ?></option>
                    <?php } ?>
                </select>
            </div>
            <div class="aib-row">
                <label for="it_hour_price">1시간당 요금 (원)</label>
                <input type="number" id="it_hour_price" name="it_hour_price" min="0" max="99999" step="0.01"
                       value="<?php echo ($input_hour_price > 0) ? rtrim(rtrim(number_format($input_hour_price, 2, '.', ''), '0'), '.') : ''; ?>"
                       placeholder="비워두면 랜덤(1~300)">
            </div>
            <div class="aib-row">
                <label for="it_install_price">개통비 (원)</label>
                <input type="number" id="it_install_price" name="it_install_price" min="0" max="99999"
                       value="<?php echo ($input_install_price > 0) ? (int)$input_install_price : ''; ?>"
                       placeholder="비워두면 랜덤(0~50)">
            </div>
            <div class="aib-row">
                <label for="target_mb_id">생성 대상 회원ID</label>
                <select id="target_mb_id" name="target_mb_id" required>
                    <?php foreach($member_options as $mopt) {
                        $opt_id = isset($mopt['mb_id']) ? (string)$mopt['mb_id'] : '';
                        $opt_nick = isset($mopt['mb_nick']) ? (string)$mopt['mb_nick'] : '';
                        if($opt_id === '') continue;
                        $is_sel = ($opt_id === $selected_mb_id) ? ' selected' : '';
                    ?>
                    <option value="<?php echo h($opt_id); ?>"<?php echo $is_sel; ?>><?php echo h($opt_id . ($opt_nick ? ' (' . $opt_nick . ')' : '')); ?></option>
                    <?php } ?>
                </select>
            </div>
            <div class="aib-row">
                <label for="confirm_text">확인 문자열 입력</label>
                <input type="text" id="confirm_text" name="confirm_text" placeholder="CREATE" required>
            </div>
            <div class="aib-actions">
                <button type="submit" class="aib-btn">일괄 생성 실행</button>
                <a href="<?php echo h(APMS_PARTNER_URL.'/?ap=list_vpn'); ?>" class="aib-link">VPN 목록으로 이동</a>
            </div>
        </form>
    </div>

    <div class="aib-section">
        <h3>AI 테스트 상품 일괄 삭제</h3>
        <p class="aib-desc">아래 조건(회원ID + VPN-CLIENT + AI 마킹)으로 생성된 테스트 상품을 삭제합니다.</p>
        <form id="aib-form-delete" method="post" autocomplete="off">
            <input type="hidden" name="do_bulk_delete_ai" value="1">
            <div class="aib-row">
                <label for="vpn_protocol_del">VPN-CLIENT 종류</label>
                <select id="vpn_protocol_del" name="vpn_protocol" required>
                    <?php foreach($vpn_protocol_options as $opt_protocol) {
                        $p_sel = ($opt_protocol === $selected_vpn_protocol) ? ' selected' : '';
                    ?>
                    <option value="<?php echo h($opt_protocol); ?>"<?php echo $p_sel; ?>><?php echo h($opt_protocol); ?></option>
                    <?php } ?>
                </select>
            </div>
            <div class="aib-row">
                <label for="target_mb_id_del">삭제 대상 회원ID</label>
                <select id="target_mb_id_del" name="target_mb_id" required>
                    <?php foreach($member_options as $mopt) {
                        $opt_id = isset($mopt['mb_id']) ? (string)$mopt['mb_id'] : '';
                        $opt_nick = isset($mopt['mb_nick']) ? (string)$mopt['mb_nick'] : '';
                        if($opt_id === '') continue;
                        $is_sel = ($opt_id === $selected_mb_id) ? ' selected' : '';
                    ?>
                    <option value="<?php echo h($opt_id); ?>"<?php echo $is_sel; ?>><?php echo h($opt_id . ($opt_nick ? ' (' . $opt_nick . ')' : '')); ?></option>
                    <?php } ?>
                </select>
            </div>
            <div class="aib-row">
                <label for="confirm_delete_text">삭제 확인 문자열</label>
                <input type="text" id="confirm_delete_text" name="confirm_delete_text" placeholder="DELETEAI" required>
            </div>
            <div class="aib-actions">
                <button type="submit" class="aib-btn aib-btn-danger">AI 테스트 상품 일괄 삭제 실행</button>
            </div>
        </form>
    </div>

    <?php if(is_array($run_result)) { ?>
    <div id="aib-result-create" class="aib-section aib-result">
        <h3>생성 실행 결과</h3>
        <p>대상 회원ID: <strong><?php echo h($run_result['target_mb_id']); ?></strong> &nbsp;|&nbsp; VPN-CLIENT: <strong><?php echo h($run_result['vpn_protocol']); ?></strong></p>
        <p>요청: <strong><?php echo (int)$run_result['requested']; ?></strong>개 &nbsp;/&nbsp; 생성 성공: <strong class="ok"><?php echo (int)$run_result['created']; ?></strong>개 &nbsp;/&nbsp; 실패: <strong class="warn"><?php echo (int)$run_result['failed']; ?></strong>개</p>
        <p><a href="<?php echo h($run_result['list_url']); ?>" class="aib-link">VPN 목록 페이지 열기</a></p>
        <?php if(!empty($run_result['created_ids'])) { ?>
        <h4 style="margin:12px 0 4px;font-size:13px;">생성된 it_id</h4>
        <div class="aib-list"><?php echo h(implode("\n", $run_result['created_ids'])); ?></div>
        <?php } ?>
        <?php if(!empty($run_result['failed_ids'])) { ?>
        <h4 style="margin:12px 0 4px;font-size:13px;">실패한 it_id</h4>
        <div class="aib-list err"><?php echo h(implode("\n", $run_result['failed_ids'])); ?></div>
        <?php } ?>
        <?php if(!empty($run_result['failed_details'])) { ?>
        <h4 style="margin:12px 0 4px;font-size:13px;">실패 상세</h4>
        <div class="aib-list err"><?php
            $detail_lines = array();
            foreach($run_result['failed_details'] as $d) {
                $detail_lines[] = '[it_id] ' . (isset($d['it_id']) ? $d['it_id'] : '');
                $detail_lines[] = '  stage: ' . (isset($d['stage']) ? $d['stage'] : '');
                $detail_lines[] = '  error: ' . (isset($d['error']) ? $d['error'] : '');
                $detail_lines[] = '  sql: ' . (isset($d['sql']) ? $d['sql'] : '');
                $detail_lines[] = '---';
            }
            echo h(implode("\n", $detail_lines));
        ?></div>
        <?php } ?>
    </div>
    <?php } ?>

    <?php if(is_array($delete_result)) { ?>
    <div id="aib-result-delete" class="aib-section aib-result">
        <h3>삭제 실행 결과</h3>
        <p>대상 회원ID: <strong><?php echo h($delete_result['target_mb_id']); ?></strong> &nbsp;|&nbsp; VPN-CLIENT: <strong><?php echo h($delete_result['vpn_protocol']); ?></strong></p>
        <p>상품 조회: <strong><?php echo (int)$delete_result['picked']; ?></strong>개 &nbsp;/&nbsp; 삭제 성공: <strong class="ok"><?php echo (int)$delete_result['deleted']; ?></strong>개 &nbsp;/&nbsp; 실패: <strong class="warn"><?php echo (int)$delete_result['failed']; ?></strong>개</p>
        <p>주문 삭제: <strong class="ok"><?php echo (int)$delete_result['deleted_orders']; ?></strong>건 &nbsp;|&nbsp; vpnid_list: <strong><?php echo $delete_result['deleted_vpnid'] ? '<span class="ok">정리 시도됨</span>' : '해당 없음'; ?></strong></p>
        <?php if(!empty($delete_result['deleted_queues'])) { ?>
        <p>정리된 큐 테이블: <strong class="ok"><?php echo h(implode(', ', $delete_result['deleted_queues'])); ?></strong></p>
        <?php } ?>

        <?php $ir_total = count($delete_result['ikev2_delete_results']); if($ir_total > 0) { ?>
        <h4 style="margin:14px 0 6px;font-size:13px;">IKEv2 서버 ipsec.secrets 삭제 결과</h4>
        <p style="margin:0 0 8px;">대상: <strong><?php echo $ir_total; ?></strong>건 &nbsp;/&nbsp; 성공: <strong class="ok"><?php echo (int)$delete_result['ikev2_ok_count']; ?></strong>건 &nbsp;/&nbsp; 실패: <strong class="warn"><?php echo (int)$delete_result['ikev2_fail_count']; ?></strong>건</p>
        <table style="border-collapse:collapse;width:100%;font-size:12px;margin-bottom:8px;">
        <thead><tr style="background:#f0f0f0;">
            <th style="border:1px solid #ccc;padding:5px 8px;text-align:left;">it_id</th>
            <th style="border:1px solid #ccc;padding:5px 8px;text-align:left;">VPN User ID</th>
            <th style="border:1px solid #ccc;padding:5px 8px;text-align:left;">서버 IP</th>
            <th style="border:1px solid #ccc;padding:5px 8px;text-align:center;">결과</th>
            <th style="border:1px solid #ccc;padding:5px 8px;text-align:left;">오류/응답</th>
        </tr></thead>
        <tbody>
        <?php foreach($delete_result['ikev2_delete_results'] as $dr) { ?>
        <tr class="<?php echo !empty($dr['ok']) ? 'aib-result-ok-row' : 'aib-result-fail-row'; ?>" style="background:<?php echo !empty($dr['ok']) ? '#f0fff4' : '#fff7f8'; ?>">
            <td style="border:1px solid #ccc;padding:4px 8px;"><?php echo h($dr['it_id']); ?></td>
            <td style="border:1px solid #ccc;padding:4px 8px;font-family:monospace;"><?php echo h($dr['vpn_user_id']); ?></td>
            <td style="border:1px solid #ccc;padding:4px 8px;"><?php echo h($dr['server_ip']); ?></td>
            <td style="border:1px solid #ccc;padding:4px 8px;text-align:center;">
                <?php if(!empty($dr['ok'])) { ?><span class="ok">&#10003; 성공</span><?php } else { ?><span class="warn">&#10005; 실패</span><?php } ?>
            </td>
            <td style="border:1px solid #ccc;padding:4px 8px;font-size:11px;color:#555;">
                <?php
                if(!empty($dr['ok'])) {
                    echo 'HTTP ' . (int)$dr['http_code'];
                } else {
                    echo h($dr['error'] !== '' ? $dr['error'] : ('HTTP '.(int)$dr['http_code']));
                    if(!empty($dr['raw_snippet'])) echo '<br><span style="color:#999">' . h(substr($dr['raw_snippet'],0,120)) . '</span>';
                }
                ?>
            </td>
        </tr>
        <?php } ?>
        </tbody>
        </table>
        <?php } ?>

        <?php if(!empty($delete_result['ikev2_manual_items'])) { ?>
        <div class="aib-manual-box" style="border:2px solid #a61b29;background:#fff7f8;padding:12px 14px;margin-top:10px;border-radius:5px;">
            <h4 style="color:#a61b29;margin:0 0 8px;font-size:13px;">&#9888; 수동 삭제 필요 보고서</h4>
            <p style="margin:0 0 8px;font-size:12px;">아래 VPN 계정은 IKEv2 서버에서 자동 삭제에 실패했습니다. <code>ipsec.secrets</code>에서 수동으로 삭제하거나 서버 정상화 후 재시도해 주세요.</p>
            <table style="border-collapse:collapse;width:100%;font-size:12px;">
            <thead><tr style="background:#fdd;">
                <th style="border:1px solid #c99;padding:4px 8px;text-align:left;">서버 IP</th>
                <th style="border:1px solid #c99;padding:4px 8px;text-align:left;">VPN User ID</th>
                <th style="border:1px solid #c99;padding:4px 8px;text-align:left;">it_id</th>
                <th style="border:1px solid #c99;padding:4px 8px;text-align:left;">실패 원인</th>
            </tr></thead>
            <tbody>
            <?php foreach($delete_result['ikev2_manual_items'] as $mi) { ?>
            <tr>
                <td style="border:1px solid #c99;padding:4px 8px;"><?php echo h($mi['server_ip']); ?></td>
                <td style="border:1px solid #c99;padding:4px 8px;font-family:monospace;font-weight:700;"><?php echo h($mi['vpn_user_id']); ?></td>
                <td style="border:1px solid #c99;padding:4px 8px;"><?php echo h($mi['it_id']); ?></td>
                <td style="border:1px solid #c99;padding:4px 8px;color:#a00;"><?php echo h($mi['error']); ?></td>
            </tr>
            <?php } ?>
            </tbody>
            </table>
            <p style="margin:8px 0 0;font-size:11px;color:#666;">수동 삭제 예시: <code>grep -v "^&lt;VPN_USER_ID&gt; " /etc/ipsec.secrets &gt; /tmp/s.new &amp;&amp; mv /tmp/s.new /etc/ipsec.secrets &amp;&amp; ipsec rereadall</code></p>
        </div>
        <?php } ?>

        <p style="margin-top:12px;"><a href="<?php echo h($delete_result['list_url']); ?>" class="aib-link">VPN 목록 페이지 열기</a></p>

        <?php if(!empty($delete_result['deleted_ids'])) { ?>
        <h4 style="margin:12px 0 4px;font-size:13px;">삭제된 it_id</h4>
        <div class="aib-list"><?php echo h(implode("\n", $delete_result['deleted_ids'])); ?></div>
        <?php } ?>
        <?php if(!empty($delete_result['failed_rows'])) { ?>
        <h4 style="margin:12px 0 4px;font-size:13px;">상품 삭제 실패 상세</h4>
        <div class="aib-list err"><?php
            $del_fail_lines = array();
            foreach($delete_result['failed_rows'] as $fr) {
                $del_fail_lines[] = '[it_id] '.(isset($fr['it_id']) ? $fr['it_id'] : '');
                $del_fail_lines[] = '  error: '.(isset($fr['error']) ? $fr['error'] : '');
                $del_fail_lines[] = '---';
            }
            echo h(implode("\n", $del_fail_lines));
        ?></div>
        <?php } ?>
    </div>
    <?php } ?>
</div>
<script>
(function() {
    var overlay  = document.getElementById('aib-loading-overlay');
    var loadMsg  = document.getElementById('aib-loading-msg');
    var toast    = document.getElementById('aib-toast');

    /* ── 폼 제출 시 로딩 오버레이 표시 ── */
    function attachLoading(formId, msg) {
        var form = document.getElementById(formId);
        if (!form) return;
        form.addEventListener('submit', function() {
            if (loadMsg) loadMsg.textContent = msg;
            if (overlay) overlay.classList.add('active');
        });
    }
    attachLoading('aib-form-create', '상품 생성 중입니다…  잠시 기다려 주세요.');
    attachLoading('aib-form-delete', '상품 삭제 중입니다…  잠시 기다려 주세요.');

    /* ── 페이지 로드 후 결과 토스트 + 스크롤 ── */
    var resultCreate = document.getElementById('aib-result-create');
    var resultDelete = document.getElementById('aib-result-delete');
    var resultEl     = resultCreate || resultDelete;

    if (resultEl && toast) {
        var isCreate = !!resultCreate;
        /* PHP가 출력한 결과에서 성공/실패 수 읽기 */
        var okEl   = resultEl.querySelector('strong.ok');
        var warnEl = resultEl.querySelector('strong.warn');
        var okCnt  = okEl   ? parseInt(okEl.textContent,   10) : 0;
        var warnCnt= warnEl ? parseInt(warnEl.textContent, 10) : 0;

        var icon    = warnCnt > 0 ? '⚠ ' : '✔ ';
        var action  = isCreate ? '생성' : '삭제';
        var msg     = icon + action + ' 완료 — 성공 ' + okCnt + '건' + (warnCnt > 0 ? ', 실패 ' + warnCnt + '건' : '');
        var cls     = warnCnt > 0 ? 'err' : 'ok';

        toast.className = cls;
        toast.innerHTML = msg + '<span class="aib-toast-close" title="닫기">✕</span>';
        toast.style.display = 'block';

        toast.querySelector('.aib-toast-close').addEventListener('click', function(e) {
            e.stopPropagation();
            toast.style.display = 'none';
        });
        toast.addEventListener('click', function() {
            resultEl.scrollIntoView({ behavior: 'smooth', block: 'start' });
        });

        /* 결과 섹션으로 자동 스크롤 */
        setTimeout(function() {
            resultEl.scrollIntoView({ behavior: 'smooth', block: 'start' });
        }, 120);

        /* 5초 후 토스트 자동 닫기 */
        setTimeout(function() { toast.style.display = 'none'; }, 5000);
    }
})();
</script>
<?php include_once('./admin.tail.php'); ?>
