<?php
/**
 * Central discount engine for Mini App APIs.
 * Backend is the source of truth: frontend validation is only a preview.
 */

function gemacc_normalize_discount_code($code): string {
    return strtoupper(trim((string)$code));
}

function gemacc_discount_preview(PDO $pdo, int $userId, string $code, int $purchaseAmount, int $planId = 0, string $paymentMethod = 'all'): array {
    $code = gemacc_normalize_discount_code($code);
    if ($code === '') return ['valid' => false, 'message' => 'کد تخفیف وارد نشده است', 'discount_amount' => 0, 'final_price' => $purchaseAmount];

    $stmt = $pdo->prepare("SELECT * FROM discount_codes WHERE code = ? LIMIT 1");
    $stmt->execute([$code]);
    $discount = $stmt->fetch(PDO::FETCH_ASSOC);
    if (!$discount) return ['valid' => false, 'message' => 'کد تخفیف یافت نشد', 'discount_amount' => 0, 'final_price' => $purchaseAmount];
    if ((int)$discount['is_active'] !== 1) return ['valid' => false, 'message' => 'کد تخفیف غیرفعال است', 'discount_amount' => 0, 'final_price' => $purchaseAmount];
    if (!empty($discount['valid_from']) && strtotime((string)$discount['valid_from']) > time()) return ['valid' => false, 'message' => 'کد تخفیف هنوز فعال نشده', 'discount_amount' => 0, 'final_price' => $purchaseAmount];
    if (!empty($discount['valid_until']) && strtotime((string)$discount['valid_until']) < time()) return ['valid' => false, 'message' => 'کد تخفیف منقضی شده', 'discount_amount' => 0, 'final_price' => $purchaseAmount];
    if ($discount['max_uses'] !== null && (int)$discount['used_count'] >= (int)$discount['max_uses']) return ['valid' => false, 'message' => 'ظرفیت استفاده از این کد تمام شده', 'discount_amount' => 0, 'final_price' => $purchaseAmount];

    $paymentMethod = strtolower(trim($paymentMethod ?: 'all'));
    $scope = strtolower(trim((string)($discount['payment_scope'] ?? 'all')));
    if ($scope === '') $scope = 'all';
    $aliases = ['card'=>'card','cart'=>'card','bank'=>'card','crypto'=>'crypto','plisio'=>'crypto','manual_crypto'=>'crypto','all'=>'all','both'=>'all'];
    $method = $aliases[$paymentMethod] ?? $paymentMethod;
    $scope = $aliases[$scope] ?? $scope;
    if ($scope !== 'all' && $method !== 'all' && $scope !== $method) {
        $msg = $scope === 'crypto' ? 'این کد تخفیف فقط برای پرداخت ارز دیجیتال معتبر است.' : 'این کد تخفیف فقط برای کارت به کارت معتبر است.';
        return ['valid' => false, 'message' => $msg, 'discount_amount' => 0, 'final_price' => $purchaseAmount];
    }

    $stmt = $pdo->prepare("SELECT COUNT(*) FROM discount_usages WHERE discount_id = ? AND user_id = ?");
    $stmt->execute([(int)$discount['id'], $userId]);
    $userUsage = (int)$stmt->fetchColumn();
    if ($userUsage >= max(1, (int)$discount['max_uses_per_user'])) return ['valid' => false, 'message' => 'شما قبلاً از این کد استفاده کرده‌اید', 'discount_amount' => 0, 'final_price' => $purchaseAmount];

    if ((int)$discount['min_purchase'] > 0 && $purchaseAmount < (int)$discount['min_purchase']) {
        return ['valid' => false, 'message' => 'حداقل مبلغ خرید برای این کد ' . number_format((int)$discount['min_purchase']) . ' تومان است', 'discount_amount' => 0, 'final_price' => $purchaseAmount];
    }

    if (strtoupper((string)$discount['type']) === 'PERCENT') {
        $discountAmount = (int)floor($purchaseAmount * (int)$discount['value'] / 100);
        if ($discount['max_discount'] !== null && $discountAmount > (int)$discount['max_discount']) $discountAmount = (int)$discount['max_discount'];
    } else {
        $discountAmount = min((int)$discount['value'], $purchaseAmount);
    }
    $discountAmount = max(0, min($discountAmount, $purchaseAmount));
    return [
        'valid' => true,
        'message' => 'کد تخفیف معتبر است',
        'discount' => $discount,
        'discount_id' => (int)$discount['id'],
        'discount_code' => $code,
        'discount_type' => (string)$discount['type'],
        'discount_value' => (int)$discount['value'],
        'discount_amount' => $discountAmount,
        'original_price' => $purchaseAmount,
        'final_price' => max(0, $purchaseAmount - $discountAmount),
    ];
}

function gemacc_discount_apply(PDO $pdo, array $preview, int $userId, int $orderId): void {
    if (empty($preview['valid']) || empty($preview['discount_id']) || (int)$preview['discount_amount'] <= 0) return;
    $discountId = (int)$preview['discount_id'];

    $stmt = $pdo->prepare("SELECT COUNT(*) FROM discount_usages WHERE discount_id=? AND user_id=? AND order_id=?");
    $stmt->execute([$discountId, $userId, $orderId]);
    if ((int)$stmt->fetchColumn() > 0) return;

    $stmt = $pdo->prepare("SELECT * FROM discount_codes WHERE id=? FOR UPDATE");
    $stmt->execute([$discountId]);
    $discount = $stmt->fetch(PDO::FETCH_ASSOC);
    if (!$discount || (int)$discount['is_active'] !== 1) throw new RuntimeException('کد تخفیف دیگر معتبر نیست');
    if ($discount['max_uses'] !== null && (int)$discount['used_count'] >= (int)$discount['max_uses']) throw new RuntimeException('ظرفیت استفاده از کد تخفیف تمام شده است');

    $stmt = $pdo->prepare("SELECT COUNT(*) FROM discount_usages WHERE discount_id=? AND user_id=?");
    $stmt->execute([$discountId, $userId]);
    if ((int)$stmt->fetchColumn() >= max(1, (int)$discount['max_uses_per_user'])) throw new RuntimeException('این کد قبلاً برای این کاربر مصرف شده است');

    $stmt = $pdo->prepare("INSERT INTO discount_usages(discount_id, user_id, order_id, discount_amount) VALUES(?,?,?,?)");
    $stmt->execute([$discountId, $userId, $orderId, (int)$preview['discount_amount']]);
    $pdo->prepare("UPDATE discount_codes SET used_count=used_count+1 WHERE id=?")->execute([$discountId]);
    try {
        $code = (string)($discount['code'] ?? '');
        if ($code !== '') {
            $pdo->prepare("UPDATE user_discount_codes SET used_at=COALESCE(used_at,NOW()) WHERE user_id=? AND code=? AND used_at IS NULL")->execute([$userId, $code]);
        }
    } catch (Throwable $ignored) {}
}

function gemacc_idempotency_begin(PDO $pdo, int $userId, string $requestId, string $scope): ?array {
    $requestId = trim($requestId);
    if ($requestId === '') return null;
    $pdo->exec("CREATE TABLE IF NOT EXISTS payment_idempotency (
        id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
        user_id BIGINT NOT NULL,
        request_id VARCHAR(128) NOT NULL,
        scope VARCHAR(40) NOT NULL,
        order_id INT UNSIGNED DEFAULT NULL,
        status VARCHAR(30) NOT NULL DEFAULT 'processing',
        response_json LONGTEXT DEFAULT NULL,
        created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
        updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
        PRIMARY KEY(id),
        UNIQUE KEY uniq_payment_request(user_id, request_id, scope)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci");
    try {
        $stmt = $pdo->prepare("INSERT INTO payment_idempotency(user_id, request_id, scope, status) VALUES(?,?,?,'processing')");
        $stmt->execute([$userId, $requestId, $scope]);
        return null;
    } catch (PDOException $e) {
        $stmt = $pdo->prepare("SELECT * FROM payment_idempotency WHERE user_id=? AND request_id=? AND scope=? LIMIT 1");
        $stmt->execute([$userId, $requestId, $scope]);
        $row = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($row) return $row;
        throw $e;
    }
}

function gemacc_idempotency_finish(PDO $pdo, int $userId, string $requestId, string $scope, ?int $orderId, array $response): void {
    if (trim($requestId) === '') return;
    $stmt = $pdo->prepare("UPDATE payment_idempotency SET order_id=?, status='completed', response_json=? WHERE user_id=? AND request_id=? AND scope=?");
    $stmt->execute([$orderId, json_encode($response, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), $userId, $requestId, $scope]);
}
