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

function liveCallJson($data, int $statusCode = 200) {
    http_response_code($statusCode);
    echo json_encode($data);
    exit;
}

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

function liveCallEnsureSchema(PDO $pdo): void {
    try {
        $pdo->exec("
            ALTER TABLE settings
            ADD COLUMN updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
        ");
    } catch (Exception $e) {}

    try {
        $pdo->exec("
            ALTER TABLE wallet_transactions
            ADD COLUMN transaction_id VARCHAR(100) NULL
        ");
    } catch (Exception $e) {}
    try {
        $pdo->exec("
            ALTER TABLE wallet_transactions
            ADD COLUMN reference_id VARCHAR(100) NULL
        ");
    } catch (Exception $e) {}
    try {
        $pdo->exec("
            ALTER TABLE wallet_transactions
            ADD COLUMN status ENUM('pending','completed','failed','cancelled') DEFAULT 'completed'
        ");
    } catch (Exception $e) {}

    $pdo->exec("
        CREATE TABLE IF NOT EXISTS live_call_sessions (
            id INT AUTO_INCREMENT PRIMARY KEY,
            user_id INT NOT NULL,
            call_type ENUM('audio','video') NOT NULL DEFAULT 'audio',
            channel_name VARCHAR(120) NOT NULL UNIQUE,
            agora_uid INT NOT NULL,
            guru_uid INT NOT NULL DEFAULT 1,
            status ENUM('requested','ringing','active','ended','cancelled','rejected') NOT NULL DEFAULT 'requested',
            rate_per_minute DECIMAL(10,2) NOT NULL DEFAULT 0.00,
            billed_seconds INT NOT NULL DEFAULT 0,
            charged_amount DECIMAL(10,2) NOT NULL DEFAULT 0.00,
            started_at DATETIME NULL,
            accepted_at DATETIME NULL,
            ended_at DATETIME NULL,
            last_heartbeat_at DATETIME NULL,
            end_reason VARCHAR(120) NULL,
            admin_extension_seconds INT NOT NULL DEFAULT 0,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            INDEX idx_user_status (user_id, status),
            INDEX idx_status_created (status, created_at)
        )
    ");

    $pdo->exec("
        CREATE TABLE IF NOT EXISTS live_call_queue (
            id INT AUTO_INCREMENT PRIMARY KEY,
            user_id INT NOT NULL,
            call_type ENUM('audio','video') NOT NULL DEFAULT 'audio',
            status ENUM('waiting','notified','cancelled','served') NOT NULL DEFAULT 'waiting',
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
            INDEX idx_status_created (status, created_at),
            INDEX idx_user_status (user_id, status)
        )
    ");

    $defaults = [
        'live_call_system_enabled' => 'off',
        'guru_online' => 'off',
        'live_call_audio_enabled' => 'on',
        'live_call_video_enabled' => 'on',
        'live_call_min_first_call_balance' => '200',
        'live_call_min_wallet_balance' => '100',
        'live_call_audio_rate_per_minute' => '20',
        'live_call_video_rate_per_minute' => '40',
        'live_call_agora_app_id' => '77b22a46a8c145d6a4a34d3037b5458e',
        'live_call_agora_app_certificate' => getenv('AGORA_APP_CERTIFICATE') ?: '',
        'live_call_tick_seconds' => '10',
        'onesignal_app_id' => 'a01cd132-bad1-4232-af31-758875b68abd',
        'onesignal_rest_api_key' => getenv('ONESIGNAL_REST_API_KEY') ?: ''
    ];

    $stmt = $pdo->prepare("
        INSERT IGNORE INTO settings (setting_key, setting_value)
        VALUES (?, ?)
    ");
    foreach ($defaults as $key => $value) {
        $stmt->execute([$key, $value]);
    }
}

function liveCallSettings(PDO $pdo): array {
    liveCallEnsureSchema($pdo);
    $fallbacks = [
        'live_call_agora_app_id' => '77b22a46a8c145d6a4a34d3037b5458e',
        'live_call_agora_app_certificate' => getenv('AGORA_APP_CERTIFICATE') ?: '',
        'onesignal_app_id' => 'a01cd132-bad1-4232-af31-758875b68abd',
        'onesignal_rest_api_key' => getenv('ONESIGNAL_REST_API_KEY') ?: ''
    ];
    $keys = [
        'live_call_system_enabled',
        'guru_online',
        'live_call_audio_enabled',
        'live_call_video_enabled',
        'live_call_min_first_call_balance',
        'live_call_min_wallet_balance',
        'live_call_audio_rate_per_minute',
        'live_call_video_rate_per_minute',
        'live_call_agora_app_id',
        'live_call_agora_app_certificate',
        'live_call_tick_seconds',
        'onesignal_app_id',
        'onesignal_rest_api_key'
    ];

    $placeholders = implode(',', array_fill(0, count($keys), '?'));
    $stmt = $pdo->prepare("SELECT setting_key, setting_value FROM settings WHERE setting_key IN ($placeholders)");
    $stmt->execute($keys);

    $settings = [];
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $settings[$row['setting_key']] = $row['setting_value'];
    }

    foreach ($fallbacks as $key => $value) {
        if (!isset($settings[$key]) || trim((string)$settings[$key]) === '') {
            $settings[$key] = $value;
        }
    }

    return $settings;
}

function liveCallSaveSetting(PDO $pdo, string $key, string $value): void {
    $stmt = $pdo->prepare("
        INSERT INTO settings (setting_key, setting_value)
        VALUES (?, ?)
        ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value)
    ");
    $stmt->execute([$key, $value]);
}

function liveCallBool($value): bool {
    return in_array(strtolower((string)$value), ['1', 'on', 'true', 'yes', 'enabled'], true);
}

function liveCallBuildAgoraToken(string $appId, string $appCertificate, string $channelName, int $uid, int $ttlSeconds = 86400): ?string {
    $appId = trim($appId);
    $appCertificate = trim($appCertificate);
    $channelName = trim($channelName);
    if (!preg_match('/^[a-f0-9]{32}$/i', $appId)
        || !preg_match('/^[a-f0-9]{32}$/i', $appCertificate)
        || $channelName === '') {
        return null;
    }

    $expireIn = max(60, $ttlSeconds);
    $privileges = [
        1 => $expireIn, // Join channel
        2 => $expireIn, // Publish audio
        3 => $expireIn, // Publish video
        4 => $expireIn  // Publish data stream
    ];

    $issueTs = time();
    $salt = random_int(1, 99999999);
    $serviceRtc = pack('v', 1);
    $serviceRtc .= pack('v', count($privileges));
    foreach ($privileges as $key => $value) {
        $serviceRtc .= pack('v', $key);
        $serviceRtc .= pack('V', $value);
    }
    $serviceRtc .= pack('v', strlen($channelName)) . $channelName;
    $uidString = (string)$uid;
    $serviceRtc .= pack('v', strlen($uidString)) . $uidString;

    $data = pack('v', strlen($appId)) . $appId;
    $data .= pack('V', $issueTs);
    $data .= pack('V', $expireIn);
    $data .= pack('V', $salt);
    $data .= pack('v', 1) . $serviceRtc;

    $signing = hash_hmac('sha256', $appCertificate, pack('V', $issueTs), true);
    $signing = hash_hmac('sha256', $signing, pack('V', $salt), true);
    $signature = hash_hmac('sha256', $data, $signing, true);
    $content = pack('v', strlen($signature)) . $signature . $data;

    $packed = zlib_encode($content, ZLIB_ENCODING_DEFLATE);
    return $packed === false ? null : '007' . base64_encode($packed);
}

function liveCallAgoraToken(array $settings, string $channelName, int $uid, int $ttlSeconds = 86400): ?string {
    return liveCallBuildAgoraToken(
        (string)($settings['live_call_agora_app_id'] ?? ''),
        (string)($settings['live_call_agora_app_certificate'] ?? ''),
        $channelName,
        $uid,
        $ttlSeconds
    );
}

function liveCallBalance(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 liveCallUserHasCompletedCall(PDO $pdo, int $userId): bool {
    $stmt = $pdo->prepare("
        SELECT COUNT(*)
        FROM live_call_sessions
        WHERE user_id = ? AND status = 'ended' AND billed_seconds > 0
    ");
    $stmt->execute([$userId]);
    return (int)$stmt->fetchColumn() > 0;
}

function liveCallActiveSession(PDO $pdo): ?array {
    $stmt = $pdo->query("
        SELECT s.*, u.name AS user_name, u.mobile AS user_mobile
        FROM live_call_sessions s
        LEFT JOIN users u ON u.id = s.user_id
        WHERE s.status IN ('requested','ringing','active')
        ORDER BY s.created_at ASC
        LIMIT 1
    ");
    $session = $stmt->fetch(PDO::FETCH_ASSOC);
    return $session ?: null;
}

function liveCallSessionById(PDO $pdo, int $sessionId): ?array {
    $stmt = $pdo->prepare("
        SELECT s.*, u.name AS user_name, u.mobile AS user_mobile
        FROM live_call_sessions s
        LEFT JOIN users u ON u.id = s.user_id
        WHERE s.id = ?
    ");
    $stmt->execute([$sessionId]);
    $session = $stmt->fetch(PDO::FETCH_ASSOC);
    return $session ?: null;
}

function liveCallDebit(PDO $pdo, int $userId, float $amount, int $sessionId): float {
    $currentBalance = liveCallBalance($pdo, $userId);
    if ($amount <= 0) {
        return $currentBalance;
    }
    if ($currentBalance < $amount) {
        return $currentBalance;
    }

    $newBalance = $currentBalance - $amount;
    $stmt = $pdo->prepare("
        INSERT INTO wallet_transactions (
            user_id, type, amount, description, payment_method,
            balance_after, transaction_id, reference_id, status, created_at
        ) VALUES (?, 'debit', ?, ?, 'Live Call', ?, ?, ?, 'completed', NOW())
    ");
    $stmt->execute([
        $userId,
        $amount,
        'Live call billing',
        $newBalance,
        'CALL_' . $sessionId . '_' . time(),
        (string)$sessionId
    ]);

    return $newBalance;
}

function liveCallNotifyGuruOnline(PDO $pdo): array {
    $result = [
        'logged_notifications' => 0,
        'onesignal_sent' => false,
        'onesignal_http_code' => null,
        'onesignal_response' => null,
        'onesignal_error' => null
    ];

    try {
        $settings = liveCallSettings($pdo);
        $pdo->exec("
            CREATE TABLE IF NOT EXISTS push_notifications (
                id INT AUTO_INCREMENT PRIMARY KEY,
                user_id INT NULL,
                title VARCHAR(255) NOT NULL,
                body TEXT NOT NULL,
                device_token VARCHAR(500) NULL,
                status VARCHAR(50) DEFAULT 'sent',
                created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
            )
        ");

        $stmt = $pdo->query("SELECT id, device_token FROM users WHERE device_token IS NOT NULL AND device_token != ''");
        $users = $stmt->fetchAll(PDO::FETCH_ASSOC);
        $insert = $pdo->prepare("
            INSERT INTO push_notifications (user_id, title, body, device_token, status, created_at)
            VALUES (?, ?, ?, ?, 'pending', NOW())
        ");
        foreach ($users as $user) {
            $insert->execute([
                $user['id'],
                'Guruji is online / गुरुजी ऑनलाइन हैं',
                'Audio aur video call ke liye Guruji ab available hain.',
                $user['device_token']
            ]);
            $result['logged_notifications']++;
        }

        $oneSignalAppId = trim($settings['onesignal_app_id'] ?? '');
        $oneSignalKey = trim($settings['onesignal_rest_api_key'] ?? '');
        if ($oneSignalAppId !== '' && $oneSignalKey !== '') {
            $payload = json_encode([
                'app_id' => $oneSignalAppId,
                'target_channel' => 'push',
                'included_segments' => ['Subscribed Users'],
                'headings' => [
                    'en' => 'Guruji is online',
                    'hi' => 'गुरुजी ऑनलाइन हैं'
                ],
                'contents' => [
                    'en' => 'Guruji is available for live audio and video calls.',
                    'hi' => 'गुरुजी अब लाइव ऑडियो और वीडियो कॉल के लिए उपलब्ध हैं।'
                ],
                'data' => [
                    'type' => 'guru_online'
                ]
            ]);

            $ch = curl_init('https://api.onesignal.com/notifications');
            curl_setopt($ch, CURLOPT_HTTPHEADER, [
                'Content-Type: application/json',
                'Authorization: Key ' . $oneSignalKey
            ]);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
            $response = curl_exec($ch);
            $curlError = curl_error($ch);
            $httpCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
            curl_close($ch);

            $result['onesignal_http_code'] = $httpCode;
            $result['onesignal_response'] = $response;
            $result['onesignal_error'] = $curlError ?: null;
            $result['onesignal_sent'] = $curlError === '' && $httpCode >= 200 && $httpCode < 300;

            $status = $result['onesignal_sent'] ? 'sent' : 'failed';
            $pdo->prepare("
                UPDATE push_notifications
                SET status = ?
                WHERE status = 'pending'
            ")->execute([$status]);
        } else {
            $result['onesignal_error'] = 'OneSignal App ID or REST API key missing';
        }
    } catch (Exception $e) {
        $result['onesignal_error'] = $e->getMessage();
        error_log('Guru online notification failed: ' . $e->getMessage());
    }

    return $result;
}
?>
