<?php
require_once '../config/database.php';
require_once 'phonepe_config.php';

function walletJson(array $data, int $statusCode = 200): void {
    http_response_code($statusCode);
    echo json_encode($data);
    exit;
}

function walletReadInput(): array {
    $input = json_decode(file_get_contents('php://input'), true);
    return is_array($input) ? $input : [];
}

function walletEnsureSchema(PDO $pdo): void {
    $pdo->exec("
        CREATE TABLE IF NOT EXISTS user_wallets (
            id INT AUTO_INCREMENT PRIMARY KEY,
            user_id INT NOT NULL UNIQUE,
            balance DECIMAL(10,2) NOT NULL DEFAULT 0.00,
            currency VARCHAR(3) DEFAULT 'INR',
            status ENUM('active','suspended','closed') DEFAULT 'active',
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            INDEX idx_balance (balance),
            INDEX idx_status (status)
        )
    ");

    $pdo->exec("
        CREATE TABLE IF NOT EXISTS wallet_transactions (
            id INT AUTO_INCREMENT PRIMARY KEY,
            user_id INT NOT NULL,
            type ENUM('credit','debit','transfer') NOT NULL,
            amount DECIMAL(10,2) NOT NULL,
            description VARCHAR(255) DEFAULT NULL,
            payment_method VARCHAR(100) DEFAULT NULL,
            transaction_time DATETIME NULL,
            balance_after DECIMAL(10,2) NOT NULL DEFAULT 0.00,
            transaction_id VARCHAR(100) DEFAULT NULL,
            reference_id VARCHAR(100) DEFAULT NULL,
            status ENUM('pending','completed','failed','cancelled') DEFAULT 'completed',
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            INDEX idx_user_id (user_id),
            INDEX idx_created_at (created_at)
        )
    ");

    foreach ([
        "ALTER TABLE wallet_transactions ADD COLUMN transaction_time DATETIME NULL",
        "ALTER TABLE wallet_transactions ADD COLUMN transaction_id VARCHAR(100) DEFAULT NULL",
        "ALTER TABLE wallet_transactions ADD COLUMN reference_id VARCHAR(100) DEFAULT NULL",
        "ALTER TABLE wallet_transactions ADD COLUMN status ENUM('pending','completed','failed','cancelled') DEFAULT 'completed'",
        "ALTER TABLE wallet_transactions ADD INDEX idx_transaction_id (transaction_id)",
        "ALTER TABLE wallet_transactions ADD INDEX idx_status (status)"
    ] as $sql) {
        try { $pdo->exec($sql); } catch (Exception $e) {}
    }
}

function walletCurrentBalance(PDO $pdo, int $userId): float {
    $stmt = $pdo->prepare("
        SELECT COALESCE(SUM(
            CASE
                WHEN type = 'credit' AND status = 'completed' THEN amount
                WHEN type = 'debit' AND status = 'completed' THEN -amount
                ELSE 0
            END
        ), 0) AS balance
        FROM wallet_transactions
        WHERE user_id = ?
    ");
    $stmt->execute([$userId]);
    return (float)($stmt->fetchColumn() ?: 0);
}

function walletSyncUserBalance(PDO $pdo, int $userId, float $balance): void {
    $stmt = $pdo->prepare("
        INSERT INTO user_wallets (user_id, balance, currency, status)
        VALUES (?, ?, 'INR', 'active')
        ON DUPLICATE KEY UPDATE balance = VALUES(balance), status = 'active', updated_at = NOW()
    ");
    $stmt->execute([$userId, $balance]);
}

function walletPhonePeEnvironment(): string {
    return strtoupper(PhonePeConfig::ENVIRONMENT) === 'PRODUCTION' ? 'PRODUCTION' : 'SANDBOX';
}

function walletPhonePeAuthUrl(): string {
    return walletPhonePeEnvironment() === 'PRODUCTION'
        ? 'https://api.phonepe.com/apis/identity-manager/v1/oauth/token'
        : 'https://api-preprod.phonepe.com/apis/pg-sandbox/v1/oauth/token';
}

function walletPhonePeCheckoutBase(): string {
    return walletPhonePeEnvironment() === 'PRODUCTION'
        ? 'https://api.phonepe.com/apis/pg/checkout/v2'
        : 'https://api-preprod.phonepe.com/apis/pg-sandbox/checkout/v2';
}

function walletHttpPostForm(string $url, array $fields): array {
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'],
        CURLOPT_POSTFIELDS => http_build_query($fields),
        CURLOPT_TIMEOUT => 30,
        CURLOPT_CONNECTTIMEOUT => 10
    ]);
    $body = curl_exec($ch);
    $code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = $body === false ? curl_error($ch) : null;
    curl_close($ch);
    return [json_decode((string)$body, true), $code, $error, $body];
}

function walletHttpJson(string $method, string $url, array $payload = null, array $headers = []): array {
    $ch = curl_init($url);
    $opts = [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => array_merge(['Content-Type: application/json'], $headers),
        CURLOPT_TIMEOUT => 30,
        CURLOPT_CONNECTTIMEOUT => 10
    ];
    if ($method === 'POST') {
        $opts[CURLOPT_POST] = true;
        $opts[CURLOPT_POSTFIELDS] = json_encode($payload ?: [], JSON_UNESCAPED_SLASHES);
    }
    curl_setopt_array($ch, $opts);
    $body = curl_exec($ch);
    $code = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = $body === false ? curl_error($ch) : null;
    curl_close($ch);
    return [json_decode((string)$body, true), $code, $error, $body];
}

function walletPhonePeAuthToken(): string {
    $creds = PhonePeConfig::getClientCredentials();
    [$resp, $code, $error] = walletHttpPostForm(walletPhonePeAuthUrl(), [
        'client_id' => $creds['client_id'],
        'client_secret' => $creds['client_secret'],
        'client_version' => $creds['client_version'],
        'grant_type' => 'client_credentials'
    ]);

    if ($error || $code < 200 || $code >= 300 || empty($resp['access_token'])) {
        throw new Exception('PhonePe auth failed');
    }
    return (string)$resp['access_token'];
}

function walletCreatePhonePeSdkOrder(float $amount, int $userId, string $merchantOrderId): array {
    $amountPaise = (int)round($amount * 100);
    $token = walletPhonePeAuthToken();
    $payload = [
        'merchantOrderId' => $merchantOrderId,
        'amount' => $amountPaise,
        'expireAfter' => 1200,
        'metaInfo' => [
            'udf1' => 'wallet_recharge',
            'udf2' => (string)$userId
        ],
        'paymentFlow' => ['type' => 'PG_CHECKOUT']
    ];

    [$resp, $code, $error, $raw] = walletHttpJson(
        'POST',
        walletPhonePeCheckoutBase() . '/sdk/order',
        $payload,
        ['Authorization: O-Bearer ' . $token]
    );

    $data = is_array($resp['data'] ?? null) ? $resp['data'] : $resp;
    if ($error || $code < 200 || $code >= 300 || empty($data['token']) || empty($data['orderId'])) {
        throw new Exception('PhonePe order create failed: HTTP ' . $code);
    }

    return [
        'raw' => $resp,
        'raw_body' => $raw,
        'order_id' => (string)$data['orderId'],
        'token' => (string)$data['token'],
        'payment_request' => json_encode([
            'orderId' => (string)$data['orderId'],
            'merchantId' => PhonePeConfig::getMerchantId(),
            'token' => (string)$data['token'],
            'paymentMode' => ['type' => 'PAY_PAGE']
        ], JSON_UNESCAPED_SLASHES)
    ];
}

function walletCheckPhonePeOrderStatus(string $merchantOrderId): array {
    $token = walletPhonePeAuthToken();
    [$resp, $code, $error, $raw] = walletHttpJson(
        'GET',
        walletPhonePeCheckoutBase() . '/order/' . rawurlencode($merchantOrderId) . '/status?details=false&errorContext=true',
        null,
        ['Authorization: O-Bearer ' . $token]
    );
    if ($error || $code < 200 || $code >= 300) {
        throw new Exception('PhonePe status check failed: HTTP ' . $code);
    }

    $data = is_array($resp['data'] ?? null) ? $resp['data'] : $resp;
    $state = strtoupper((string)($data['state'] ?? $data['status'] ?? 'PENDING'));
    return ['state' => $state, 'response' => $resp, 'raw_body' => $raw];
}
?>
