<?php
// Usage:
//   php __CRON/cron_ikev2_normalize_order_user_cli.php --help
//   php __CRON/cron_ikev2_normalize_order_user_cli.php --od_id=2026031215535054
//   php __CRON/cron_ikev2_normalize_order_user_cli.php --apply --od_id=2026031215535054 --user_id=habmds

if (PHP_SAPI !== 'cli') {
    echo "CLI only\n";
    exit(1);
}

$projectRoot = realpath(__DIR__ . '/..');
if ($projectRoot === false) {
    $projectRoot = dirname(__DIR__);
}

@chdir($projectRoot);

$hasGnuboardCommon = is_file($projectRoot . '/_common.php');
if ($hasGnuboardCommon) {
    require_once $projectRoot . '/_common.php';
}

if (!defined('VPN_USERS_SKIP_ACTION_ROUTER')) {
    define('VPN_USERS_SKIP_ACTION_ROUTER', true);
}

require_once $projectRoot . '/IKEv2SellerOffice4U/config.php';

if (!function_exists('logError')) {
    function logError($message, $context = array())
    {
        $line = '[ikev2_normalize_cli] ' . (string)$message;
        if (!empty($context)) {
            $line .= ' ' . json_encode($context, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        }
        error_log($line);
    }
}

require_once $projectRoot . '/IKEv2SellerOffice4U/vpn_users.php';

$opts = getopt('', array('help', 'apply', 'od_id::', 'it_id::', 'user_id::', 'expire::', 'memo::', 'admin::', 'secrets-file::'));

if (isset($opts['help'])) {
    echo "IKEv2 order user metadata normalize CLI\n";
    echo "\n";
    echo "Usage:\n";
    echo "  php __CRON/cron_ikev2_normalize_order_user_cli.php [options]\n";
    echo "\n";
    echo "Options:\n";
    echo "  --help                Show this help message\n";
    echo "  --apply               Apply update (default: dry-run)\n";
    echo "  --od_id=VALUE         Target order id (optional in standalone mode)\n";
    echo "  --it_id=VALUE         Item id (optional; useful in standalone mode)\n";
    echo "  --user_id=VALUE       Target VPN user id (recommended / standalone required)\n";
    echo "  --expire=DATETIME     Expire datetime (e.g. 2026-03-14 15:54:00)\n";
    echo "  --memo=TEXT           Memo override\n";
    echo "  --admin=ID            Admin override (default: shop_auto for order, else manual_api)\n";
    echo "  --secrets-file=PATH   Override secrets file path for this run\n";
    echo "\n";
    exit(0);
}

$apply = isset($opts['apply']);
$odId = isset($opts['od_id']) ? trim((string)$opts['od_id']) : '';
$itIdOption = isset($opts['it_id']) ? trim((string)$opts['it_id']) : '';
$userId = isset($opts['user_id']) ? trim((string)$opts['user_id']) : '';
$expireOption = isset($opts['expire']) ? trim((string)$opts['expire']) : '';
$memoOption = isset($opts['memo']) ? trim((string)$opts['memo']) : '';
$adminOption = isset($opts['admin']) ? trim((string)$opts['admin']) : '';
$secretsFileOverride = isset($opts['secrets-file']) ? trim((string)$opts['secrets-file']) : '';

if ($secretsFileOverride !== '') {
    if (!isset($GLOBALS['config']) || !is_array($GLOBALS['config'])) {
        $GLOBALS['config'] = array();
    }
    $GLOBALS['config']['secrets_file_path'] = $secretsFileOverride;
}

if ($odId === '' && $userId === '') {
    echo json_encode(array(
        'ok' => false,
        'mode' => $apply ? 'apply' : 'dry-run',
        'error' => 'missing_target_identifier',
        'hint' => 'provide --od_id or --user_id'
    ), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    echo "\n";
    exit(1);
}

function cli_normalize_datetime_text($raw)
{
    $text = trim((string)$raw);
    if ($text === '' || $text === '-' || $text === '0') {
        return '';
    }

    $text = str_replace('T', ' ', $text);
    $text = preg_replace('/\s*KST\(대한민국표준시\)\s*$/u', '', $text);
    $text = preg_replace('/\s*KST\s*$/u', '', $text);
    $text = preg_replace('/\s*UTC[^\s]*$/iu', '', $text);
    $text = trim($text);

    if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $text)) {
        $text .= ' 00:00:00';
    } elseif (preg_match('/^\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}$/', $text)) {
        $text .= ':00';
    }

    $ts = strtotime($text);
    if ($ts === false) {
        return '';
    }

    return date('Y-m-d H:i:s', $ts);
}

$itId = $itIdOption;
$itName = '';
$ctId = 0;
$resolvedExpire = '';
$modeContext = 'standalone';

$hasDbContext = ($hasGnuboardCommon && function_exists('sql_fetch') && function_exists('sql_escape_string') && isset($GLOBALS['g5']) && is_array($GLOBALS['g5']) && isset($GLOBALS['g5']['g5_shop_cart_table']) && isset($GLOBALS['g5']['g5_shop_item_table']) && $odId !== '');

if ($hasDbContext) {
    $modeContext = 'gnuboard';
    $g5 = $GLOBALS['g5'];

    $row = sql_fetch("SELECT c.ct_id,
                             c.it_id,
                             c.mb_id,
                             c.ct_option,
                             c.io_id,
                             c.ct_price,
                             c.ct_qty,
                             c.ct_qty_hour,
                            c.ct_time,
                             c.extension_of_period_to_datetime,
                             c.extension_of_period_date,
                             b.it_name,
                             b.it_spec_to_datetime
                        FROM {$g5['g5_shop_cart_table']} c
                   LEFT JOIN {$g5['g5_shop_item_table']} b ON c.it_id = b.it_id
                       WHERE c.od_id = '" . sql_escape_string($odId) . "'
                    ORDER BY c.ct_id DESC
                       LIMIT 1", false);

    if (!$row || !isset($row['it_id'])) {
        echo json_encode(array(
            'ok' => false,
            'mode' => $apply ? 'apply' : 'dry-run',
            'context' => $modeContext,
            'error' => 'order_row_not_found',
            'od_id' => $odId
        ), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
        echo "\n";
        exit(1);
    }

    $ctId = isset($row['ct_id']) ? (int)$row['ct_id'] : 0;
    $itId = trim((string)$row['it_id']);
    $itName = isset($row['it_name']) ? (string)$row['it_name'] : '';

    $memberId = trim((string)($row['mb_id'] ?? ''));
    $memberName = '';
    if (isset($g5['member_table']) && $g5['member_table'] !== '' && $memberId !== '') {
        $m = sql_fetch("SELECT mb_name FROM {$g5['member_table']} WHERE mb_id = '" . sql_escape_string($memberId) . "' LIMIT 1", false);
        if (is_array($m) && !empty($m['mb_name'])) {
            $memberName = trim((string)$m['mb_name']);
        }
    }

    $orderPoint = 0;
    $cashAmount = 0;
    $totalAmount = 0;
    $cartAmount = 0;
    $sendCost = 0;
    $sendCost2 = 0;
    $orderTimeRaw = '';
    if (isset($g5['g5_shop_order_table']) && $g5['g5_shop_order_table'] !== '') {
        $o = sql_fetch("SELECT od_time, od_receipt_point, od_receipt_price, od_cart_price, od_send_cost, od_send_cost2 FROM {$g5['g5_shop_order_table']} WHERE od_id = '" . sql_escape_string($odId) . "' LIMIT 1", false);
        if (is_array($o) && isset($o['od_time'])) {
            $orderTimeRaw = (string)$o['od_time'];
        }
        if (is_array($o) && isset($o['od_receipt_point'])) {
            $orderPoint = (float)$o['od_receipt_point'];
        }
        if (is_array($o) && isset($o['od_receipt_price'])) {
            $cashAmount = (float)$o['od_receipt_price'];
        }
        if (is_array($o) && isset($o['od_cart_price'])) {
            $cartAmount = (float)$o['od_cart_price'];
        }
        if (is_array($o) && isset($o['od_send_cost'])) {
            $sendCost = (float)$o['od_send_cost'];
        }
        if (is_array($o) && isset($o['od_send_cost2'])) {
            $sendCost2 = (float)$o['od_send_cost2'];
        }

        if ($cashAmount > 0 || $orderPoint > 0) {
            $totalAmount = $cashAmount + $orderPoint;
        } elseif ($cartAmount > 0 || $sendCost > 0 || $sendCost2 > 0) {
            $totalAmount = $cartAmount + $sendCost + $sendCost2;
        }
    }

    $planText = trim((string)($row['ct_option'] ?? ''));
    if ($planText === '' && !empty($row['io_id'])) {
        $planText = trim((string)$row['io_id']);
    }
    $usagePeriodText = '';
    $qDay = (int)($row['ct_qty'] ?? 0);
    $qHour = (int)($row['ct_qty_hour'] ?? 0);

    $baseTimeText = cli_normalize_datetime_text($orderTimeRaw);
    if ($baseTimeText === '') {
        $baseTimeText = cli_normalize_datetime_text(isset($row['ct_time']) ? $row['ct_time'] : '');
    }
    $baseTs = $baseTimeText !== '' ? strtotime($baseTimeText) : false;

    $expireCandidates = array(
        isset($row['extension_of_period_to_datetime']) ? $row['extension_of_period_to_datetime'] : '',
        isset($row['extension_of_period_date']) ? $row['extension_of_period_date'] : '',
        isset($row['it_spec_to_datetime']) ? $row['it_spec_to_datetime'] : ''
    );

    foreach ($expireCandidates as $candidate) {
        $normalized = cli_normalize_datetime_text($candidate);
        if ($normalized !== '') {
            $candidateTs = strtotime($normalized);
            if ($baseTs !== false && $candidateTs !== false && $candidateTs <= $baseTs) {
                continue;
            }
            $resolvedExpire = $normalized;
            break;
        }
    }

    if ($resolvedExpire === '' && ($qDay > 0 || $qHour > 0) && $baseTs !== false) {
        $resolvedExpire = date('Y-m-d H:i:s', $baseTs + ($qDay * 86400) + ($qHour * 3600));
    }

    if ($qDay > 0 || $qHour > 0) {
        $usagePeriodText = $qDay . '일' . $qHour . '시간';
    }

    if ($planText !== '') {
        $normalizeToken = function ($text) {
            $text = trim((string)$text);
            if ($text === '') {
                return '';
            }
            $text = preg_replace('/\s+/u', '', $text);
            return strtolower($text);
        };

        $planToken = $normalizeToken($planText);
        $itemNameToken = $normalizeToken($itName);
        $itemIdToken = $normalizeToken($itId);

        if (($itemNameToken !== '' && $planToken === $itemNameToken)
            || ($itemIdToken !== '' && $planToken === $itemIdToken)) {
            $planText = '';
        }
    }

    if ($planText === '' && isset($g5['g5_shop_cart_table']) && $g5['g5_shop_cart_table'] !== '') {
        $planWhere = "od_id = '" . sql_escape_string($odId) . "'";
        if ($itId !== '') {
            $planWhere .= " AND it_id = '" . sql_escape_string($itId) . "'";
        }

        $planRow = sql_fetch("SELECT ct_option, io_id
                                FROM {$g5['g5_shop_cart_table']}
                               WHERE {$planWhere}
                            ORDER BY ((ct_option LIKE '%이용권%') OR (io_id LIKE '%이용권%')) DESC, ct_id DESC
                               LIMIT 1", false);
        if (is_array($planRow)) {
            $planCandidate = trim((string)($planRow['ct_option'] ?? ''));
            if ($planCandidate === '') {
                $planCandidate = trim((string)($planRow['io_id'] ?? ''));
            }

            $normalizeToken = function ($text) {
                $text = trim((string)$text);
                if ($text === '') {
                    return '';
                }
                $text = preg_replace('/\s+/u', '', $text);
                return strtolower($text);
            };

            $candidateToken = $normalizeToken($planCandidate);
            $itemNameToken = $normalizeToken($itName);
            $itemIdToken = $normalizeToken($itId);

            if ($candidateToken !== ''
                && !($itemNameToken !== '' && $candidateToken === $itemNameToken)
                && !($itemIdToken !== '' && $candidateToken === $itemIdToken)) {
                $planText = $planCandidate;
            }
        }
    }

    if ($totalAmount <= 0 && isset($row['ct_price'])) {
        $unitPrice = (float)$row['ct_price'];
        $lineQty = $qDay > 0 ? $qDay : 1;
        if ($unitPrice > 0) {
            $totalAmount = $unitPrice * $lineQty;
        }
    }

    if ($cashAmount <= 0 && $totalAmount > 0 && $orderPoint <= 0) {
        $cashAmount = $totalAmount;
    }

    if ($memoOption === '') {
        $memoParts = array();
        if ($memberName !== '' && $memberId !== '') {
            $memoParts[] = '회원:' . $memberName . '(' . $memberId . ')';
        } elseif ($memberId !== '') {
            $memoParts[] = '회원ID:' . $memberId;
        }
        $memoParts[] = '주문번호:' . $odId;
        if ($itName !== '') {
            $memoParts[] = '상품명:' . $itName;
        } elseif ($itId !== '') {
            $memoParts[] = '상품코드:' . $itId;
        }
        if ($planText !== '') {
            $memoParts[] = '요금제:' . $planText;
        }
        if ($usagePeriodText !== '') {
            $memoParts[] = '주문기간:' . $usagePeriodText;
        }
        if ($resolvedExpire !== '') {
            $memoParts[] = '만료일시:' . $resolvedExpire;
        }
        if ($totalAmount > 0 || $cashAmount > 0 || $orderPoint > 0) {
            if ($totalAmount > 0) {
                $memoParts[] = '결제총액:' . rtrim(rtrim(number_format($totalAmount, 2, '.', ''), '0'), '.') . '원';
            }
            $memoParts[] = '실결제:' . rtrim(rtrim(number_format($cashAmount, 2, '.', ''), '0'), '.') . '원';
            $memoParts[] = '포인트결제:' . rtrim(rtrim(number_format($orderPoint, 2, '.', ''), '0'), '.') . 'P';
        }
        $memoOption = implode(' Œ ', $memoParts);
    }
}

if ($resolvedExpire === '' && $expireOption !== '') {
    $resolvedExpire = cli_normalize_datetime_text($expireOption);
}

if ($memoOption !== '') {
    $memo = str_replace('|', '／', $memoOption);
} else {
    if ($odId !== '' || $itId !== '') {
        $memo = '쇼핑몰 자동등록';
        if ($odId !== '') {
            $memo .= ' Œ 주문번호:' . $odId;
        }
        if ($itId !== '') {
            $memo .= ' Œ 상품코드:' . $itId;
        }
    } else {
        $memo = '수동 정규화';
    }
}

if ($adminOption !== '') {
    $admin = $adminOption;
} else {
    $admin = ($odId !== '' || $itId !== '') ? 'shop_auto' : 'manual_api';
}

$selectedUser = $userId;
$foundByMemo = array();

if ($selectedUser === '') {
    $users = VPNUserManager::getAllUsers();
    foreach ($users as $u) {
        $memoRaw = (string)($u['memo'] ?? '');
        if ($memoRaw !== '' && strpos($memoRaw, $odId) !== false) {
            $foundByMemo[] = (string)($u['user_id'] ?? '');
        }
    }

    $foundByMemo = array_values(array_filter(array_unique($foundByMemo)));
    if (count($foundByMemo) === 1) {
        $selectedUser = $foundByMemo[0];
    }
}

$secretsPathForRun = '';
if (isset($GLOBALS['config']) && is_array($GLOBALS['config']) && isset($GLOBALS['config']['secrets_file_path'])) {
    $secretsPathForRun = (string)$GLOBALS['config']['secrets_file_path'];
}

$payload = array(
    'ok' => true,
    'mode' => $apply ? 'apply' : 'dry-run',
    'context' => $modeContext,
    'od_id' => $odId,
    'ct_id' => $ctId,
    'it_id' => $itId,
    'it_name' => $itName,
    'resolved_expire' => $resolvedExpire,
    'memo' => $memo,
    'admin' => $admin,
    'user_id' => $selectedUser,
    'found_by_memo' => $foundByMemo,
    'secrets_file_path' => $secretsPathForRun,
    'secrets_exists' => ($secretsPathForRun !== '' && is_file($secretsPathForRun)) ? true : false,
    'secrets_readable' => ($secretsPathForRun !== '' && is_readable($secretsPathForRun)) ? true : false
);

if ($selectedUser === '') {
    $payload['ok'] = false;
    $payload['error'] = 'target_user_not_resolved';
    $payload['hint'] = 'provide --user_id explicitly';
    echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
    echo "\n";
    exit(1);
}

if (!$apply) {
    echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
    echo "\n";
    exit(0);
}

$ret = VPNUserManager::updateUser(
    $selectedUser,
    null,
    ($resolvedExpire !== '' ? $resolvedExpire : null),
    $memo,
    $admin,
    null
);

$payload['update_result'] = $ret;
$payload['ok'] = is_array($ret) && !empty($ret['success']);

echo json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
echo "\n";

exit($payload['ok'] ? 0 : 1);
