<?php
$sub_menu = '400911';
include_once('./_common.php');
auth_check($auth[$sub_menu], 'r');

// ── POST 처리: od_id + mb_id 단위로 모든 대기 요청을 일괄 처리 ──────────
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $od_id_post  = trim($_POST['od_id'] ?? '');
    $mb_id_post  = trim($_POST['mb_id'] ?? '');
    $act         = preg_replace('/[^a-z_]/i', '', $_POST['act'] ?? '');
    $adm_memo    = $_POST['adm_memo'] ?? '';
    $back_status = preg_replace('/[^가-힣a-z]/u', '', $_POST['back_status'] ?? '');

    if ($od_id_post !== '' && $mb_id_post !== '' && in_array($act, ['complete', 'hold', 'cancel'])) {
        $safe_od   = sql_real_escape_string($od_id_post);
        $safe_mb2  = sql_real_escape_string($mb_id_post);
        $safe_memo = sql_real_escape_string($adm_memo);
        $now       = date('Y-m-d H:i:s');
        $label_map = ['complete' => '처리완료', 'hold' => '보류', 'cancel' => '취소'];
        $new_status = $label_map[$act];

        $hold_reason_raw = trim($_POST['hold_reason'] ?? '');
        if ($act === 'hold' && $hold_reason_raw !== '') {
            $safe_reason = mb_substr(preg_replace('/[\r\n<>]/', '', $hold_reason_raw), 0, 60);
            $adm_memo    = '[보류 사유: ' . $safe_reason . ']' .
                           (trim($adm_memo) !== '' ? "\n" . $adm_memo : '');
            $safe_memo   = sql_real_escape_string($adm_memo);
        }

        // 해당 주문의 모든 '대기' 상태 요청을 일괄 처리
        sql_query("UPDATE g5_withdraw_notify
                   SET wn_status='{$new_status}', wn_admin_memo='{$safe_memo}',
                       wn_processed_at='{$now}', wn_processed_by='{$member['mb_id']}'
                   WHERE od_id='{$safe_od}' AND mb_id='{$safe_mb2}' AND wn_status='대기'", false);

        header('Location: withdraw_notify_list.php?wn_status=' . urlencode($back_status));
        exit;
    }
}

$g5['title'] = '출금신고 (포인트출금) 내역';
include_once(G5_ADMIN_PATH . '/admin.head.php');

$status_filter = isset($_GET['wn_status']) ? preg_replace('/[^가-힣a-z]/u', '', $_GET['wn_status']) : '';
$page          = max(1, (int)($_GET['page'] ?? 1));
$rows_per_page = 20;
$offset        = ($page - 1) * $rows_per_page;

// ── 상태 필터 HAVING 조건 ────────────────────────────────────────────────
$having = '';
if ($status_filter === '대기') {
    $having = "HAVING SUM(CASE WHEN wn.wn_status='대기' THEN 1 ELSE 0 END) > 0";
} elseif ($status_filter === '처리완료') {
    $having = "HAVING SUM(CASE WHEN wn.wn_status='대기' THEN 1 ELSE 0 END) = 0
                   AND SUM(CASE WHEN wn.wn_status='처리완료' THEN 1 ELSE 0 END) > 0";
} elseif ($status_filter === '보류') {
    $having = "HAVING SUM(CASE WHEN wn.wn_status='대기' THEN 1 ELSE 0 END) = 0
                   AND SUM(CASE WHEN wn.wn_status='보류' THEN 1 ELSE 0 END) > 0";
} elseif ($status_filter === '취소') {
    $having = "HAVING SUM(CASE WHEN wn.wn_status='대기' THEN 1 ELSE 0 END) = 0
                   AND SUM(CASE WHEN wn.wn_status='처리완료' THEN 1 ELSE 0 END) = 0
                   AND SUM(CASE WHEN wn.wn_status='보류' THEN 1 ELSE 0 END) = 0";
}

// GROUP_CONCAT 최대 길이 확장
sql_query("SET SESSION group_concat_max_len=65536", false);

// ── 전체 건수 (그룹 기준) ────────────────────────────────────────────────
$cnt_res  = sql_query("SELECT COUNT(*) AS cnt FROM (
    SELECT wn.od_id FROM g5_withdraw_notify wn
    GROUP BY wn.od_id, wn.mb_id {$having}
) AS cnt_sub", false);
$cnt_row  = sql_fetch_array($cnt_res);
$total_cnt   = (int)($cnt_row['cnt'] ?? 0);
$total_pages = max(1, ceil($total_cnt / $rows_per_page));

// ── 메인 쿼리: od_id 기준 1행 ────────────────────────────────────────────
$list = [];
$res  = sql_query("SELECT
    sub.*,
    o.od_status AS order_status, o.od_time, o.od_cart_price,
    o.od_withdraw_fee, o.od_withdraw_type,
    o.od_withdraw_bank_name, o.od_withdraw_bank_account,
    o.od_withdraw_bank_account_name, o.od_withdraw_bank_country,
    o.od_withdraw_pay, o.od_withdraw_pay_id,
    o.od_withdraw_coin, o.od_withdraw_coin_id,
    o.od_fx_type, o.od_fx_amount,
    m.mb_name, m.mb_nick, m.mb_email, m.mb_hp, m.mb_datetime,
    m.mb_today_login, m.mb_point,
    m.mb_intercept_date, m.mb_leave_date,
    (SELECT COUNT(*) FROM g5_shoppoint_order4withdraw so
     WHERE so.mb_id=sub.mb_id AND so.od_status NOT IN ('취소','주문취소')) AS mb_ord_cnt,
    (SELECT COALESCE(SUM(so2.od_cart_price),0) FROM g5_shoppoint_order4withdraw so2
     WHERE so2.mb_id=sub.mb_id AND so2.od_status NOT IN ('취소','주문취소')) AS mb_ord_total,
    (SELECT COUNT(*) FROM g5_login gl WHERE gl.mb_id=sub.mb_id) AS mb_login_cnt
FROM (
    SELECT
        wn.od_id, wn.mb_id,
        COUNT(wn.wn_id)  AS total_count,
        SUM(CASE WHEN wn.wn_status='대기' THEN 1 ELSE 0 END) AS pending_count,
        CASE
            WHEN SUM(CASE WHEN wn.wn_status='대기' THEN 1 ELSE 0 END) > 0 THEN '대기'
            WHEN SUM(CASE WHEN wn.wn_status='보류' THEN 1 ELSE 0 END) > 0 THEN '보류'
            WHEN SUM(CASE WHEN wn.wn_status='처리완료' THEN 1 ELSE 0 END) > 0 THEN '처리완료'
            ELSE '취소'
        END AS effective_status,
        MAX(wn.wn_created_at) AS latest_created_at,
        MAX(CASE WHEN wn.wn_processed_at > '0000-00-00 00:00:00' THEN wn.wn_processed_at ELSE NULL END) AS latest_processed_at,
        MAX(CASE WHEN wn.wn_processed_at > '0000-00-00 00:00:00' THEN wn.wn_processed_by ELSE NULL END) AS latest_processed_by,
        MAX(CASE WHEN wn.wn_admin_memo <> '' THEN wn.wn_admin_memo ELSE NULL END) AS latest_admin_memo,
        GROUP_CONCAT(
            CONCAT_WS('||',
                wn.wn_id, wn.wn_created_at,
                REPLACE(IFNULL(wn.wn_message,''), '^^', ' '),
                wn.wn_status,
                REPLACE(IFNULL(wn.wn_admin_memo,''), '^^', ' ')
            )
            ORDER BY wn.wn_id DESC SEPARATOR '^^'
        ) AS req_data
    FROM g5_withdraw_notify wn
    GROUP BY wn.od_id, wn.mb_id
    {$having}
) sub
LEFT JOIN g5_shoppoint_order4withdraw o ON o.od_id = sub.od_id
LEFT JOIN g5_member m ON m.mb_id = sub.mb_id
ORDER BY sub.pending_count DESC, sub.latest_created_at DESC
LIMIT {$offset}, {$rows_per_page}", false);
while ($row = sql_fetch_array($res)) $list[] = $row;

$status_labels = ['' => '전체', '대기' => '대기', '처리완료' => '처리완료', '보류' => '보류', '취소' => '취소'];
$status_colors = ['대기' => '#E87020', '처리완료' => '#2E8B57', '보류' => '#888', '취소' => '#CC3333'];

function wn_elapsed_str($datetime) {
    $ts = strtotime($datetime);
    if (!$ts) return '';
    $diff = time() - $ts;
    if ($diff < 60)        return '방금';
    if ($diff < 3600)      return (int)($diff/60) . '분 전';
    if ($diff < 86400)     return (int)($diff/3600) . '시간 전';
    if ($diff < 86400*30)  return (int)($diff/86400) . '일 전';
    if ($diff < 86400*365) return (int)($diff/86400/30) . '개월 전';
    return (int)($diff/86400/365) . '년 전';
}
function wn_fmt_amount($val) {
    if ((float)$val == (int)(float)$val) return number_format((int)(float)$val);
    return rtrim(rtrim(number_format((float)$val, 4), '0'), '.');
}
?>
<style>
.dn-table { width:100%; border-collapse:collapse; font-size:13px; }
.dn-table th { background:#2d2d2d; color:#cccccc; padding:8px 6px; border-bottom:1px solid #454545; text-align:left; }
.dn-table td { padding:8px 6px; border-bottom:1px solid #454545; vertical-align:top; color:#cccccc; transition:background .28s ease; }
.dn-table tr:hover td { background:#3c3c3c !important; }
.badge { display:inline-block; padding:2px 8px; border-radius:10px; font-size:11px; font-weight:bold; }
.btn-sm { padding:4px 11px; font-size:12px; border:none; border-radius:4px; cursor:pointer; }
.btn-complete { background:#2E8B57; color:#fff; }
.btn-hold     { background:#555; color:#fff; }
.btn-cancel   { background:#993333; color:#fff; }
/* 중복 경고 */
.dup-warn {
    display:inline-flex; align-items:center; gap:4px;
    background:#7a1a0022; border:1px solid #cc440077; border-radius:4px;
    color:#ff8888; font-size:11px; font-weight:bold; padding:3px 8px;
    margin-bottom:6px;
}
/* 요청 내역 목록 */
.req-list { display:flex; flex-direction:column; gap:6px; }
.req-item {
    background:#252526; border-radius:4px; padding:6px 8px;
    border-left:3px solid #454545; font-size:12px;
}
.req-item.req-pending { border-left-color:#E87020; }
.req-item.req-done    { border-left-color:#2E8B57; opacity:.75; }
.req-item.req-hold    { border-left-color:#888; opacity:.75; }
.req-item.req-cancel  { border-left-color:#CC3333; opacity:.75; }
.req-item-header { display:flex; align-items:center; gap:6px; margin-bottom:3px; flex-wrap:wrap; }
.req-item-num    { color:#666; font-size:10px; }
.req-item-time   { color:#7a9ab0; font-size:11px; }
.req-item-status { font-size:10px; font-weight:bold; padding:1px 5px; border-radius:3px; }
.req-msg         { color:#cccccc; word-break:break-all; line-height:1.5; }
.req-admin-memo  { color:#3794ff; font-size:11px; margin-top:3px; }
.req-no-msg      { color:#555; font-style:italic; }
/* 일괄처리 안내 */
.bulk-hint {
    font-size:10px; color:#7a9ab0; margin-bottom:5px; line-height:1.5;
}
/* filter bar */
.filter-bar { margin-bottom:12px; }
.filter-bar a {
    margin-right:8px; padding:4px 14px; border-radius:14px; text-decoration:none;
    background:#3c3c3c; color:#cccccc; font-size:12px; border:1px solid #454545;
    display:inline-block; transition:background .15s,color .15s;
}
.filter-bar a:hover  { background:#094771; color:#cccccc; border-color:#0e639c; text-decoration:none; }
.filter-bar a.active { background:#094771; color:#fff; border-color:#0e639c; font-weight:bold; }
/* manual */
.dn-manual-wrap { margin-bottom:14px; }
.dn-manual-toggle { background:#3c3c3c; color:#cccccc; border:1px solid #454545;
    padding:5px 14px; border-radius:6px; font-size:12px; cursor:pointer; margin-bottom:6px; }
.dn-manual-toggle:hover { background:#094771; }
#dn-manual-body { background:#252526; border:1px solid #454545; border-radius:8px; padding:14px 16px; margin-top:4px; }
.dn-manual-table { width:100%; border-collapse:collapse; font-size:12px; }
.dn-manual-table th { background:#2d2d2d; color:#888; padding:6px 8px; border-bottom:1px solid #454545; text-align:left; }
.dn-manual-table td { padding:6px 8px; border-bottom:1px solid #3c3c3c; color:#cccccc; vertical-align:top; }
.dn-manual-table tr:last-child td { border-bottom:none; }
.mn-badge { display:inline-block; padding:2px 8px; border-radius:4px; font-size:11px; font-weight:bold; white-space:nowrap; }
.mn-complete { background:#2E8B5722; color:#4de080; border:1px solid #2E8B57; }
.mn-hold     { background:#55555522; color:#bbbbbb; border:1px solid #888; }
.mn-cancel   { background:#99333322; color:#ff9090; border:1px solid #993333; }
.mn-none     { color:#666; }
.mn-note     { color:#888; font-size:11px; margin-top:8px; margin-bottom:0; line-height:1.6; }
/* sticky 5컬럼 */
.dn-table-wrap { overflow-x:auto; -webkit-overflow-scrolling:touch; }
.dn-table      { min-width:980px; table-layout:fixed; }
.dn-table tbody td { background:#1e1e1e; }
.dn-table th:nth-child(1), .dn-table td:nth-child(1) { width:178px; position:sticky; left:0; z-index:2; }
.dn-table th:nth-child(1) { background:#2d2d2d; box-shadow:3px 0 7px rgba(0,0,0,.4); }
.dn-table td:nth-child(1) { background:#1e1e1e; box-shadow:3px 0 7px rgba(0,0,0,.4); }
.dn-table th:nth-child(2), .dn-table td:nth-child(2) { width:160px; }
.dn-table th:nth-child(3), .dn-table td:nth-child(3) { width:230px; word-break:break-all; }
.dn-table th:nth-child(4), .dn-table td:nth-child(4) { width:80px; }
.dn-table th:nth-child(5), .dn-table td:nth-child(5) { width:220px; position:sticky; right:0; z-index:2; }
.dn-table th:nth-child(5) { background:#2d2d2d; box-shadow:-3px 0 7px rgba(0,0,0,.4); }
.dn-table td:nth-child(5) { background:#1e1e1e; box-shadow:-3px 0 7px rgba(0,0,0,.4); }
.dn-table tbody tr:hover td:nth-child(1),
.dn-table tbody tr:hover td:nth-child(5) { background:#3c3c3c !important; }
/* 처리 */
.adm-memo-wrap { margin-bottom:5px; }
.adm-memo-hint { font-size:10px; color:#888; display:block; margin-bottom:3px; }
.adm-memo-wrap input[type=text] { width:160px; font-size:11px; padding:3px 5px;
    background:#252526; border:1px solid #454545; color:#cccccc; border-radius:3px; }
.btn-row { display:flex; gap:4px; flex-wrap:wrap; }
/* 회원 */
.mb-cell { cursor:default; }
#mb-floating-tip { display:none; position:fixed; z-index:9999;
    background:#252526; border:1px solid #454545; border-radius:8px; padding:10px 14px;
    min-width:290px; font-size:12px; color:#cccccc; box-shadow:0 6px 24px rgba(0,0,0,.65); }
.mb-tr { display:flex; align-items:center; gap:6px; padding:4px 0; border-bottom:1px solid #3c3c3c; }
.mb-tr:last-child { border-bottom:none; }
.mb-tl { color:#888; font-size:11px; min-width:82px; flex-shrink:0; }
.mb-tv { flex:1; word-break:break-all; }
.mb-cp { cursor:pointer; color:#3794ff; font-size:10px; padding:1px 5px;
    border:1px solid #454545; border-radius:2px; background:transparent; flex-shrink:0; }
.mb-cp:hover { background:#094771; }
/* 주문 셀 */
.col-oi { vertical-align:top; }
.oi-top { display:flex; align-items:baseline; gap:5px; flex-wrap:wrap; margin-bottom:4px; }
.oi-num { color:#666; font-size:11px; }
.oi-od  { color:#3794ff; font-size:12px; overflow:hidden; text-overflow:ellipsis;
    white-space:nowrap; max-width:140px; direction:rtl; unicode-bidi:plaintext; text-align:left; }
.oi-os  { color:#666; font-size:10px; padding:1px 5px; background:rgba(255,255,255,.06); border-radius:3px; }
.oi-dt  { color:#888; font-size:11px; margin-top:4px; }
.th-sub { font-size:10px; color:#aaa; font-weight:normal; }
/* 검색 */
.dn-search-row th { padding:4px 6px !important; background:#2d2d2d !important; border-bottom:2px solid #2d2d2d !important; }
.dn-search-row th:nth-child(1),
.dn-search-row th:nth-child(5) { background:#2d2d2d !important; }
.dn-sf { width:100%; box-sizing:border-box; background:#3c3c3c; border:1px solid #454545;
    border-radius:4px; color:#cccccc; font-size:11px; padding:3px 6px; outline:none; }
.dn-sf::placeholder { color:#666; }
.dn-sf:focus { border-color:#0e639c; background:#094771; }
/* 정렬 */
#dn-hdr th[data-sort] { cursor:pointer; user-select:none; }
#dn-hdr th[data-sort]:hover { background:#094771 !important; }
.sort-ic { font-size:10px; color:#888; margin-left:3px; }

/* ── 라이트 모드 ── */
[data-theme="light"] .dn-table th { background:#2a5080; color:#fff; border-bottom-color:#1e3a6a; }
[data-theme="light"] .dn-table td { color:#333; border-bottom-color:#d0dde8; }
[data-theme="light"] .dn-table tbody td { background:#fff; }
[data-theme="light"] .dn-table tr:hover td { background:#d8eaf8 !important; }
[data-theme="light"] .dn-table th:nth-child(1) { background:#2a5080; }
[data-theme="light"] .dn-table td:nth-child(1) { background:#fff; }
[data-theme="light"] .dn-table th:nth-child(5) { background:#2a5080; }
[data-theme="light"] .dn-table td:nth-child(5) { background:#fff; }
[data-theme="light"] .dn-table tbody tr:hover td:nth-child(1),
[data-theme="light"] .dn-table tbody tr:hover td:nth-child(5) { background:#d8eaf8 !important; }
[data-theme="light"] .filter-bar a { background:#e8f0f8; color:#336699; border-color:#b0c8e0; }
[data-theme="light"] .filter-bar a:hover  { background:#c8e0f8; border-color:#80aacc; }
[data-theme="light"] .filter-bar a.active { background:#2a5080; color:#fff; }
[data-theme="light"] .req-item { background:#f0f5fa; }
[data-theme="light"] .req-msg { color:#333; }
[data-theme="light"] .req-admin-memo { color:#1a5a9a; }
[data-theme="light"] .dup-warn { background:#ffe8e8; border-color:#cc4444; color:#aa1111; }
[data-theme="light"] .dn-search-row th,
[data-theme="light"] .dn-search-row th:nth-child(1),
[data-theme="light"] .dn-search-row th:nth-child(5) { background:#dce8f4 !important; border-bottom-color:#a0bcd8 !important; }
[data-theme="light"] .dn-sf { background:#fff !important; border-color:#aabccc !important; color:#333 !important; }
[data-theme="light"] .dn-sf::placeholder { color:#aaa !important; }
[data-theme="light"] .adm-memo-wrap input[type=text] { background:#fff !important; border-color:#aabccc !important; color:#333 !important; }
[data-theme="light"] .bulk-hint { color:#4a6a8a; }
[data-theme="light"] .oi-od { color:#1a5a9a !important; }
</style>
<script>
var _tip=null, _tipHide=null;
function showMbTip(ev,el){
    clearTimeout(_tipHide);
    if(!_tip){_tip=document.getElementById('mb-floating-tip');
        _tip.onmouseenter=function(){clearTimeout(_tipHide);};
        _tip.onmouseleave=function(){_tipHide=setTimeout(function(){_tip.style.display='none';},200);};}
    var d=el.dataset;
    var rows=[
        ['아이디',d.mbId,true],['이름',d.mbName,true],['닉네임',d.mbNick,true],
        ['이메일',d.mbEmail,true],['전화번호',d.mbHp,true],
        ['가입일시',d.mbDt,false],['마지막로그인',d.mbLogin,false],
        ['로그인 횟수',d.mbLoginCnt+'회',false],['출금 횟수',d.mbOrdCnt+'건',false],
        ['출금 총액',d.mbOrdTotal+' P',false],['포인트 잔액',d.mbPoint+' P',false],
    ];
    if(d.mbIntercept&&d.mbIntercept>'00000000') rows.push(['⛔ 차단일','<span style="color:#e05555">'+d.mbIntercept+'</span>',false]);
    if(d.mbLeave&&d.mbLeave>'00000000') rows.push(['탈퇴일','<span style="color:#888">'+d.mbLeave+'</span>',false]);
    var skip={'0회':1,'0건':1,'0 P':1,'':1};
    var html='';
    for(var i=0;i<rows.length;i++){
        var v=rows[i][1]||'';
        if(skip[v]) continue;
        var plain=v.replace(/<[^>]+>/g,'');
        var cp=rows[i][2]?'<button class="mb-cp" onclick="cpTip(this,\''+plain.replace(/\\/g,'\\\\').replace(/'/g,"\\'")+'\')" onmousedown="event.stopPropagation()">복사</button>':'';
        html+='<div class="mb-tr"><span class="mb-tl">'+rows[i][0]+'</span><span class="mb-tv">'+v+'</span>'+cp+'</div>';
    }
    _tip.innerHTML=html; _tip.style.display='block';
    _tip.style.left=Math.min(ev.clientX+14,window.innerWidth-310)+'px';
    _tip.style.top=Math.min(ev.clientY+14,window.innerHeight-360)+'px';
}
function qHideMbTip(){_tipHide=setTimeout(function(){if(_tip)_tip.style.display='none';},200);}
function cpTip(btn,text){
    var done=function(){btn.textContent='✓';setTimeout(function(){btn.textContent='복사';},1200);};
    if(navigator.clipboard){navigator.clipboard.writeText(text).then(done);}
    else{var t=document.createElement('textarea');t.value=text;document.body.appendChild(t);t.select();document.execCommand('copy');document.body.removeChild(t);done();}
}

var _wnConfirmForm=null, _wnActionMode='', _wnSelectedReason='';
var _WN_HOLD_REASONS=[
    {id:'processing_delay',label:'처리 지연',        desc:'출금 처리가 지연되고 있습니다.'},
    {id:'info_check',      label:'정보 확인 필요',    desc:'출금 계좌/지갑 정보 추가 확인이 필요합니다.'},
    {id:'security_check',  label:'보안 검토 중',      desc:'보안 검토 절차가 진행 중입니다.'},
    {id:'other',           label:'기타 (직접 작성)',  desc:''}
];

function _wnSetMemo(memoVal){
    var el=document.getElementById('wn-confirm-memo');
    if(memoVal&&memoVal.trim()!==''){el.style.display='block';el.querySelector('.dn-confirm-memo-text').textContent=memoVal.trim();}
    else{el.style.display='none';}
}
function showWnConfirm(form,actionLabel,memoVal){
    _wnConfirmForm=form; _wnActionMode='simple';
    document.getElementById('wn-reason-section').style.display='none';
    document.getElementById('wn-custom-msg-section').style.display='none';
    document.getElementById('wn-confirm-title').textContent=actionLabel+' 처리하시겠습니까?';
    _wnSetMemo(memoVal);
    document.getElementById('wn-confirm-modal').style.display='flex';
    return false;
}
function showWnHoldConfirm(form,memoVal){
    _wnConfirmForm=form; _wnActionMode='hold'; _wnSelectedReason='';
    document.getElementById('wn-confirm-memo').style.display='none';
    document.getElementById('wn-custom-msg-section').style.display='none';
    document.getElementById('wn-custom-msg-input').value='';
    var list=document.getElementById('wn-reason-list'); list.innerHTML='';
    _WN_HOLD_REASONS.forEach(function(r,idx){
        var lbl=document.createElement('label'); lbl.className='dn-reason-row';
        var radio=document.createElement('input');
        radio.type='radio'; radio.name='wn_hold_reason'; radio.value=r.id;
        if(idx===0){radio.checked=true; _wnSelectedReason=r.id;}
        radio.addEventListener('change',(function(rid,isOther){
            return function(){_wnSelectedReason=rid;
                document.getElementById('wn-custom-msg-section').style.display=isOther?'block':'none';
                if(isOther)setTimeout(function(){document.getElementById('wn-custom-msg-input').focus();},60);};
        })(r.id,r.id==='other'));
        lbl.appendChild(radio);
        var sp=document.createElement('span');
        sp.innerHTML='<strong>'+r.label+'</strong>'+(r.desc?'<em>'+r.desc+'</em>':'');
        lbl.appendChild(sp); list.appendChild(lbl);
    });
    document.getElementById('wn-reason-section').style.display='block';
    document.getElementById('wn-confirm-title').textContent='출금확인 보류 처리하시겠습니까?';
    document.getElementById('wn-confirm-modal').style.display='flex';
    return false;
}
function wnConfirmOk(){
    document.getElementById('wn-confirm-modal').style.display='none';
    if(_wnConfirmForm){
        if(_wnActionMode==='hold'){
            var hr=_wnConfirmForm.querySelector('[name=hold_reason]');
            if(hr){var rObj=_WN_HOLD_REASONS.find(function(x){return x.id===_wnSelectedReason;});
                hr.value=(_wnSelectedReason==='other')?(document.getElementById('wn-custom-msg-input').value||'').trim():(rObj?rObj.label:(_wnSelectedReason||''));}
        }
        _wnConfirmForm.submit(); _wnConfirmForm=null;
    }
    _wnActionMode=''; _wnSelectedReason='';
}
function wnConfirmCancel(){
    document.getElementById('wn-confirm-modal').style.display='none';
    document.getElementById('wn-reason-section').style.display='none';
    document.getElementById('wn-custom-msg-section').style.display='none';
    _wnConfirmForm=null; _wnActionMode=''; _wnSelectedReason='';
}
function _wnFilterTable(){
    var filters=[];
    document.querySelectorAll('.dn-sf').forEach(function(inp){
        var v=inp.value.trim().toLowerCase();
        if(v) filters.push({col:parseInt(inp.dataset.col),val:v});
    });
    document.querySelectorAll('.dn-table tbody tr').forEach(function(tr){
        if(!filters.length){tr.style.display='';return;}
        var ok=filters.every(function(f){var c=tr.cells[f.col];return c&&c.textContent.toLowerCase().indexOf(f.val)!==-1;});
        tr.style.display=ok?'':'none';
    });
}
document.addEventListener('DOMContentLoaded',function(){
    document.querySelectorAll('.dn-sf').forEach(function(inp){inp.addEventListener('input',_wnFilterTable);});
    document.querySelectorAll('#dn-hdr th[data-sort]').forEach(function(th){
        th.addEventListener('click',function(){
            var col=parseInt(th.dataset.sort);
            var tbody=document.querySelector('.dn-table tbody'); if(!tbody) return;
            var rows=Array.from(tbody.querySelectorAll('tr'));
            var asc=(th.dataset.sortDir!=='asc'); th.dataset.sortDir=asc?'asc':'desc';
            document.querySelectorAll('#dn-hdr th[data-sort]').forEach(function(t){t.classList.remove('sort-asc','sort-desc');var ic=t.querySelector('.sort-ic');if(ic)ic.textContent='⇅';});
            th.classList.add(asc?'sort-asc':'sort-desc'); var ic=th.querySelector('.sort-ic');if(ic)ic.textContent=asc?'↑':'↓';
            rows.sort(function(a,b){
                var ta=(a.cells[col]?a.cells[col].textContent:'').trim().toLowerCase();
                var tb=(b.cells[col]?b.cells[col].textContent:'').trim().toLowerCase();
                var na=parseFloat(ta.replace(/[^0-9.-]/g,'')),nb=parseFloat(tb.replace(/[^0-9.-]/g,''));
                if(!isNaN(na)&&!isNaN(nb)) return asc?na-nb:nb-na;
                return asc?ta.localeCompare(tb,'ko'):tb.localeCompare(ta,'ko');
            });
            rows.forEach(function(r){tbody.appendChild(r);});
        });
    });
});
</script>
<style>
#wn-confirm-modal { display:none; position:fixed; inset:0; z-index:99999;
    background:rgba(0,0,0,.55); align-items:center; justify-content:center; }
.dn-confirm-box { background:#252526; border:1px solid #454545; border-radius:10px;
    padding:24px 28px; min-width:300px; max-width:420px; width:90%; box-shadow:0 8px 32px rgba(0,0,0,.7); }
.dn-confirm-header { display:flex; align-items:center; gap:8px; color:#cccccc; font-size:13px; margin-bottom:14px; }
.dn-confirm-title { color:#cccccc; font-size:15px; margin-bottom:10px; line-height:1.5; }
.dn-confirm-memo-wrap { background:#252526; border:1px solid #454545; border-radius:6px;
    padding:9px 12px; margin-bottom:14px; font-size:13px; }
.dn-confirm-memo-label { font-size:11px; color:#888; margin-bottom:4px; }
.dn-confirm-memo-text  { color:#cccccc; word-break:break-all; }
.dn-confirm-btns { display:flex; justify-content:flex-end; gap:10px; margin-top:18px; }
.dn-confirm-btns button { padding:7px 22px; border:none; border-radius:6px; font-size:14px; cursor:pointer; font-weight:bold; }
.dn-btn-ok { background:#0e639c; color:#fff; } .dn-btn-ok:hover { background:#1177bb; }
.dn-btn-no { background:#454545; color:#cccccc; } .dn-btn-no:hover { background:#3c3c3c; }
.dn-reason-section { border-bottom:1px solid #454545; margin-bottom:14px; padding-bottom:14px; }
.dn-reason-label   { font-size:12px; color:#3794ff; font-weight:bold; margin-bottom:8px; }
.dn-reason-list    { display:flex; flex-direction:column; gap:5px; }
.dn-reason-row     { display:flex; align-items:flex-start; gap:8px; cursor:pointer; padding:5px 8px; border-radius:5px; }
.dn-reason-row:hover { background:rgba(255,255,255,.05); }
.dn-reason-row input[type=radio] { margin-top:3px; accent-color:#0e639c; cursor:pointer; flex-shrink:0; }
.dn-reason-row span { font-size:12.5px; color:#cccccc; line-height:1.5; }
.dn-reason-row span strong { color:#cccccc; }
.dn-reason-row span em { color:#888; font-style:normal; font-size:11px; display:block; }
.dn-custom-msg-section { margin-top:10px; border-top:1px solid #454545; padding-top:10px; }
.dn-custom-msg-label { font-size:12px; color:#3794ff; font-weight:bold; margin-bottom:6px; }
.dn-custom-msg-input { width:100%; box-sizing:border-box; background:#252526; border:1px solid #454545;
    border-radius:4px; color:#cccccc; font-size:13px; padding:6px 10px; resize:vertical; font-family:inherit; }
.dn-custom-msg-input:focus { outline:none; border-color:#0e639c; }
.dn-custom-msg-input::placeholder { color:#666; }
</style>
<div id="wn-confirm-modal">
  <div class="dn-confirm-box">
    <div class="dn-confirm-header">
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#cccccc" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"/></svg>
      vpnlink.kr
    </div>
    <div class="dn-confirm-title" id="wn-confirm-title"></div>
    <div class="dn-confirm-memo-wrap" id="wn-confirm-memo" style="display:none">
      <div class="dn-confirm-memo-label">📱 앱 전송 메시지</div>
      <div class="dn-confirm-memo-text"></div>
    </div>
    <div class="dn-reason-section" id="wn-reason-section" style="display:none">
      <div class="dn-reason-label">📋 보류 사유 선택</div>
      <div class="dn-reason-list" id="wn-reason-list"></div>
    </div>
    <div id="wn-custom-msg-section" style="display:none">
      <div class="dn-custom-msg-label">✏️ 직접 입력</div>
      <textarea id="wn-custom-msg-input" class="dn-custom-msg-input" rows="3" placeholder="앱에 전달할 메시지를 입력하세요..."></textarea>
    </div>
    <div class="dn-confirm-btns">
      <button class="dn-btn-no" onclick="wnConfirmCancel()">취소</button>
      <button class="dn-btn-ok" onclick="wnConfirmOk()">확인</button>
    </div>
  </div>
</div>
<div id="mb-floating-tip"></div>

<h2><?= htmlspecialchars($g5['title']) ?> (<?= $total_cnt ?>건)</h2>

<div class="dn-manual-wrap">
  <button class="dn-manual-toggle" onclick="var b=document.getElementById('dn-manual-body');b.style.display=b.style.display==='none'?'block':'none';this.textContent=b.style.display==='none'?'📋 버튼 기능 안내 ▾':'📋 버튼 기능 안내 ▲'">📋 버튼 기능 안내 ▾</button>
  <div id="dn-manual-body" style="display:none">
    <table class="dn-manual-table">
      <thead><tr><th>버튼</th><th>역할</th><th>처리 범위</th><th>앱 메시지</th></tr></thead>
      <tbody>
        <tr><td><span class="mn-badge mn-complete">처리완료</span></td><td>출금 확인 처리 완료</td><td>해당 주문의 모든 대기 요청 일괄 처리</td><td>메모 입력 시 앱 전달</td></tr>
        <tr><td><span class="mn-badge mn-hold">보류</span></td><td>추가 확인 필요, 대기</td><td>해당 주문의 모든 대기 요청 일괄 처리</td><td>메모 내용 앱 전달 (회색)</td></tr>
        <tr><td><span class="mn-badge mn-cancel">취소</span></td><td>요청 거절/취소 처리</td><td>해당 주문의 모든 대기 요청 일괄 처리</td><td>메모 내용 앱 전달 (빨간색)</td></tr>
      </tbody>
    </table>
    <p class="mn-note">💡 동일 주문의 여러 요청은 <b>1행으로 통합</b>됩니다. 처리 버튼은 해당 주문의 모든 대기 요청을 한 번에 처리하므로 중복 이체 사고를 방지합니다.</p>
  </div>
</div>

<div class="filter-bar">
<?php foreach ($status_labels as $k => $v): ?>
  <a href="?wn_status=<?= urlencode($k) ?>" class="<?= $status_filter === $k ? 'active' : '' ?>"><?= $v ?></a>
<?php endforeach; ?>
</div>

<div class="dn-table-wrap">
<table class="dn-table">
<thead>
<tr id="dn-hdr">
  <th data-sort="0">주문 정보 <span class="sort-ic">⇅</span></th>
  <th data-sort="1">출금신청 내역<br><span class="th-sub">(금액 · 수수료 · 방식)</span></th>
  <th>요청 내역<br><span class="th-sub">(요청 건수 · 사용자 메시지)</span></th>
  <th data-sort="3">상태 <span class="sort-ic">⇅</span></th>
  <th>처리 (앱 피드백)</th>
</tr>
<tr class="dn-search-row">
  <th><input class="dn-sf" data-col="0" placeholder="주문번호 · 회원"></th>
  <th><input class="dn-sf" data-col="1" placeholder="금액 · 방식 · 계좌"></th>
  <th><input class="dn-sf" data-col="2" placeholder="요청 내용"></th>
  <th><input class="dn-sf" data-col="3" placeholder="상태"></th>
  <th></th>
</tr>
</thead>
<tbody>
<?php if (empty($list)): ?>
<tr><td colspan="5" style="text-align:center;padding:20px;color:#667788">내역이 없습니다.</td></tr>
<?php else: ?>
<?php foreach ($list as $r):
    $eff_status  = $r['effective_status'];
    $color       = $status_colors[$eff_status] ?? '#888';
    $total_cnt_r = (int)($r['total_count']   ?? 1);
    $pend_cnt    = (int)($r['pending_count'] ?? 0);

    // 요청 목록 파싱 (GROUP_CONCAT 결과)
    $requests = [];
    foreach (explode('^^', $r['req_data'] ?? '') as $req_str) {
        if ($req_str === '') continue;
        $parts = explode('||', $req_str, 5);
        $requests[] = [
            'wn_id'      => $parts[0] ?? '',
            'created_at' => $parts[1] ?? '',
            'message'    => $parts[2] ?? '',
            'status'     => $parts[3] ?? '',
            'admin_memo' => $parts[4] ?? '',
        ];
    }

    // 출금 방식/목적지
    $wtype = trim($r['od_withdraw_type'] ?? '');
    if ($wtype === 'COIN') {
        $dest_label = '코인'; $dest_info = htmlspecialchars($r['od_withdraw_coin'] ?? '') . ' / ' . htmlspecialchars($r['od_withdraw_coin_id'] ?? '');
    } elseif ($wtype === 'PAY') {
        $dest_label = '페이';  $dest_info = htmlspecialchars($r['od_withdraw_pay'] ?? '') . ' / ' . htmlspecialchars($r['od_withdraw_pay_id'] ?? '');
    } else {
        $dest_label = '계좌';
        $bank_country = trim($r['od_withdraw_bank_country'] ?? '');
        $dest_info = htmlspecialchars($r['od_withdraw_bank_name'] ?? '');
        if ($bank_country !== '' && $bank_country !== 'KR') $dest_info .= ' <small style="color:#7a9ab0">(' . htmlspecialchars($bank_country) . ')</small>';
        $dest_info .= '<br>' . htmlspecialchars($r['od_withdraw_bank_account'] ?? '') . '<br>' . htmlspecialchars($r['od_withdraw_bank_account_name'] ?? '');
    }

    $fx_type   = strtoupper(trim($r['od_fx_type'] ?? ''));
    $currency  = (strlen($fx_type) >= 6) ? substr($fx_type, 3, 3) : 'KRW';
    $fx_amount = (float)($r['od_fx_amount'] ?? 0);

    $is_blocked    = !empty($r['mb_intercept_date']) && $r['mb_intercept_date'] > '00000000';
    $is_leaved     = !empty($r['mb_leave_date'])     && $r['mb_leave_date']     > '00000000';
    $mb_id_color   = $is_blocked ? '#e05555' : ($is_leaved ? '#888' : '#cccccc');
    $mb_dt_safe    = (substr($r['mb_datetime'] ?? '', 0, 4) > '0000') ? htmlspecialchars(substr($r['mb_datetime'], 0, 16)) : '';
    $mb_login_safe = (substr($r['mb_today_login'] ?? '', 0, 4) > '0000') ? htmlspecialchars(substr($r['mb_today_login'], 0, 16)) : '';

    $row_id = 'wn_' . md5($r['od_id'] . $r['mb_id']);
?>
<tr>
  <td class="col-oi">
    <div class="oi-top">
      <a href="orderlist4shoppoint.php?sel_field=od_id&search=<?= urlencode($r['od_id']) ?>" class="oi-od"><?= htmlspecialchars($r['od_id']) ?></a>
      <?php if (!empty($r['order_status'])): ?><span class="oi-os"><?= htmlspecialchars($r['order_status']) ?></span><?php endif; ?>
    </div>
    <div class="mb-cell"
         onmouseenter="showMbTip(event,this)" onmouseleave="qHideMbTip()"
         data-mb-id="<?= htmlspecialchars($r['mb_id']) ?>"
         data-mb-name="<?= htmlspecialchars($r['mb_name'] ?? '') ?>"
         data-mb-nick="<?= htmlspecialchars($r['mb_nick'] ?? '') ?>"
         data-mb-email="<?= htmlspecialchars($r['mb_email'] ?? '') ?>"
         data-mb-hp="<?= htmlspecialchars($r['mb_hp'] ?? '') ?>"
         data-mb-dt="<?= $mb_dt_safe ?>"
         data-mb-login="<?= $mb_login_safe ?>"
         data-mb-login-cnt="<?= (int)($r['mb_login_cnt'] ?? 0) ?>"
         data-mb-ord-cnt="<?= (int)($r['mb_ord_cnt'] ?? 0) ?>"
         data-mb-ord-total="<?= number_format((int)($r['mb_ord_total'] ?? 0)) ?>"
         data-mb-point="<?= number_format((int)($r['mb_point'] ?? 0)) ?>"
         data-mb-intercept="<?= htmlspecialchars($r['mb_intercept_date'] ?? '') ?>"
         data-mb-leave="<?= htmlspecialchars($r['mb_leave_date'] ?? '') ?>"
    >
      <b style="color:<?= $mb_id_color ?>"><?= htmlspecialchars($r['mb_id']) ?></b>
      <?php if (!empty($r['mb_name']) && $r['mb_name'] !== $r['mb_id']): ?><br><small style="color:#8a9eb0"><?= htmlspecialchars($r['mb_name']) ?></small><?php endif; ?>
      <?php if (!empty($r['mb_nick']) && $r['mb_nick'] !== ($r['mb_name'] ?? '') && $r['mb_nick'] !== $r['mb_id']): ?><br><small style="color:#6a8898"><?= htmlspecialchars($r['mb_nick']) ?></small><?php endif; ?>
      <?php if ($is_blocked): ?><br><small style="color:#e05555;font-size:10px">⛔ 차단</small>
      <?php elseif ($is_leaved): ?><br><small style="color:#888;font-size:10px">탈퇴</small><?php endif; ?>
    </div>
    <div class="oi-dt"><?= substr($r['latest_created_at'], 0, 16) ?> <small style="color:#888;font-size:11px">(<?= wn_elapsed_str($r['latest_created_at']) ?>)</small></div>
  </td>
  <td>
    <b style="color:#cccccc"><?= number_format((int)($r['od_cart_price'] ?? 0)) ?> P</b>
    <?php if ((int)($r['od_withdraw_fee'] ?? 0) > 0): ?>
      <br><small style="color:#888">수수료 <?= number_format((int)$r['od_withdraw_fee']) ?> P</small>
      <br><small style="color:#3794ff">실지급 <?= number_format((int)($r['od_cart_price'] ?? 0) - (int)($r['od_withdraw_fee'] ?? 0)) ?> P</small>
    <?php endif; ?>
    <?php if ($fx_amount > 0 && $currency !== 'KRW'): ?>
      <br><small style="color:#e8c060">= <?= wn_fmt_amount($fx_amount) ?> <?= htmlspecialchars($currency) ?></small>
    <?php endif; ?>
    <br><small style="color:#7a9ab0">[<?= htmlspecialchars($dest_label) ?>]</small>
    <br><small style="color:#aaa;word-break:break-all"><?= $dest_info ?></small>
  </td>
  <td>
    <?php if ($total_cnt_r > 1 && $pend_cnt > 1): ?>
    <div class="dup-warn">⚠ 동일 주문 <?= $pend_cnt ?>건 대기 중 — 버튼 1회 클릭으로 일괄 처리됩니다</div>
    <?php elseif ($total_cnt_r > 1): ?>
    <div style="font-size:11px;color:#888;margin-bottom:4px">총 <?= $total_cnt_r ?>건 요청 (<?= $pend_cnt ?>건 대기)</div>
    <?php endif; ?>
    <div class="req-list">
    <?php foreach ($requests as $idx => $req):
        $rstat  = $req['status'];
        $rcls   = ($rstat === '대기') ? 'req-pending' : (($rstat === '처리완료') ? 'req-done' : (($rstat === '보류') ? 'req-hold' : 'req-cancel'));
        $rcolor = $status_colors[$rstat] ?? '#888';
    ?>
      <div class="req-item <?= $rcls ?>">
        <div class="req-item-header">
          <span class="req-item-num">#<?= $total_cnt_r - $idx ?></span>
          <span class="req-item-time"><?= htmlspecialchars(substr($req['created_at'], 0, 16)) ?></span>
          <span class="req-item-status" style="background:<?= $rcolor ?>22;color:<?= $rcolor ?>;border:1px solid <?= $rcolor ?>"><?= htmlspecialchars($rstat) ?></span>
        </div>
        <?php if ($req['message'] !== ''): ?>
          <div class="req-msg"><?= nl2br(htmlspecialchars($req['message'])) ?></div>
        <?php else: ?>
          <div class="req-no-msg">(메시지 없음)</div>
        <?php endif; ?>
        <?php if ($req['admin_memo'] !== ''): ?>
          <div class="req-admin-memo">📬 <?= htmlspecialchars($req['admin_memo']) ?></div>
        <?php endif; ?>
      </div>
    <?php endforeach; ?>
    </div>
  </td>
  <td>
    <span class="badge" style="background:<?= $color ?>22;color:<?= $color ?>;border:1px solid <?= $color ?>">
      <?= htmlspecialchars($eff_status) ?></span>
    <?php if ($r['latest_processed_at']): ?>
      <br><small style="color:#556677"><?= substr($r['latest_processed_at'], 0, 16) ?><br><?= htmlspecialchars($r['latest_processed_by'] ?? '') ?></small>
    <?php endif; ?>
  </td>
  <td>
    <?php if ($pend_cnt > 0): ?>
    <div class="adm-memo-wrap">
      <span class="adm-memo-hint">📱 아래 메시지가 앱에서 고객에게 표시됩니다</span>
      <input type="text" id="adm_memo_<?= $row_id ?>"
             value="<?= htmlspecialchars($r['latest_admin_memo'] ?? '') ?>"
             placeholder="고객에게 전달할 메시지 (선택)">
    </div>
    <?php if ($pend_cnt > 1): ?>
    <div class="bulk-hint">⚡ <?= $pend_cnt ?>건 대기 요청을 한 번에 처리합니다</div>
    <?php endif; ?>
    <div class="btn-row">
      <form method="post" style="display:contents"
            onsubmit="var _m=document.getElementById('adm_memo_<?= $row_id ?>').value;this.querySelector('[name=adm_memo]').value=_m;return showWnConfirm(this,'처리완료',_m);">
        <input type="hidden" name="od_id" value="<?= htmlspecialchars($r['od_id']) ?>">
        <input type="hidden" name="mb_id" value="<?= htmlspecialchars($r['mb_id']) ?>">
        <input type="hidden" name="act" value="complete">
        <input type="hidden" name="adm_memo" value="">
        <input type="hidden" name="back_status" value="<?= htmlspecialchars($status_filter) ?>">
        <button class="btn-sm btn-complete">처리완료</button>
      </form>
      <form method="post" style="display:contents"
            onsubmit="var _m=document.getElementById('adm_memo_<?= $row_id ?>').value;this.querySelector('[name=adm_memo]').value=_m;return showWnHoldConfirm(this,_m);">
        <input type="hidden" name="od_id" value="<?= htmlspecialchars($r['od_id']) ?>">
        <input type="hidden" name="mb_id" value="<?= htmlspecialchars($r['mb_id']) ?>">
        <input type="hidden" name="act" value="hold">
        <input type="hidden" name="adm_memo" value="">
        <input type="hidden" name="hold_reason" value="">
        <input type="hidden" name="back_status" value="<?= htmlspecialchars($status_filter) ?>">
        <button class="btn-sm btn-hold">보류</button>
      </form>
      <form method="post" style="display:contents"
            onsubmit="var _m=document.getElementById('adm_memo_<?= $row_id ?>').value;this.querySelector('[name=adm_memo]').value=_m;return showWnConfirm(this,'취소',_m);">
        <input type="hidden" name="od_id" value="<?= htmlspecialchars($r['od_id']) ?>">
        <input type="hidden" name="mb_id" value="<?= htmlspecialchars($r['mb_id']) ?>">
        <input type="hidden" name="act" value="cancel">
        <input type="hidden" name="adm_memo" value="">
        <input type="hidden" name="back_status" value="<?= htmlspecialchars($status_filter) ?>">
        <button class="btn-sm btn-cancel">취소</button>
      </form>
    </div>
    <?php else: ?>
      <span style="color:#aaa;font-size:12px">처리됨<br><?= htmlspecialchars(substr($r['latest_processed_at'] ?? '', 0, 16)) ?></span>
    <?php endif; ?>
  </td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>

<?php if ($total_pages > 1): ?>
<div style="margin-top:12px;text-align:center">
<?php for ($p = 1; $p <= $total_pages; $p++): ?>
  <a href="?wn_status=<?= urlencode($status_filter) ?>&page=<?= $p ?>"
     style="margin:0 3px;<?= $p === $page ? 'font-weight:bold;color:#fff' : 'color:#cccccc' ?>"><?= $p ?></a>
<?php endfor; ?>
</div>
<?php endif; ?>

<?php include_once(G5_ADMIN_PATH . '/admin.tail.php'); ?>
