<?php

require_once __DIR__ . '/XuiV3Config.php';
require_once __DIR__ . '/XuiV3Service.php';
require_once __DIR__ . '/PasarguardConfig.php';

/**
 * Customer-facing subscription delivery (3x-ui v3 — subscription links only).
 */
class SubscriptionDelivery
{
    /** @var string[] */
    private static $rawConfigPatterns = [
        'vless://', 'vmess://', 'trojan://', 'ss://', 'hysteria://', 'hy2://',
    ];

    /** @param array<string, mixed> $serverInfo */
    public static function isPanelServer(array $serverInfo): bool
    {
        return XuiV3Config::isPanelServer($serverInfo);
    }

    /** @param array<string, mixed> $serverInfo */
    public static function buildSubscriptionUrl(array $serverInfo, string $subId): string
    {
        return (new XuiV3Service($serverInfo))->buildSubscriptionUrl($subId);
    }

    /** @param array<string, mixed> $serverInfo @param array<string, mixed> $order */
    public static function resolveOrderSubscriptionLink(array $serverInfo, array $order): string
    {
        if (!empty($order['subscription_url'])) {
            return (string) $order['subscription_url'];
        }
        if (!empty($order['sub_id'])) {
            return self::buildSubscriptionUrl($serverInfo, (string) $order['sub_id']);
        }
        if (!empty($order['remark'])) {
            $service = new XuiV3Service($serverInfo);
            $subId = $service->getClientSubId((string) $order['remark']);
            if ($subId !== null) {
                return $service->buildSubscriptionUrl($subId);
            }
        }
        return '';
    }

    /**
     * After successful client/inbound creation on panel.
     * @param array<string, mixed> $serverInfo
     * @return array{token:string,uniqid:string,sub_id:string,subLink:string,vray_link:string}
     */
    public static function finalizeOrderDelivery(array $serverInfo, string $remark): array
    {
        $service = new XuiV3Service($serverInfo);
        $subId = $service->getClientSubId($remark) ?? RandomString(16);
        $subLink = $service->buildSubscriptionUrl($subId);
        return [
            'token' => RandomString(30),
            'uniqid' => $remark,
            'sub_id' => $subId,
            'subLink' => $subLink,
            'vray_link' => json_encode([$subLink]),
        ];
    }

    public static function formatCustomerMessage(string $remark, string $subLink): string
    {
        global $mainValues;
        $template = $mainValues['subscription_delivery_message'] ?? '';
        if ($template === '') {
            $template = "🔮 REMARK\n\n🔗 لینک سابسکریپشن شما:\n<code>SUB-LINK</code>\n\n📱 لینک را در برنامه VPN (v2rayNG، Streisand، Hiddify و...) در بخش Subscription اضافه کنید.\n🔄 برای دریافت سرورهای جدید، یک‌بار Update/Refresh بزنید.";
        }
        return str_replace(['REMARK', 'SUB-LINK'], [$remark, $subLink], $template);
    }

    public static function sendToUser($chatId, string $remark, string $subLink, $keyboard = null, bool $withQr = true): void
    {
        global $botUrl, $ecc, $pixel_Size, $frame_Size;

        $accText = self::formatCustomerMessage($remark, $subLink);
        $keyboardJson = is_string($keyboard) ? $keyboard : json_encode($keyboard);

        if (!$withQr || empty($subLink)) {
            sendMessage($accText, $keyboardJson, 'HTML', $chatId);
            return;
        }

        if (!class_exists('QRcode', false)) {
            require_once __DIR__ . '/../phpqrcode/qrlib.php';
        }

        $file = RandomString() . '.png';
        $eccLevel = $ecc ?? 'L';
        $pixelSize = $pixel_Size ?? 11;
        $frameSize = $frame_Size ?? 0;
        QRcode::png($subLink, $file, $eccLevel, $pixelSize, $frameSize);
        addBorderImage($file);
        applyQrBackground($file);

        sendPhoto($botUrl . $file, $accText, $keyboardJson, 'HTML', $chatId);
        if (file_exists($file)) {
            unlink($file);
        }
    }

    /**
     * @param array<string, mixed> $serverInfo
     * @return array{subLink:string,vray_link:string,token:string,uniqid:string,sub_id:string}
     */
    public static function preparePurchaseDelivery(array $serverInfo, string $serverType, string $remark, $panelResponse, string $uniqid, int $inbound_id, array $extra = []): array
    {
        if ($serverType === 'pasarguard') {
            $panelUrl = (string) ($serverInfo['panel_url'] ?? ($panelUrl ?? ''));
            $raw = (string) (($panelResponse->vray_links[0] ?? '') ?: ($panelResponse->sub_link ?? ''));
            if ($raw === '' && $remark !== '') {
                $user = getPasarguardUser((int) ($serverInfo['id'] ?? 0), $remark);
                if (is_object($user) && !empty($user->subscription_url)) {
                    $raw = (string) $user->subscription_url;
                }
            }
            $subLink = PasarguardConfig::buildSubscriptionUrl($panelUrl, $raw);
            $token = PasarguardConfig::extractSubToken($panelUrl, $raw);
            if ($token === '' && !empty($panelResponse->sub_link)) {
                $token = str_replace('/sub/', '', (string) $panelResponse->sub_link);
            }

            return [
                'subLink' => $subLink,
                'vray_link' => json_encode($subLink !== '' ? [$subLink] : []),
                'token' => $token,
                'uniqid' => $token,
                'sub_id' => $token,
            ];
        }
        if ($serverType === 'marzban') {
            global $botState, $panelUrl;
            $token = str_replace('/sub/', '', (string) ($panelResponse->sub_link ?? ''));
            $subLink = ($botState['subLinkState'] ?? 'off') === 'on'
                ? rtrim($panelUrl, '/') . (string) ($panelResponse->sub_link ?? '')
                : '';
            $links = $panelResponse->vray_links ?? [];
            if (empty($links) && $subLink !== '') {
                $links = [$subLink];
            }

            return [
                'subLink' => $subLink,
                'vray_link' => json_encode($links),
                'token' => $token,
                'uniqid' => $token,
                'sub_id' => $token,
            ];
        }

        return self::finalizeOrderDelivery($serverInfo, $remark);
    }

    public static function containsRawConfig(string $text): bool
    {
        foreach (self::$rawConfigPatterns as $pattern) {
            if (stripos($text, $pattern) !== false) {
                return true;
            }
        }
        return false;
    }
}
