<?php
include_once('./_common.php');
include_once(G5_LIB_PATH.'/order_result_popup.lib.php');
include_once(G5_PATH.'/mylib/ikev2_provision.lib.php');

if (!function_exists('oi_refund_mark_vpn_profile_state')) {
    function oi_refund_mark_vpn_profile_state($mbIdEsc, $odIdEsc, $itIdEsc, $refundDatetimeEsc)
    {
        $hasOdId = false;
        $c = sql_fetch("SHOW COLUMNS FROM vpnid_list LIKE 'od_id'", false);
        if (is_array($c) && !empty($c['Field'])) {
            $hasOdId = true;
        }

        $targetWhere = "it_name = CONCAT('VPN-', '{$itIdEsc}')";
        if ($hasOdId) {
            $targetWhere = "(od_id = '{$odIdEsc}' OR {$targetWhere})";
        }

        // enable=2: 환불/해지 완료, 앱 목록에는 남겨 수동 삭제를 허용
        sql_query("UPDATE vpnid_list
                      SET enable = '2',
                          vpn_id_expire = '{$refundDatetimeEsc}',
                          update_datetime = NOW()
                    WHERE (mb_id = '{$mbIdEsc}' OR remark = '{$mbIdEsc}')
                      AND {$targetWhere}", false);
    }
}

$member_mb_id_esc = sql_escape_string($member['mb_id']);
$od_id = oi_clean_id($od_id);
$it_id = oi_clean_id($it_id);
$uid = oi_clean_uid($uid);
$od_id_esc = oi_sql($od_id);
$it_id_esc = oi_sql($it_id);
$refund_memo_esc = oi_sql(oi_clean_text($refund_memo));
$error_redirect_url = ($od_id !== '' && $uid !== '')
    ? (G5_SHOP_URL . "/orderinquiryview.php?od_id={$od_id}&uid={$uid}")
    : G5_SHOP_URL;
$popup_log_fail_options = array('log' => true, 'log_tag' => 'order_refund_fail');
$popup_log_success_options = array('log' => true, 'log_tag' => 'order_refund_success');
$refund_tx_started = false;
$refund_idempotency_key = isset($_POST['idempotency_key']) ? trim((string)$_POST['idempotency_key']) : '';
$refund_idem_session_key = '';
if ($refund_idempotency_key !== '' && preg_match('/^[a-f0-9]{32}$/', $refund_idempotency_key)) {
    $refund_idem_session_key = 'oi_idem_refund_' . $refund_idempotency_key;
}

$refund_fail = function($message, $detail = '') use (&$refund_tx_started, $error_redirect_url, $popup_log_fail_options, &$refund_idem_session_key) {
    if ($refund_tx_started) {
        sql_query("ROLLBACK", false);
        $refund_tx_started = false;
    }
    if ($refund_idem_session_key !== '') {
        set_session($refund_idem_session_key, '');
    }
    oi_fail_popup($message, $detail, $error_redirect_url, '요청 처리 실패', '확인', '요청이 중단되었습니다.', $popup_log_fail_options);
};

if ($od_id === '' || $it_id === '') {
    $refund_fail('잘못된 요청입니다.', '주문정보를 다시 확인해 주세요. (ERR-REQ)');
}

// 세션에 저장된 토큰과 폼으로 넘어온 토큰을 비교하여 틀리면 에러
if ($token && get_session("ss_token") == $token) {
    // 맞으면 세션을 지워 다시 입력폼을 통해서 들어오도록 한다.
    set_session("ss_token", "");
} else {
    set_session("ss_token", "");
    $refund_fail('토큰 에러가 발생했습니다.', '페이지를 새로고침 후 다시 시도해 주세요. (ERR-TOKEN)');
}

if ($refund_idem_session_key === '') {
    $refund_fail('요청 식별키가 올바르지 않습니다.', '페이지를 새로고침 후 다시 시도해 주세요. (ERR-IDEM)');
}

$refund_idem_state = get_session($refund_idem_session_key);
if ($refund_idem_state === 'done') {
    oi_success_popup('이미 처리된 계약해지 요청입니다.', array(
        "주문번호 : {$od_id}",
        "상품명 : RPC-{$it_id}",
        '중복 제출이 감지되어 추가 처리는 수행하지 않았습니다.'
    ), $error_redirect_url, '계약해지 처리 완료', '확인', '이미 처리된 요청입니다.', $popup_log_success_options);
}
if ($refund_idem_state === 'pending') {
    $refund_fail('동일 요청이 처리 중입니다.', '잠시 후 다시 확인해 주세요. (ERR-IDEMPENDING)');
}
set_session($refund_idem_session_key, 'pending');

sql_query("START TRANSACTION");
$refund_tx_started = true;

$row_order_locked = sql_fetch(" SELECT od_id, od_mod_history FROM {$g5['g5_shop_order_table']} WHERE od_id = '{$od_id_esc}' AND mb_id = '{$member_mb_id_esc}' FOR UPDATE ");
if (!$row_order_locked || !isset($row_order_locked['od_id']) || trim((string)$row_order_locked['od_id']) === '') {
    $refund_fail('주문번호 확인에 실패했습니다.', '주문정보가 회원 계정과 일치하지 않습니다. (ERR-ORDER)');
}

$row_cart_refund_locked = sql_fetch(" SELECT * FROM {$g5['g5_shop_cart_table']} WHERE od_id = '{$od_id_esc}' AND it_id = '{$it_id_esc}' AND mb_id = '{$member_mb_id_esc}' FOR UPDATE ");
if (!$row_cart_refund_locked || !isset($row_cart_refund_locked['od_id'])) {
    $refund_fail('장바구니 주문정보 확인에 실패했습니다.', '주문정보가 회원 계정과 일치하지 않습니다. (ERR-CART)');
}

$ct_status_locked = isset($row_cart_refund_locked['ct_status']) ? trim((string)$row_cart_refund_locked['ct_status']) : '';
if ($ct_status_locked !== '입금' && $ct_status_locked !== '완료') {
    $refund_fail('환불 가능한 주문상태가 아닙니다.', '입금/완료 상태에서만 환불신청이 가능합니다. (ERR-STATUS)');
}


// 환불금액 재계산 {
$row_it_refund = sql_fetch(" SELECT * FROM {$g5['g5_shop_item_table']} WHERE it_id = '{$it_id_esc}' AND it_spec_buyer_mb_id = '{$member_mb_id_esc}' FOR UPDATE ");

if (!$row_it_refund || trim((string)$row_it_refund['it_spec_from_datetime']) === '' || trim((string)$row_it_refund['it_spec_to_datetime']) === '') {
    $refund_fail('계약정보 조회에 실패했습니다.', '계약 시작/종료 정보를 확인할 수 없습니다. (ERR-CONTRACT)');
}

$row_ct_price = $row_cart_refund_locked;

$sell_price = max(0, ((float)$row_ct_price['ct_price'] * (float)$row_ct_price['ct_qty']) + (float)$row_ct_price['ct_price_for_extension_of_period']); // 설치비/개통비를 제외한 금액을 환불대상금액으로 설정해야 함


// 현재 시간
$current_time = new DateTime(G5_TIME_YMDHIS);

// 시작 및 종료 시간
$start_time = new DateTime($row_it_refund['it_spec_from_datetime']);
$end_time = new DateTime($row_it_refund['it_spec_to_datetime']);

// 총 사용 시간 (초 단위)
$total_usage_time = max(0, $end_time->getTimestamp() - $start_time->getTimestamp());
$total_usage_minutes = $total_usage_time / 60;

if ($total_usage_minutes <= 0) {
    $refund_fail('환불금액 계산 중 오류가 발생했습니다.', '계약기간 정보가 올바르지 않습니다. (E-CODE: OIR002)');
}

// 분당 요금 계산
$minute_rate = ($total_usage_minutes > 0) ? ($sell_price / $total_usage_minutes) : 0;

// 현재까지 경과된 시간 (0 ~ 총사용시간으로 보정)
$elapsed_time_raw = $current_time->getTimestamp() - $start_time->getTimestamp();
$elapsed_time = min(max(0, $elapsed_time_raw), $total_usage_time);

// 남은 시간 (초 단위)
$remaining_time = max(0, $total_usage_time - $elapsed_time);

$elapsed_minutes = $elapsed_time / 60;
$remaining_minutes = $remaining_time / 60;

// 환불액 계산 (위약금 30% 공제)
$refund_amount = max(0, $remaining_minutes * $minute_rate);
$penalty_amount = max(0, $refund_amount * (defined('VPNLINK_CANCELLATION_FEE_RATE') ? VPNLINK_CANCELLATION_FEE_RATE : 0.30));
$refund_amount_after_penalty = max(0, $refund_amount - $penalty_amount);

// 총 사용 시간 계산 (일, 시간, 분 단위)
$total_usage_days = floor($total_usage_time / 86400);
$total_usage_hours = floor(($total_usage_time % 86400) / 3600);
$total_usage_remaining_minutes = floor(($total_usage_time % 3600) / 60);

// 잔여 시간 계산 (일, 시간, 분 단위)
$remaining_days = floor($remaining_time / 86400);
$remaining_hours = floor(($remaining_time % 86400) / 3600);
$remaining_remaining_minutes = floor(($remaining_time % 3600) / 60);

// 현재까지 경과된 시간 계산 (일, 시간, 분 단위)
$elapsed_days = floor($elapsed_time / 86400);
$elapsed_hours = floor(($elapsed_time % 86400) / 3600);
$elapsed_remaining_minutes = floor(($elapsed_time % 3600) / 60);

// 현재까지 경과된 시간에 대한 요금 계산
$elapsed_cost = max(0, $elapsed_minutes * $minute_rate);

// 잔여 시간에 대한 환산 요금 계산
$remaining_cost = max(0, $remaining_minutes * $minute_rate);

// 결과 출력
// echo "[계약해지 명세서]<br>";
// // echo "계약기간: {$total_usage_days}일 {$total_usage_hours}시간 {$total_usage_remaining_minutes}분<br>";
// echo "사용한요금: " . display_point($elapsed_cost);
// echo " (사용한시간: {$elapsed_days}일 {$elapsed_hours}시간 {$elapsed_remaining_minutes}분)<br>";

// echo "미사용요금: " . display_point($remaining_cost);
// echo " (미사용시간: {$remaining_days}일 {$remaining_hours}시간 {$remaining_remaining_minutes}분)<br>";

// echo "해지수수료: " . display_point($penalty_amount) . " (미사용요금 x 0.3)<br>";
// echo "환불금액: " . display_point($refund_amount_after_penalty) . " (미사용요금 - 해지수수료)<br>";
// 환불금액 재계산 }


// 기존에 동일 품번에 대해 이미 환불이 있었을 경우, 해당 환불 포인트를 먼저 회수함 (플랫폼에서 되돌려 받은 후 새로운 환불금액을 포인트로 재적립해 줘야 하므로 이미 환불해 준 포인트가 있는 경우 회수함)
$po_rel_action = $od_id_esc."|".$it_id_esc;
$row_point_sum = sql_fetch(" SELECT sum(po_point) as sum_po_point FROM {$g5['point_table']} WHERE mb_id = '{$member_mb_id_esc}' AND po_rel_table LIKE '@shoprefund%' AND po_rel_action = '{$po_rel_action}' ");
if ($row_point_sum['sum_po_point'] > 0) {
    $old_point = $row_point_sum['sum_po_point'];
    insert_point($member['mb_id'], $old_point * (-1), "계약해지 주문번호 {$od_id} 상품명 RPC-{$it_id} 환불 취소 (시스템 자동처리)", "@shoprefundcancel"."|".time(), $member['mb_id']."|".$member['mb_id'], $od_id."|".$it_id);
}


// 환불금액 $refund_amount_after_penalty 변수 데이터값 DB에 등록 (shop_cart 테이블의 real_refund_amount 필드에 저장)
$refund_amount_after_penalty = round($refund_amount_after_penalty);
$real_refund_datetime = G5_TIME_YMDHIS;
sql_query(" UPDATE {$g5['g5_shop_cart_table']} SET real_refund_datetime = '{$real_refund_datetime}', real_refund_amount = '{$refund_amount_after_penalty}', real_refund_memo = '{$refund_memo_esc}' WHERE od_id = '{$od_id_esc}' AND it_id = '{$it_id_esc}' AND mb_id = '{$member_mb_id_esc}' ");

oi_refund_mark_vpn_profile_state($member_mb_id_esc, $od_id_esc, $it_id_esc, oi_sql($real_refund_datetime));

// 환불시 계약 종료시각을 환불시각으로 고정한다.
sql_query(" UPDATE {$g5['g5_shop_item_table']} SET it_spec_to_datetime = '{$real_refund_datetime}' WHERE it_id = '{$it_id_esc}' AND it_spec_buyer_mb_id = '{$member_mb_id_esc}' ");

// shop_order 테이블의 od_refund_price 필드에 저장할려면 shop_cart 테이블의 real_refund_amount 필드의 합계를 구해서 저장해야 함 단, 이건 it_id를 제외하고 합산해야 함
$row_total_real_refund_amount = sql_fetch(" SELECT sum(real_refund_amount) AS total_real_refund_amount FROM {$g5['g5_shop_cart_table']} WHERE od_id = '{$od_id_esc}' AND mb_id = '{$member_mb_id_esc}' ");

// shop_order 테이블의 od_refund_price 필드에 저장
$sum_real_refund_amount = round($row_total_real_refund_amount['total_real_refund_amount']);
// 기존 od_mod_history 값을 조회
$row_od_mod_history = sql_fetch("SELECT od_mod_history FROM {$g5['g5_shop_order_table']} WHERE od_id = '{$od_id_esc}' AND mb_id = '{$member_mb_id_esc}'");
$existing_od_mod_history = trim($row_od_mod_history['od_mod_history']);

// 새로 추가할 shop_order 테이블의 od_mod_history 컬럼에 추가할 메모
$new_od_mod_history = G5_TIME_YMDHIS . " 계약해지 상품명 RPC-{$it_id} 환불 (이용자: {$member['mb_id']} / {$member['mb_name']}) " . display_point($refund_amount_after_penalty);

// 기존 메모에 줄바꿈과 함께 새 메모를 추가
$updated_od_mod_history = trim($existing_od_mod_history . "\n" . $new_od_mod_history);

// 데이터베이스 업데이트
sql_query("UPDATE {$g5['g5_shop_order_table']} SET od_refund_price = '{$sum_real_refund_amount}', od_mod_history = '{$updated_od_mod_history}' WHERE od_id = '{$od_id_esc}' AND mb_id = '{$member_mb_id_esc}'");

// 환불신청 회원의 포인트를 되돌려 줌
if ($refund_amount_after_penalty > 0) {
    insert_point($member['mb_id'], $refund_amount_after_penalty, "계약해지 주문번호 {$od_id} 상품명 RPC-{$it_id} 환불 (이용자: {$member['mb_id']} / {$member['mb_name']})", "@shoprefund"."|".time(), $member['mb_id']."|".$member['mb_id'], $od_id."|".$it_id);
}

/////////////////////////////////////////////////////////////////////////
// 환불처리가 완료 되었으므로 RPC전원을 종료시키거나 원격접속을 종료시켜야 함
/////////////////////////////////////////////////////////////////////////


if ($refund_tx_started) {
    sql_query("COMMIT");
    $refund_tx_started = false;
}

if (function_exists('vpnlink_vpnid_sync_upsert_by_order')) {
    $vpnid_sync_ret = vpnlink_vpnid_sync_upsert_by_order($od_id, $it_id, 'shop_order_refund');
    if (empty($vpnid_sync_ret['ok']) && function_exists('vpnlink_ikev2_log')) {
        vpnlink_ikev2_log('shop/orderinquiryrefund vpnid sync failed: od_id='.$od_id.' it_id='.$it_id.' error='.(isset($vpnid_sync_ret['error']) ? $vpnid_sync_ret['error'] : 'unknown'));
    }
}

if (function_exists('vpnlink_ikev2_queue_order')) {
    $ikev2_requeue_ret = vpnlink_ikev2_queue_order($od_id, 'shop_order_refund_requeue');
    if (empty($ikev2_requeue_ret['ok']) && function_exists('vpnlink_ikev2_log')) {
        vpnlink_ikev2_log('shop/orderinquiryrefund ikev2 requeue failed: od_id='.$od_id.' it_id='.$it_id.' error='.(isset($ikev2_requeue_ret['error']) ? $ikev2_requeue_ret['error'] : 'unknown'));
    }
}

set_session($refund_idem_session_key, 'done');



$redirect_url = G5_SHOP_URL . "/orderinquiryview.php?od_id={$od_id}&uid={$uid}";
$refund_amount_disp = number_format((int)$refund_amount_after_penalty);
oi_success_popup('계약해지 처리가 완료되었습니다.', array(
    "주문번호 : {$od_id}",
    "상품명 : RPC-{$it_id}",
    "환불(포인트)금액 : {$refund_amount_disp} Point",
    "처리일시 : {$real_refund_datetime}",
    "해지사유 : {$refund_memo}"
), $redirect_url, '계약해지 처리 완료', '확인', '처리 내역을 확인해 주세요.', $popup_log_success_options);
?>