<?php
/**
 * سودانا — RiskEngine v1
 * Detects anomalies + assigns risk levels
 * OUTPUT: risk_level (low/medium/high/critical) + reasons + action
 */
class RiskEngine {

    // Risk thresholds
    const LARGE_TXN_SDG     = 5000;    // single txn > 5000 SDG = elevated
    const VELOCITY_1H       = 5;       // >5 txns in 1 hour = velocity alert
    const VELOCITY_24H      = 20;      // >20 txns in 24h = high velocity
    const DUPLICATE_WINDOW  = 300;     // 5 min window for duplicate detection

    /**
     * Assess risk for a payment attempt
     */
    public static function assess(int $userId, float $amount, string $service = ''): array {
        $reasons    = [];
        $riskScore  = 0;
        $traceId    = uniqid('rsk_', true);

        try {
            // 1. Large transaction check
            if ($amount >= self::LARGE_TXN_SDG) {
                $riskScore += 30;
                $reasons[] = "large_transaction: {$amount} SDG";
            }

            // 2. Velocity check — transactions in last hour
            $v1h = (int)db()->prepare(
                "SELECT COUNT(*) FROM wallet_transactions
                 WHERE user_id=? AND created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)"
            )->execute([$userId]) ? db()->query(
                "SELECT COUNT(*) FROM wallet_transactions
                 WHERE user_id=$userId AND created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)"
            )->fetchColumn() : 0;

            $v1hQ = db()->prepare(
                "SELECT COUNT(*) FROM wallet_transactions
                 WHERE user_id=? AND created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)"
            );
            $v1hQ->execute([$userId]);
            $v1h = (int)$v1hQ->fetchColumn();

            if ($v1h >= self::VELOCITY_1H) {
                $riskScore += 25;
                $reasons[] = "velocity_1h: $v1h transactions";
            }

            // 3. Velocity check — 24 hours
            $v24hQ = db()->prepare(
                "SELECT COUNT(*) FROM wallet_transactions
                 WHERE user_id=? AND created_at > DATE_SUB(NOW(), INTERVAL 24 HOUR)"
            );
            $v24hQ->execute([$userId]);
            $v24h = (int)$v24hQ->fetchColumn();

            if ($v24h >= self::VELOCITY_24H) {
                $riskScore += 20;
                $reasons[] = "velocity_24h: $v24h transactions";
            }

            // 4. Failed invoices recently
            $failQ = db()->prepare(
                "SELECT COUNT(*) FROM invoices
                 WHERE user_id=? AND status='rejected'
                   AND updated_at > DATE_SUB(NOW(), INTERVAL 7 DAY)"
            );
            $failQ->execute([$userId]);
            $fails = (int)$failQ->fetchColumn();
            if ($fails >= 3) {
                $riskScore += 20;
                $reasons[] = "repeated_failures: $fails rejected invoices";
            }

            // 5. New user with high amount
            $joinedQ = db()->prepare(
                "SELECT DATEDIFF(NOW(), created_at) FROM users WHERE id=?"
            );
            $joinedQ->execute([$userId]);
            $accountAgeDays = (int)$joinedQ->fetchColumn();
            if ($accountAgeDays < 7 && $amount > 1000) {
                $riskScore += 15;
                $reasons[] = "new_account_large_txn: age={$accountAgeDays}d amount={$amount}";
            }

            // Determine level
            $level = match(true) {
                $riskScore >= 70 => 'critical',
                $riskScore >= 40 => 'high',
                $riskScore >= 20 => 'medium',
                default          => 'low',
            };

            $action = match($level) {
                'critical' => 'block',
                'high'     => 'review',
                'medium'   => 'flag',
                default    => 'allow',
            };

            $result = [
                'risk_level'  => $level,
                'risk_score'  => $riskScore,
                'action'      => $action,
                'reasons'     => $reasons,
                'user_id'     => $userId,
                'amount'      => $amount,
                'service'     => $service,
                'trace_id'    => $traceId,
                'assessed_at' => date('Y-m-d H:i:s'),
            ];

            // Log to audit_logs
            self::logAssessment($result);

            return $result;

        } catch (Throwable $e) {
            error_log("[RiskEngine] " . $e->getMessage());
            return [
                'risk_level' => 'medium',
                'action'     => 'flag',
                'reasons'    => ['assessment_error'],
                'error'      => $e->getMessage(),
                'trace_id'   => $traceId,
            ];
        }
    }

    private static function logAssessment(array $r): void {
        try {
            db()->prepare(
                "INSERT INTO audit_logs (action, entity_type, entity_id, data, created_at)
                 VALUES ('risk.assessment','user',?,?,NOW())"
            )->execute([$r['user_id'], json_encode($r, JSON_UNESCAPED_UNICODE)]);
        } catch (Throwable $e) {
            error_log("[RiskEngine::log] " . $e->getMessage());
        }
    }
}
