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

include_once(G5_PATH.'/mylib/ikev2_provision.lib.php');

auth_check($auth[$sub_menu], 'r');

$g5['title'] = 'IKEv2 서버별 사용자 비교';

$server_name = isset($_GET['server_name']) ? trim((string)$_GET['server_name']) : '';
$limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 5000;
if ($limit <= 0) {
    $limit = 5000;
}
if ($limit > 20000) {
    $limit = 20000;
}

$server_list = array();
$server_seen = array();

$res_vpnid = sql_query("SELECT DISTINCT `server_name` AS server_name FROM `vpnid_list` WHERE TRIM(`server_name`) <> '' ORDER BY `server_name` ASC", false);
if ($res_vpnid) {
    for ($i = 0; $row = sql_fetch_array($res_vpnid); $i++) {
        $name = trim((string)($row['server_name'] ?? ''));
        if ($name === '' || isset($server_seen[$name])) {
            continue;
        }
        $server_seen[$name] = true;
        $server_list[] = $name;
    }
}

$res_queue = sql_query("SELECT DISTINCT `server_ip` AS server_name FROM `app_ikev2_provision_queue` WHERE TRIM(`server_ip`) <> '' ORDER BY `server_ip` ASC", false);
if ($res_queue) {
    for ($i = 0; $row = sql_fetch_array($res_queue); $i++) {
        $name = trim((string)($row['server_name'] ?? ''));
        if ($name === '' || isset($server_seen[$name])) {
            continue;
        }
        $server_seen[$name] = true;
        $server_list[] = $name;
    }
}

sort($server_list);

if ($server_name === '' && count($server_list) > 0) {
    $server_name = (string)$server_list[0];
}

$shop_users = array();
$server_users = array();
$compare_rows = array();
$server_fetch_error = '';
$server_fetch_message = '';

if ($server_name !== '') {
    $sql_shop = "SELECT v.*
                   FROM `vpnid_list` v
             INNER JOIN (
                         SELECT `vpn_user_id`, MAX(`no`) AS max_no
                           FROM `vpnid_list`
                          WHERE `server_name` = '" . sql_escape_string($server_name) . "'
                          GROUP BY `vpn_user_id`
                        ) x ON v.no = x.max_no
                  ORDER BY v.vpn_user_id ASC";
    $res_shop = sql_query($sql_shop, false);
    if ($res_shop) {
        for ($i = 0; $row = sql_fetch_array($res_shop); $i++) {
            $vpn_user_id = trim((string)($row['vpn_user_id'] ?? ''));
            if ($vpn_user_id === '') {
                continue;
            }

            $shop_users[$vpn_user_id] = array(
                'vpn_user_id' => $vpn_user_id,
                'vpn_user_pwd' => trim((string)($row['vpn_user_pwd'] ?? '')),
                'member_id_expire' => trim((string)($row['member_id_expire'] ?? '')),
                'od_id' => trim((string)($row['od_id'] ?? '')),
                'plan_name' => trim((string)($row['plan_name'] ?? '')),
                'memo' => trim((string)($row['memo'] ?? '')),
                'enable' => isset($row['enable']) ? (int)$row['enable'] : 1,
                'password_sha256' => hash('sha256', trim((string)($row['vpn_user_pwd'] ?? '')))
            );
        }
    }

    $fetch_ret = vpnlink_ikev2_fetch_server_users($server_name, $limit);
    if (empty($fetch_ret['ok'])) {
        $server_fetch_error = isset($fetch_ret['error']) ? (string)$fetch_ret['error'] : 'server_fetch_failed';
    } else {
        $server_fetch_message = isset($fetch_ret['message']) ? (string)$fetch_ret['message'] : '';
        $rows = isset($fetch_ret['users']) && is_array($fetch_ret['users']) ? $fetch_ret['users'] : array();
        foreach ($rows as $row) {
            if (!is_array($row)) {
                continue;
            }
            $user_id = trim((string)($row['user_id'] ?? ''));
            if ($user_id === '') {
                continue;
            }
            $server_users[$user_id] = $row;
        }
    }

    $union_ids = array();
    foreach ($shop_users as $uid => $tmp) {
        $union_ids[$uid] = true;
    }
    foreach ($server_users as $uid => $tmp) {
        $union_ids[$uid] = true;
    }

    $ids = array_keys($union_ids);
    sort($ids);

    foreach ($ids as $uid) {
        $shop = isset($shop_users[$uid]) ? $shop_users[$uid] : null;
        $server = isset($server_users[$uid]) ? $server_users[$uid] : null;

        $has_shop = is_array($shop);
        $has_server = is_array($server);

        $shop_pwd_hash = $has_shop ? (string)$shop['password_sha256'] : '';
        $server_pwd_hash = $has_server ? trim((string)($server['password_sha256'] ?? '')) : '';

        $shop_expire = $has_shop ? trim((string)$shop['member_id_expire']) : '';
        $server_expire = $has_server ? trim((string)($server['expire'] ?? '')) : '';

        $server_shop_managed = $has_server ? (!empty($server['shop_managed'])) : false;

        $pwd_diff = false;
        if ($has_shop && $has_server && $server_shop_managed) {
            if ($shop_pwd_hash !== '' && $server_pwd_hash !== '' && $shop_pwd_hash !== $server_pwd_hash) {
                $pwd_diff = true;
            }
        }

        $expire_diff = false;
        if ($has_shop && $has_server && $server_shop_managed) {
            $expire_diff = ($shop_expire !== $server_expire);
        }

        $sync_candidate = false;
        $status_label = '';
        $source_label = '';

        if ($has_shop && !$has_server) {
            $status_label = '쇼핑몰에만 존재 (동기화 필요)';
            $source_label = '쇼핑몰 주문 사용자';
            $sync_candidate = true;
        } elseif (!$has_shop && $has_server) {
            if ($server_shop_managed) {
                $status_label = '서버에만 존재 (점검 필요)';
                $source_label = '쇼핑몰 주문 사용자(서버만 존재)';
            } else {
                $status_label = '서버관리자 수동등록 (보호대상)';
                $source_label = '개별 서버 관리자 등록';
            }
        } else {
            if ($server_shop_managed) {
                if ($pwd_diff || $expire_diff) {
                    $status_label = '불일치 (업데이트 필요)';
                    $sync_candidate = true;
                } else {
                    $status_label = '일치';
                }
                $source_label = '쇼핑몰 주문 사용자';
            } else {
                $status_label = '동일 ID 충돌 (수동등록 보호)';
                $source_label = '개별 서버 관리자 등록';
            }
        }

        $compare_rows[] = array(
            'user_id' => $uid,
            'has_shop' => $has_shop,
            'has_server' => $has_server,
            'shop_expire' => $shop_expire,
            'server_expire' => $server_expire,
            'shop_od_id' => $has_shop ? trim((string)$shop['od_id']) : '',
            'shop_plan_name' => $has_shop ? trim((string)$shop['plan_name']) : '',
            'server_shop_managed' => $server_shop_managed,
            'source_label' => $source_label,
            'status_label' => $status_label,
            'pwd_diff' => $pwd_diff,
            'expire_diff' => $expire_diff,
            'sync_candidate' => $sync_candidate
        );
    }
}

$summary_total = count($compare_rows);
$summary_sync_needed = 0;
$summary_manual_protected = 0;
foreach ($compare_rows as $r) {
    if (!empty($r['sync_candidate'])) {
        $summary_sync_needed++;
    }
    if (!empty($r['has_server']) && empty($r['server_shop_managed'])) {
        $summary_manual_protected++;
    }
}

include_once(G5_ADMIN_PATH.'/admin.head.php');
include_once('./_vpn_help_card.php');
vpn_help_card(array(
    'title'     => 'IKEv2 서버별 사용자 비교',
    'purpose'   => 'DB에 등록된 VPN 계정과 실제 IKEv2 서버의 ipsec.secrets 내용을 비교하여 동기화 누락 항목을 찾습니다.',
    'functions' => array('DB 계정과 서버 계정 나란히 비교 표시', 'DB에 있지만 서버에 없는 항목 강조', '서버에 있지만 DB에 없는 항목 강조', '서버별(IP 기준) 독립 비교'),
    'results'   => array('불일치 항목 발견 시 IKEv2 연동모니터에서 해당 계정 재시도로 동기화 가능', '정기 실행으로 DB↔서버 간 데이터 정합성 유지'),
    'target'    => 'IKEv2 VPN 서버의 ipsec.secrets 파일 (Ubuntu/CentOS)',
    'warnings'  => array('조회 전용 — 이 페이지에서 직접 서버를 수정하지 않음', '서버 API 실패 시 서버 데이터 없이 DB 목록만 표시', 'Ubuntu(/etc/ipsec.secrets)와 CentOS(/etc/strongswan/ipsec.secrets) 경로가 다름'),
));

?>

<style>
.ikev2-compare-wrap .local_desc01 { margin-bottom: 12px; }
.ikev2-compare-wrap .summary-box { display:flex; gap:12px; flex-wrap:wrap; margin:10px 0 14px; }
.ikev2-compare-wrap .summary-box .item { padding:8px 10px; border:1px solid #ddd; border-radius:6px; background:#fafafa; }
.ikev2-compare-wrap .danger-text { color:#b11a1a; font-weight:600; }
.ikev2-compare-wrap .ok-text { color:#176b2c; font-weight:600; }
.ikev2-compare-wrap .warn-text { color:#8a5a00; font-weight:600; }
.ikev2-compare-wrap .muted-text { color:#666; }
.ikev2-compare-wrap .table-wrap { overflow-x:auto; }
.ikev2-compare-wrap .tbl_head01 td, .ikev2-compare-wrap .tbl_head01 th { white-space:nowrap; }
[data-site-theme="dark"] .ikev2-compare-wrap .summary-box .item { background:#1a2336; border-color:#2d4470; color:#c4c4cc; }
[data-site-theme="dark"] .ikev2-compare-wrap .danger-text { color:#f87171; }
[data-site-theme="dark"] .ikev2-compare-wrap .ok-text { color:#4ade80; }
[data-site-theme="dark"] .ikev2-compare-wrap .warn-text { color:#fbbf24; }
[data-site-theme="dark"] .ikev2-compare-wrap .muted-text { color:#9ca3af; }
</style>

<div class="ikev2-compare-wrap">
    <div class="local_desc01 local_desc">
        <p>
            강제 동기화는 쇼핑몰 주문 사용자에 대해서만 <strong>추가/업데이트</strong>를 수행합니다.<br>
            개별 IKEv2 서버 관리자가 수동 등록한 사용자는 보호대상이며, 본 화면/프로그램에서 삭제/수정하지 않습니다.
        </p>
    </div>

    <form method="get" action="./ikev2_server_compare.php" class="local_sch01">
        <label for="server_name">서버</label>
        <select name="server_name" id="server_name">
            <option value="">서버 선택</option>
            <?php for ($i = 0; $i < count($server_list); $i++) { $sv = $server_list[$i]; ?>
                <option value="<?php echo htmlspecialchars($sv, ENT_QUOTES); ?>" <?php echo get_selected($server_name, $sv); ?>><?php echo htmlspecialchars($sv, ENT_QUOTES); ?></option>
            <?php } ?>
        </select>
        <label for="limit">조회건수</label>
        <input type="number" name="limit" id="limit" value="<?php echo (int)$limit; ?>" min="1" max="20000" style="width:110px;">
        <button type="submit" class="btn btn_02">비교 조회</button>
    </form>

    <?php if ($server_name !== '') { ?>
        <div class="summary-box">
            <div class="item">비교대상 전체: <strong><?php echo number_format($summary_total); ?></strong></div>
            <div class="item">동기화 필요: <strong class="warn-text"><?php echo number_format($summary_sync_needed); ?></strong></div>
            <div class="item">수동등록 보호대상: <strong class="danger-text"><?php echo number_format($summary_manual_protected); ?></strong></div>
            <div class="item">서버 응답: <span class="muted-text"><?php echo htmlspecialchars($server_fetch_message !== '' ? $server_fetch_message : '-', ENT_QUOTES); ?></span></div>
        </div>

        <?php if ($server_fetch_error !== '') { ?>
            <div class="local_desc01 local_desc">
                <p class="danger-text">서버 목록 조회 실패: <?php echo htmlspecialchars($server_fetch_error, ENT_QUOTES); ?></p>
            </div>
        <?php } ?>

        <form name="fcompare" method="post" action="./ikev2_server_compare_update.php" onsubmit="return fcompare_submit(this);">
            <input type="hidden" name="token" value="">
            <input type="hidden" name="server_name" value="<?php echo htmlspecialchars($server_name, ENT_QUOTES); ?>">
            <input type="hidden" name="limit" value="<?php echo (int)$limit; ?>">

            <div class="btn_fixed_top">
                <button type="submit" name="act_button" value="선택 강제동기화" class="btn btn_03">선택 강제동기화 (쇼핑몰 주문 사용자만)</button>
            </div>

            <div class="tbl_head01 tbl_wrap table-wrap">
                <table>
                    <caption>IKEv2 서버별 사용자 비교</caption>
                    <thead>
                        <tr>
                            <th scope="col"><input type="checkbox" onclick="check_all(this.form)"></th>
                            <th scope="col">사용자ID</th>
                            <th scope="col">구분</th>
                            <th scope="col">상태</th>
                            <th scope="col">쇼핑몰 만료</th>
                            <th scope="col">서버 만료</th>
                            <th scope="col">암호비교</th>
                            <th scope="col">만료비교</th>
                            <th scope="col">주문번호</th>
                            <th scope="col">요금제</th>
                        </tr>
                    </thead>
                    <tbody>
                        <?php
                        if (count($compare_rows) < 1) {
                            echo '<tr><td colspan="10" class="empty_table">비교 데이터가 없습니다.</td></tr>';
                        }

                        for ($i = 0; $i < count($compare_rows); $i++) {
                            $row = $compare_rows[$i];
                            $sync_candidate = !empty($row['sync_candidate']);
                            $status_class = 'muted-text';
                            if ($row['status_label'] === '일치') {
                                $status_class = 'ok-text';
                            } elseif ($sync_candidate) {
                                $status_class = 'warn-text';
                            } elseif (!$row['server_shop_managed'] && $row['has_server']) {
                                $status_class = 'danger-text';
                            }
                        ?>
                        <tr>
                            <td>
                                <?php if ($sync_candidate) { ?>
                                    <input type="hidden" name="vpn_user_id[<?php echo $i; ?>]" value="<?php echo htmlspecialchars($row['user_id'], ENT_QUOTES); ?>">
                                    <input type="checkbox" name="chk[]" value="<?php echo $i; ?>">
                                <?php } else { ?>
                                    <span class="muted-text">-</span>
                                <?php } ?>
                            </td>
                            <td><?php echo htmlspecialchars($row['user_id'], ENT_QUOTES); ?></td>
                            <td><?php echo htmlspecialchars($row['source_label'], ENT_QUOTES); ?></td>
                            <td class="<?php echo $status_class; ?>"><?php echo htmlspecialchars($row['status_label'], ENT_QUOTES); ?></td>
                            <td><?php echo htmlspecialchars($row['shop_expire'] !== '' ? $row['shop_expire'] : '-', ENT_QUOTES); ?></td>
                            <td><?php echo htmlspecialchars($row['server_expire'] !== '' ? $row['server_expire'] : '-', ENT_QUOTES); ?></td>
                            <td>
                                <?php
                                if ($row['has_shop'] && $row['has_server'] && $row['server_shop_managed']) {
                                    echo $row['pwd_diff'] ? '<span class="warn-text">불일치</span>' : '<span class="ok-text">일치</span>';
                                } else {
                                    echo '<span class="muted-text">-</span>';
                                }
                                ?>
                            </td>
                            <td>
                                <?php
                                if ($row['has_shop'] && $row['has_server'] && $row['server_shop_managed']) {
                                    echo $row['expire_diff'] ? '<span class="warn-text">불일치</span>' : '<span class="ok-text">일치</span>';
                                } else {
                                    echo '<span class="muted-text">-</span>';
                                }
                                ?>
                            </td>
                            <td><?php echo htmlspecialchars($row['shop_od_id'] !== '' ? $row['shop_od_id'] : '-', ENT_QUOTES); ?></td>
                            <td><?php echo htmlspecialchars($row['shop_plan_name'] !== '' ? $row['shop_plan_name'] : '-', ENT_QUOTES); ?></td>
                        </tr>
                        <?php } ?>
                    </tbody>
                </table>
            </div>
        </form>
    <?php } else { ?>
        <div class="local_desc01 local_desc">
            <p>비교할 서버를 선택해 주세요.</p>
        </div>
    <?php } ?>
</div>

<script>
function fcompare_submit(f) {
    if (!f.act_button || f.act_button.value !== '선택 강제동기화') {
        return true;
    }

    var checked = false;
    var boxes = f.querySelectorAll('input[name="chk[]"]');
    for (var i = 0; i < boxes.length; i++) {
        if (boxes[i].checked) {
            checked = true;
            break;
        }
    }

    if (!checked) {
        alert('강제동기화할 항목을 선택하세요.');
        return false;
    }

    return confirm('선택한 쇼핑몰 주문 사용자만 서버에 추가/업데이트합니다.\n수동등록 사용자에는 영향이 없습니다.\n진행하시겠습니까?');
}
</script>

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