<?php
/**
 * strongswan_profile_delete.php
 * - 1차 요청: 확인 절차 (confirm 팝업/confirm_required JSON)
 * - 2차 요청(confirm=1): vpnid_list.enable = 0 소프트 삭제 수행
 */

include_once('./_common.php');

global $g5;

if (!$link) {
    $link = $g5['connect_db'];
}

header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json; charset=UTF-8');

function delete_debug_log($message, $context = array()) {
    // debug logging disabled
}

function request_value($key, $default = '') {
    return isset($_REQUEST[$key]) ? trim((string)$_REQUEST[$key]) : $default;
}

function json_out($result, $msg, $extra = array()) {
    $payload = array_merge(array(
        'result' => $result,
        'msg' => $msg,
    ), $extra);
    echo json_encode($payload, JSON_UNESCAPED_UNICODE);
    exit;
}

function esc_sql($value) {
    if (function_exists('sql_real_escape_string')) {
        return sql_real_escape_string($value);
    }
    return addslashes($value);
}

function post_bool_confirmed() {
    $confirm = strtolower(request_value('confirm', ''));
    return in_array($confirm, array('1', 'y', 'yes', 'true', 'confirm'), true);
}

function delete_load_shop_sync_secret() {
    $secret = '';

    if (isset($_SERVER['IKEV2_SHOP_SYNC_SHARED_SECRET'])) {
        $secret = trim((string)$_SERVER['IKEV2_SHOP_SYNC_SHARED_SECRET']);
    }

    if ($secret === '' && isset($_ENV['IKEV2_SHOP_SYNC_SHARED_SECRET'])) {
        $secret = trim((string)$_ENV['IKEV2_SHOP_SYNC_SHARED_SECRET']);
    }

    if ($secret === '' && function_exists('getenv')) {
        $envVal = getenv('IKEV2_SHOP_SYNC_SHARED_SECRET');
        if (is_string($envVal)) {
            $secret = trim($envVal);
        }
    }

    if ($secret === '') {
        $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);
                    }
                    $secret = trim((string)$v);
                    break;
                }
            }
        }
    }

    return $secret;
}

function delete_extract_gateway_base($rawGateway) {
    $rawGateway = trim((string)$rawGateway);
    if ($rawGateway === '') {
        return '';
    }

    // profile_gateway가 IP/도메인만 올 수도 있고 URL 전체가 올 수도 있으므로 둘 다 처리한다.
    if (preg_match('#^https?://#i', $rawGateway)) {
        $parsed = @parse_url($rawGateway);
        if (!is_array($parsed) || empty($parsed['host'])) {
            return '';
        }
        $scheme = isset($parsed['scheme']) ? strtolower((string)$parsed['scheme']) : 'http';
        $host = trim((string)$parsed['host']);
        if ($host === '') {
            return '';
        }
        return $scheme . '://' . $host;
    }

    // 스키마가 없는 경우 host:port/path 형태를 host:port로 정리
    $hostPart = preg_split('#[/?]#', $rawGateway, 2);
    $host = trim((string)$hostPart[0]);
    if ($host === '') {
        return '';
    }
    return 'http://' . $host;
}

function delete_default_vpn_users_endpoint() {
    // 1순위: 요청에서 전달된 profile_gateway/profile_gateway_url 기반
    $gatewayUrl = delete_extract_gateway_base(request_value('profile_gateway_url', ''));
    if ($gatewayUrl !== '') {
        return $gatewayUrl . '/IKEv2SellerOffice4U/vpn_users.php';
    }

    $gateway = delete_extract_gateway_base(request_value('profile_gateway', ''));
    if ($gateway !== '') {
        return $gateway . '/IKEv2SellerOffice4U/vpn_users.php';
    }

    // 2순위: 기존 호환용 HTTP_HOST 기반 fallback
    $host = isset($_SERVER['HTTP_HOST']) ? trim((string)$_SERVER['HTTP_HOST']) : '';
    if ($host === '') {
        return '';
    }
    $scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
    return $scheme . '://' . $host . '/IKEv2SellerOffice4U/vpn_users.php';
}

function delete_call_vpn_users_disable($vpnUserId, $mbId) {
    $vpnUserId = trim((string)$vpnUserId);
    $mbId = trim((string)$mbId);
    if ($vpnUserId === '') {
        return array('attempted' => false, 'status' => 'skip_empty_user_id');
    }

    $endpoint = trim((string)request_value('vpn_users_endpoint', ''));
    if ($endpoint === '') {
        $endpoint = delete_default_vpn_users_endpoint();
    }
    if ($endpoint === '') {
        return array('attempted' => false, 'status' => 'skip_no_endpoint');
    }

    $secret = delete_load_shop_sync_secret();
    if ($secret === '') {
        return array('attempted' => false, 'status' => 'skip_no_shared_secret', 'endpoint' => $endpoint);
    }

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

    $headers = 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,
    );

    $sendRequest = function ($targetEndpoint) use ($headers, $requestPayload) {
        $raw = '';
        $httpCode = 0;
        $transportError = '';
        $location = '';

        if (function_exists('curl_init')) {
            $ch = curl_init($targetEndpoint);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_HEADER, true);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 4);
            curl_setopt($ch, CURLOPT_TIMEOUT, 8);
            curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $requestPayload);

            $rawResp = curl_exec($ch);
            if ($rawResp === false) {
                $transportError = (string)curl_error($ch);
            } else {
                $headerSize = (int)curl_getinfo($ch, CURLINFO_HEADER_SIZE);
                $headerBlob = (string)substr((string)$rawResp, 0, $headerSize);
                $raw = (string)substr((string)$rawResp, $headerSize);
                if (preg_match('/\r?\nLocation:\s*([^\r\n]+)/i', $headerBlob, $mLoc)) {
                    $location = trim((string)$mLoc[1]);
                }
            }
            $httpCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);
        } else {
            $ctx = stream_context_create(array(
                'http' => array(
                    'method' => 'POST',
                    'header' => implode("\r\n", $headers),
                    'content' => $requestPayload,
                    'timeout' => 8,
                    'ignore_errors' => true,
                ),
            ));
            $rawResp = @file_get_contents($targetEndpoint, false, $ctx);
            if ($rawResp === false) {
                $transportError = 'file_get_contents_failed';
                $raw = '';
            } else {
                $raw = (string)$rawResp;
            }
            if (isset($http_response_header) && is_array($http_response_header)) {
                foreach ($http_response_header as $line) {
                    if ($httpCode === 0 && preg_match('/^HTTP\/\S+\s+(\d{3})/i', $line, $m)) {
                        $httpCode = (int)$m[1];
                    }
                    if ($location === '' && preg_match('/^Location:\s*(.+)$/i', $line, $mLoc2)) {
                        $location = trim((string)$mLoc2[1]);
                    }
                }
            }
        }

        return array(
            'endpoint' => $targetEndpoint,
            'http_code' => $httpCode,
            'transport_error' => $transportError,
            'raw' => $raw,
            'location' => $location,
        );
    };

    $attemptEndpoints = array($endpoint);
    if (stripos($endpoint, 'http://') === 0) {
        $attemptEndpoints[] = 'https://' . substr($endpoint, 7);
    }

    $seen = array();
    $attemptTrace = array();
    $last = array(
        'endpoint' => $endpoint,
        'http_code' => 0,
        'transport_error' => '',
        'raw' => '',
        'location' => '',
    );
    $success = false;
    $decoded = null;
    $isJson = false;

    $maxAttempts = 3;
    while (!empty($attemptEndpoints) && count($attemptTrace) < $maxAttempts) {
        $targetEndpoint = array_shift($attemptEndpoints);
        if ($targetEndpoint === '' || isset($seen[$targetEndpoint])) {
            continue;
        }
        $seen[$targetEndpoint] = true;

        $last = $sendRequest($targetEndpoint);
        $attemptTrace[] = array(
            'endpoint' => $last['endpoint'],
            'http_code' => (int)$last['http_code'],
            'transport_error' => (string)$last['transport_error'],
            'location' => (string)$last['location'],
        );

        $decoded = json_decode((string)$last['raw'], true);
        $isJson = is_array($decoded);
        $remoteSuccess = false;
        if ($isJson) {
            $resultVal = strtolower(trim((string)(isset($decoded['result']) ? $decoded['result'] : '')));
            $statusVal = strtolower(trim((string)(isset($decoded['status']) ? $decoded['status'] : '')));
            $successVal = isset($decoded['success']) ? $decoded['success'] : null;
            $okVal = isset($decoded['ok']) ? $decoded['ok'] : null;
            $remoteSuccess = !empty($successVal)
                || !empty($okVal)
                || $resultVal === 'success'
                || $statusVal === 'success'
                || $statusVal === 'ok';
        }

        if ($last['transport_error'] === '' && $last['http_code'] >= 200 && $last['http_code'] < 300 && $remoteSuccess) {
            $success = true;
            break;
        }

        if ($last['http_code'] >= 300 && $last['http_code'] < 400) {
            $location = trim((string)$last['location']);
            if ($location !== '' && preg_match('#^https?://#i', $location)) {
                $attemptEndpoints[] = $location;
            }
            if (stripos($targetEndpoint, 'http://') === 0) {
                $attemptEndpoints[] = 'https://' . substr($targetEndpoint, 7);
            }
        }
    }

    return array(
        'attempted' => true,
        'endpoint' => $last['endpoint'],
        'http_code' => (int)$last['http_code'],
        'transport_error' => (string)$last['transport_error'],
        'location' => (string)$last['location'],
        'attempt_trace' => $attemptTrace,
        'raw' => (strlen((string)$last['raw']) > 400) ? substr((string)$last['raw'], 0, 400) . '...[truncated]' : (string)$last['raw'],
        'json' => $isJson ? $decoded : null,
        'success' => $success,
    );
}

function resolve_member_id($rawMemberId, $rawMemberEmail) {
    global $g5;

    $mbId = $rawMemberId;
    if ($rawMemberEmail !== '') {
        $mbId = $rawMemberEmail;
    }

    if ($mbId === '' || preg_match('/^VpNgueSt/', $mbId)) {
        return $mbId;
    }

    $resolvedMember = array();
    if ($rawMemberEmail !== '' || filter_var($mbId, FILTER_VALIDATE_EMAIL)) {
        $safeIdentifier = esc_sql($mbId);
        $resolvedMember = sql_fetch(" select * from {$g5['member_table']} where mb_email = '{$safeIdentifier}' ");
    }

    if (!isset($resolvedMember['mb_id']) || !$resolvedMember['mb_id']) {
        $resolvedMember = get_member($mbId);
    }

    if (isset($resolvedMember['mb_id']) && $resolvedMember['mb_id']) {
        return $resolvedMember['mb_id'];
    }

    return $mbId;
}

function should_show_browser_confirm() {
    // 브라우저 직접 호출 시 확인 팝업을 띄우고, 앱/서버 호출은 JSON으로 안내한다.
    $accept = isset($_SERVER['HTTP_ACCEPT']) ? strtolower((string)$_SERVER['HTTP_ACCEPT']) : '';
    $xhr = isset($_SERVER['HTTP_X_REQUESTED_WITH']) ? strtolower((string)$_SERVER['HTTP_X_REQUESTED_WITH']) : '';

    if ($xhr === 'xmlhttprequest') {
        return false;
    }
    if (strpos($accept, 'application/json') !== false) {
        return false;
    }
    return true;
}

function render_browser_confirm_page($message) {
    $self = htmlspecialchars(isset($_SERVER['PHP_SELF']) ? $_SERVER['PHP_SELF'] : '', ENT_QUOTES, 'UTF-8');
    ?>
<!doctype html>
<html lang="ko">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>삭제 확인</title>
</head>
<body>
<form id="confirmForm" method="post" action="<?php echo $self; ?>">
<?php foreach ($_REQUEST as $k => $v) { ?>
    <input type="hidden" name="<?php echo htmlspecialchars($k, ENT_QUOTES, 'UTF-8'); ?>" value="<?php echo htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8'); ?>">
<?php } ?>
    <input type="hidden" name="confirm" value="1">
</form>
<script>
(function () {
    var ok = window.confirm(<?php echo json_encode($message, JSON_UNESCAPED_UNICODE); ?>);
    if (ok) {
        document.getElementById('confirmForm').submit();
    } else {
        document.body.innerHTML = '<p style="font-family:sans-serif;padding:16px;">삭제가 취소되었습니다.</p>';
    }
})();
</script>
</body>
</html>
<?php
    exit;
}

function extract_vpn_no_from_profile_name($profileName) {
    $name = trim((string)$profileName);
    if ($name === '') {
        return '';
    }

    // 프로필명에 만료시간 텍스트가 붙는 경우를 고려해 문자열 어디서든 VPN-숫자 패턴을 찾는다.
    if (preg_match('/VPN-([0-9]+)/i', $name, $m)) {
        return $m[1];
    }
    if (preg_match('/([0-9]+)$/', $name, $m2)) {
        return $m2[1];
    }
    return '';
}

function build_where_attempts($mbId, $profileName, $profileGateway, $profileUsername, $profileUuid, $profileId) {
    $attempts = array();
    $vpnNoFromName = extract_vpn_no_from_profile_name($profileName);    // e.g. 10852
    $vpnItemName = request_value('it_name');                             // e.g. VPN-10852
    $vpnMemo = request_value('vpn_memo');                                // e.g. VPN-10852

    if ($vpnItemName === '' && $vpnNoFromName !== '') {
        $vpnItemName = 'VPN-' . $vpnNoFromName;
    }
    if ($vpnMemo === '' && $vpnItemName !== '') {
        $vpnMemo = $vpnItemName;
    }

    // 실제 vpnid_list 컬럼명만 사용:
    // no, mb_id, server_name, it_name, vpn_user_id, vpn_memo, remark, enable
    $eMbId = esc_sql($mbId);
    $eProfileGateway = esc_sql($profileGateway);
    $eProfileUsername = esc_sql($profileUsername);
    $eVpnNoFromName = esc_sql($vpnNoFromName);
    $eVpnItemName = esc_sql($vpnItemName);
    $eVpnMemo = esc_sql($vpnMemo);

    $ownerByMb = "`mb_id` = '{$eMbId}'";
    $ownerByRemark = "`remark` = '{$eMbId}'";

    if ($vpnItemName !== '') {
        $attempts[] = "({$ownerByMb} OR {$ownerByRemark}) AND `it_name` = '{$eVpnItemName}'";
    }

    if ($profileUsername !== '' && $profileGateway !== '') {
        $attempts[] = "({$ownerByMb} OR {$ownerByRemark}) AND `vpn_user_id` = '{$eProfileUsername}' AND `server_name` = '{$eProfileGateway}'";
    }

    if ($profileUsername !== '' && $vpnItemName !== '') {
        $attempts[] = "({$ownerByMb} OR {$ownerByRemark}) AND `vpn_user_id` = '{$eProfileUsername}' AND `it_name` = '{$eVpnItemName}'";
    }

    if ($profileGateway !== '' && $vpnItemName !== '') {
        $attempts[] = "({$ownerByMb} OR {$ownerByRemark}) AND `server_name` = '{$eProfileGateway}' AND `it_name` = '{$eVpnItemName}'";
    }

    if ($vpnMemo !== '') {
        $attempts[] = "({$ownerByMb} OR {$ownerByRemark}) AND `vpn_memo` = '{$eVpnMemo}'";
    }

    if ($vpnNoFromName !== '') {
        $attempts[] = "({$ownerByMb} OR {$ownerByRemark}) AND `no` = '{$eVpnNoFromName}'";
    }

    if ($profileUsername !== '') {
        $attempts[] = "({$ownerByMb} OR {$ownerByRemark}) AND `vpn_user_id` = '{$eProfileUsername}'";
    }

    if ($profileGateway !== '') {
        $attempts[] = "({$ownerByMb} OR {$ownerByRemark}) AND `server_name` = '{$eProfileGateway}'";
    }

    return array_values(array_unique($attempts));
}

$postMbEmail = request_value('mb_email');
$postMbId = request_value('mb_id');
$postUserId = request_value('user_id');

$rawMemberId = $postMbId !== '' ? $postMbId : $postUserId;
$mbId = resolve_member_id($rawMemberId, $postMbEmail);

$profileName = request_value('profile_name');
$profileGateway = request_value('profile_gateway');
$profileUsername = request_value('profile_username');
$profileUuid = request_value('profile_uuid');
$profileId = request_value('profile_id');

delete_debug_log('request_received', array(
    'mb_email' => $postMbEmail,
    'mb_id_raw' => $postMbId,
    'user_id_raw' => $postUserId,
    'mb_id_resolved' => $mbId,
    'profile_name' => $profileName,
    'profile_gateway' => $profileGateway,
    'profile_username' => $profileUsername,
    'profile_uuid' => $profileUuid,
    'profile_id' => $profileId,
    'it_name' => request_value('it_name'),
    'vpn_memo' => request_value('vpn_memo'),
    'confirm' => request_value('confirm'),
    'client' => request_value('client'),
    'response' => request_value('response'),
));

if ($mbId === '') {
    json_out('failure', '사용자 식별값(mb_id 또는 user_id)이 누락되었습니다.');
}

if ($profileName === '' && $profileGateway === '' && $profileUsername === '' && $profileUuid === '' && $profileId === '') {
    json_out('failure', '프로필 식별값이 누락되었습니다.');
}

if (!post_bool_confirmed()) {
    $confirmMessage = '정말 이 VPN 프로필을 목록에서 삭제하시겠습니까?';

    if (should_show_browser_confirm()) {
        render_browser_confirm_page($confirmMessage);
    }

    json_out('confirm', '삭제를 진행하려면 confirm=1 파라미터로 재요청해 주세요.', array(
        'confirm_required' => true,
        'confirm_message' => $confirmMessage,
    ));
}

$whereAttempts = build_where_attempts($mbId, $profileName, $profileGateway, $profileUsername, $profileUuid, $profileId);
delete_debug_log('where_attempts_built', array(
    'attempt_count' => count($whereAttempts),
    'attempts' => array_slice($whereAttempts, 0, 10),
));
if (empty($whereAttempts)) {
    delete_debug_log('empty_where_attempts', array(
        'mb_id' => $mbId,
        'profile_name' => $profileName,
        'profile_gateway' => $profileGateway,
        'profile_username' => $profileUsername,
        'profile_uuid' => $profileUuid,
        'profile_id' => $profileId,
    ));
    json_out('failure', '삭제 대상 조건을 구성하지 못했습니다.');
}

$updated = 0;
$matchedButAlreadyDisabled = 0;
$lastSqlError = '';
$vpnUsersSyncResult = array('attempted' => false, 'status' => 'not_run');

foreach ($whereAttempts as $whereClause) {
    $updateSql = "UPDATE `vpnid_list` SET `enable` = '0' WHERE ({$whereClause}) AND `enable` <> '0'";
    delete_debug_log('update_try', array('where' => $whereClause));
    $updateResult = sql_query($updateSql, false);

    if ($updateResult === false) {
        $lastSqlError = isset($GLOBALS['g5']['error']) ? (string)$GLOBALS['g5']['error'] : '';
        delete_debug_log('update_sql_error', array(
            'where' => $whereClause,
            'error' => $lastSqlError,
        ));
        continue;
    }

    $affected = 0;
    if (function_exists('sql_affected_rows')) {
        $affected = (int)sql_affected_rows();
    } else {
        $rowCount = sql_fetch('SELECT ROW_COUNT() AS cnt', false);
        $affected = isset($rowCount['cnt']) ? (int)$rowCount['cnt'] : 0;
    }

    if ($affected > 0) {
        $updated += $affected;
        delete_debug_log('update_success', array(
            'where' => $whereClause,
            'affected' => $affected,
        ));
        break;
    }

    $checkSql = "SELECT COUNT(*) AS cnt FROM `vpnid_list` WHERE {$whereClause} LIMIT 1";
    $exists = sql_fetch($checkSql, false);
    if (isset($exists['cnt']) && (int)$exists['cnt'] > 0) {
        $matchedButAlreadyDisabled = 1;
        delete_debug_log('matched_already_disabled', array(
            'where' => $whereClause,
            'count' => (int)$exists['cnt'],
        ));
        break;
    }
}

if ($updated > 0) {
    $vpnUsersSyncResult = delete_call_vpn_users_disable($profileUsername, $mbId);
    delete_debug_log('vpn_users_disable_result', $vpnUsersSyncResult);
    delete_debug_log('final_success', array('updated_count' => $updated));
    json_out('success', '프로필이 삭제(비활성화) 처리되었습니다.', array(
        'updated_count' => $updated,
        'vpn_users_sync' => $vpnUsersSyncResult,
    ));
}

if ($matchedButAlreadyDisabled) {
    $vpnUsersSyncResult = delete_call_vpn_users_disable($profileUsername, $mbId);
    delete_debug_log('vpn_users_disable_result', $vpnUsersSyncResult);
    delete_debug_log('final_already_disabled');
    json_out('success', '이미 삭제(비활성화)된 프로필입니다.', array(
        'updated_count' => 0,
        'vpn_users_sync' => $vpnUsersSyncResult,
    ));
}

delete_debug_log('final_failure', array('last_sql_error' => $lastSqlError));
json_out('failure', '삭제 대상 프로필을 찾지 못했거나 삭제에 실패했습니다.' . ($lastSqlError !== '' ? ' DB_ERROR: ' . $lastSqlError : ''));

