<?php

/**

 * AI Payment Predictor

 * Predicts payment behavior, identifies risks, and forecasts revenue

 */



class AIPaymentPredictor extends AIModel {

    private $features = [];

    private $predictions = [];

    

    public function __construct() {

        parent::__construct('payment_predictor', '2.0');

    }

    

    /**

     * Predict payment probability for a student

     */

    public function predictPaymentProbability($studentId, $feeType = null) {

        // Check cache first

        // NEW FIXED CODE:

$feeTypeString = $feeType ?? '';

$cacheKey = AI_PREDICTIONS_CACHE . 'payment_prob_' . $studentId . '_' . md5($feeTypeString) . '.cache';

        if (AI_CACHE_ENABLED && file_exists($cacheKey) && (time() - filemtime($cacheKey)) < AI_CACHE_TTL) {

            return json_decode(file_get_contents($cacheKey), true);

        }

        

        // Extract features for this student

        $features = $this->extractStudentFeatures($studentId, $feeType);

        

        // Calculate probability using logistic regression model

        $probability = $this->calculateProbability($features);

        

        // Get risk factors

        $riskFactors = $this->identifyRiskFactors($studentId, $features);

        

        // Get recommended actions

        $recommendations = $this->generateRecommendations($probability, $riskFactors);

        

        $result = [

            'student_id' => $studentId,

            'payment_probability' => round($probability * 100, 2),

            'risk_level' => $this->getRiskLevel($probability),

            'risk_factors' => $riskFactors,

            'recommendations' => $recommendations,

            'prediction_date' => date('Y-m-d H:i:s'),

            'confidence' => $this->calculateConfidence($features)

        ];

        

        // Cache the result

        if (AI_CACHE_ENABLED) {

            file_put_contents($cacheKey, json_encode($result));

        }

        

        return $result;

    }

    

    /**

     * Predict monthly revenue for the next N months

     */

   /**

 * Predict monthly revenue for the next N months

 */

public function predictMonthlyRevenue($months = 6) {

    $cacheKey = AI_PREDICTIONS_CACHE . 'revenue_forecast_' . $months . '.cache';

    if (AI_CACHE_ENABLED && file_exists($cacheKey) && (time() - filemtime($cacheKey)) < AI_CACHE_TTL) {

        $cached = json_decode(file_get_contents($cacheKey), true);

        if ($cached && isset($cached['forecast'])) {

            return $cached;

        }

    }

    

    // Get historical payment data

    $historicalData = $this->getHistoricalPaymentData();

    

    // Apply time series forecasting (simplified linear regression)

    $forecast = $this->forecastRevenue($historicalData, $months);

    

    // Add seasonal adjustments

    $forecast = $this->applySeasonalAdjustments($forecast);

    

    // Calculate total expected

    $totalExpected = array_sum($forecast);

    

    $result = [

        'forecast' => $forecast,

        'total_expected' => $totalExpected,

        'confidence_interval' => $this->calculateConfidenceInterval($forecast),

        'based_on_months' => count($historicalData),

        'generated_at' => date('Y-m-d H:i:s')

    ];

    

    if (AI_CACHE_ENABLED) {

        file_put_contents($cacheKey, json_encode($result));

    }

    

    return $result;

}

    /**

     * Identify students at risk of default

     */

    public function identifyAtRiskStudents($threshold = 0.5) {

        $cacheKey = AI_PREDICTIONS_CACHE . 'at_risk_students.cache';

        if (AI_CACHE_ENABLED && file_exists($cacheKey) && (time() - filemtime($cacheKey)) < 3600) {

            return json_decode(file_get_contents($cacheKey), true);

        }

        

        $query = "SELECT DISTINCT s.id, s.student_id, s.first_name, s.last_name, s.class, s.parent_name, s.phone

                  FROM students s

                  WHERE s.status = 'active'";

        

        $result = $this->conn->query($query);

        $atRisk = [];

        

        while ($student = $result->fetch_assoc()) {

            $prediction = $this->predictPaymentProbability($student['id']);

            

            if ($prediction['payment_probability'] < ($threshold * 100)) {

                $atRisk[] = [

                    'student' => $student,

                    'probability' => $prediction['payment_probability'],

                    'risk_level' => $prediction['risk_level'],

                    'risk_factors' => $prediction['risk_factors'],

                    'recommendations' => $prediction['recommendations']

                ];

            }

        }

        

        // Sort by probability (lowest first)

        usort($atRisk, function($a, $b) {

            return $a['probability'] - $b['probability'];

        });

        

        if (AI_CACHE_ENABLED) {

            file_put_contents($cacheKey, json_encode($atRisk));

        }

        

        return $atRisk;

    }

    

    /**

     * Extract features for a student

     */

    private function extractStudentFeatures($studentId, $feeType = null) {

        $features = [];

        

        // Payment history features

        $query = "SELECT 

                    COUNT(*) as total_payments,

                    COALESCE(SUM(amount_paid), 0) as total_paid,

                    COALESCE(AVG(amount_paid), 0) as avg_payment,

                    COALESCE(MAX(amount_paid), 0) as max_payment,

                    COUNT(CASE WHEN payment_date < NOW() - INTERVAL 7 DAY THEN 1 END) as late_payments,

                    COALESCE(AVG(DATEDIFF(payment_date, 

                        (SELECT due_date FROM fee_structures WHERE id = p.fee_structure_id))), 0) as avg_delay

                  FROM payments p

                  WHERE p.student_id = ?";

        

        $stmt = $this->conn->prepare($query);

        $stmt->bind_param("i", $studentId);

        $stmt->execute();

        $result = $stmt->get_result();

        $paymentStats = $result->fetch_assoc();

        $stmt->close();

        

        $features['total_payments'] = $paymentStats['total_payments'];

        $features['total_paid'] = $paymentStats['total_paid'];

        $features['avg_payment'] = $paymentStats['avg_payment'];

        $features['late_payment_ratio'] = $paymentStats['total_payments'] > 0 ? 

            $paymentStats['late_payments'] / $paymentStats['total_payments'] : 0;

        $features['avg_delay_days'] = $paymentStats['avg_delay'];

        

        // Outstanding balance

        $query = "SELECT 

                    COALESCE((SELECT SUM(fs.amount) FROM fee_structures fs 

                              WHERE fs.class_name = s.class), 0) as total_expected,

                    COALESCE((SELECT SUM(p.amount_paid) FROM payments p 

                              WHERE p.student_id = s.id), 0) as total_paid

                  FROM students s

                  WHERE s.id = ?";

        

        $stmt = $this->conn->prepare($query);

        $stmt->bind_param("i", $studentId);

        $stmt->execute();

        $result = $stmt->get_result();

        $balanceData = $result->fetch_assoc();

        $stmt->close();

        

        $features['outstanding_balance'] = $balanceData['total_expected'] - $balanceData['total_paid'];

        $features['payment_completion_rate'] = $balanceData['total_expected'] > 0 ? 

            $balanceData['total_paid'] / $balanceData['total_expected'] : 0;

        

        // Time-based features

        $features['days_since_last_payment'] = $this->getDaysSinceLastPayment($studentId);

        $features['payment_frequency'] = $this->calculatePaymentFrequency($studentId);

        

        // Class-based features

        $classQuery = "SELECT class FROM students WHERE id = ?";

        $stmt = $this->conn->prepare($classQuery);

        $stmt->bind_param("i", $studentId);

        $stmt->execute();

        $classResult = $stmt->get_result();

        $studentClass = $classResult->fetch_assoc()['class'];

        $stmt->close();

        

        $features['class_payment_rate'] = $this->getClassPaymentRate($studentClass);

        

        return $features;

    }

    

    /**

     * Calculate payment probability using logistic regression

     */

    private function calculateProbability($features) {

        // Weights learned from training (simplified version)

        $weights = [

            'payment_completion_rate' => 2.5,

            'late_payment_ratio' => -1.8,

            'avg_delay_days' => -0.5,

            'payment_frequency' => 1.2,

            'days_since_last_payment' => -0.3,

            'class_payment_rate' => 1.5,

            'outstanding_balance' => -0.8

        ];

        

        $bias = -0.5;

        $score = $bias;

        

        // Apply weights to normalized features

        if (isset($features['payment_completion_rate'])) {

            $score += $weights['payment_completion_rate'] * $features['payment_completion_rate'];

        }

        

        if (isset($features['late_payment_ratio'])) {

            $score += $weights['late_payment_ratio'] * $features['late_payment_ratio'];

        }

        

        if (isset($features['avg_delay_days'])) {

            $normalizedDelay = min($features['avg_delay_days'] / 30, 1); // Cap at 30 days

            $score += $weights['avg_delay_days'] * $normalizedDelay;

        }

        

        if (isset($features['payment_frequency'])) {

            $score += $weights['payment_frequency'] * $features['payment_frequency'];

        }

        

        if (isset($features['days_since_last_payment'])) {

            $normalizedDays = min($features['days_since_last_payment'] / 60, 1); // Cap at 60 days

            $score += $weights['days_since_last_payment'] * $normalizedDays;

        }

        

        if (isset($features['class_payment_rate'])) {

            $score += $weights['class_payment_rate'] * $features['class_payment_rate'];

        }

        

        if (isset($features['outstanding_balance'])) {

            $normalizedBalance = min($features['outstanding_balance'] / 1000, 1); // Cap at 1000

            $score += $weights['outstanding_balance'] * $normalizedBalance;

        }

        

        // Apply sigmoid function to get probability

        return 1 / (1 + exp(-$score));

    }

    

    /**

     * Identify risk factors for a student

     */

    private function identifyRiskFactors($studentId, $features) {

        $riskFactors = [];

        

        if ($features['late_payment_ratio'] > 0.3) {

            $riskFactors[] = 'High rate of late payments (' . round($features['late_payment_ratio'] * 100) . '%)';

        }

        

        if ($features['avg_delay_days'] > 15) {

            $riskFactors[] = 'Average payment delay of ' . round($features['avg_delay_days']) . ' days';

        }

        

        if ($features['days_since_last_payment'] > 45) {

            $riskFactors[] = 'No payment for ' . $features['days_since_last_payment'] . ' days';

        }

        

        if ($features['outstanding_balance'] > 500) {

            $riskFactors[] = 'High outstanding balance: ' . formatCurrency($features['outstanding_balance']);

        }

        

        if ($features['payment_completion_rate'] < 0.5) {

            $riskFactors[] = 'Low payment completion rate (' . round($features['payment_completion_rate'] * 100) . '%)';

        }

        

        if ($features['class_payment_rate'] < 0.6) {

            $riskFactors[] = 'Class has generally low payment rate';

        }

        

        return $riskFactors;

    }

    

    /**

     * Generate recommendations based on risk factors

     */

    private function generateRecommendations($probability, $riskFactors) {

        $recommendations = [];

        

        if ($probability < 0.3) {

            $recommendations[] = 'URGENT: Contact parent immediately';

            $recommendations[] = 'Consider payment plan options';

            $recommendations[] = 'Send reminder SMS and email';

            $recommendations[] = 'Flag for principal review';

        } elseif ($probability < 0.6) {

            $recommendations[] = 'Send payment reminder within 3 days';

            $recommendations[] = 'Follow up with phone call';

            $recommendations[] = 'Offer flexible payment options';

        } else {

            $recommendations[] = 'Monitor payment status';

            $recommendations[] = 'Send thank you note for regular payments';

        }

        

        // Add specific recommendations based on risk factors

        foreach ($riskFactors as $factor) {

            if (strpos($factor, 'late') !== false) {

                $recommendations[] = 'Remind about due dates and late penalties';

            }

            if (strpos($factor, 'balance') !== false) {

                $recommendations[] = 'Suggest splitting balance into installments';

            }

        }

        

        return array_unique($recommendations);

    }

    

    /**

     * Get risk level based on probability

     */

    private function getRiskLevel($probability) {

        if ($probability < 0.3) return 'Critical';

        if ($probability < 0.6) return 'High';

        if ($probability < 0.8) return 'Medium';

        return 'Low';

    }

    

    /**

     * Calculate confidence in prediction

     */

    private function calculateConfidence($features) {

        $confidence = 0.7; // Base confidence

        

        // More data = higher confidence

        if ($features['total_payments'] > 10) $confidence += 0.15;

        elseif ($features['total_payments'] > 5) $confidence += 0.1;

        elseif ($features['total_payments'] > 2) $confidence += 0.05;

        

        // Recent data = higher confidence

        if ($features['days_since_last_payment'] < 7) $confidence += 0.1;

        

        // Cap at 0.95

        return min($confidence, 0.95);

    }

    

    /**

     * Get days since last payment

     */

    private function getDaysSinceLastPayment($studentId) {

        $query = "SELECT DATEDIFF(NOW(), MAX(payment_date)) as days 

                  FROM payments WHERE student_id = ?";

        $stmt = $this->conn->prepare($query);

        $stmt->bind_param("i", $studentId);

        $stmt->execute();

        $result = $stmt->get_result();

        $row = $result->fetch_assoc();

        $stmt->close();

        

        return $row['days'] ?? 999; // Return large number if no payments

    }

    

    /**

     * Calculate payment frequency (payments per month)

     */

    private function calculatePaymentFrequency($studentId) {

        $query = "SELECT COUNT(*) as count, 

                         DATEDIFF(NOW(), MIN(payment_date)) as date_range

                  FROM payments WHERE student_id = ?";

        $stmt = $this->conn->prepare($query);

        $stmt->bind_param("i", $studentId);

        $stmt->execute();

        $result = $stmt->get_result();

        $row = $result->fetch_assoc();

        $stmt->close();

        

        if ($row['count'] > 0 && $row['date_range'] > 0) {

            return ($row['count'] / $row['date_range']) * 30; // Payments per month

        }

        

        return 0;

    }

    

    /**

     * Get class payment rate

     */

    private function getClassPaymentRate($className) {

        $query = "SELECT 

                    COALESCE(AVG(p.amount_paid / fs.amount), 0) as payment_rate

                  FROM students s

                  LEFT JOIN payments p ON s.id = p.student_id

                  LEFT JOIN fee_structures fs ON p.fee_structure_id = fs.id

                  WHERE s.class = ? AND fs.amount > 0";

        

        $stmt = $this->conn->prepare($query);

        $stmt->bind_param("s", $className);

        $stmt->execute();

        $result = $stmt->get_result();

        $row = $result->fetch_assoc();

        $stmt->close();

        

        return $row['payment_rate'] ?? 0.5;

    }

    

    /**

     * Get historical payment data for forecasting

     */

    private function getHistoricalPaymentData() {

        $query = "SELECT 

                    DATE_FORMAT(payment_date, '%Y-%m') as month,

                    SUM(amount_paid) as total

                  FROM payments

                  WHERE payment_date >= DATE_SUB(NOW(), INTERVAL 12 MONTH)

                  GROUP BY DATE_FORMAT(payment_date, '%Y-%m')

                  ORDER BY month ASC";

        

        $result = $this->conn->query($query);

        $data = [];

        

        while ($row = $result->fetch_assoc()) {

            $data[$row['month']] = $row['total'];

        }

        

        return $data;

    }

    

    /**

     * Forecast revenue using linear regression

     */

    private function forecastRevenue($historicalData, $months) {

        $values = array_values($historicalData);

        $count = count($values);

        

        if ($count < 3) {

            // Not enough data, use simple average

            $avg = array_sum($values) / max($count, 1);

            return array_fill(0, $months, $avg);

        }

        

        // Simple linear regression

        $x = range(1, $count);

        $y = $values;

        

        $n = $count;

        $sumX = array_sum($x);

        $sumY = array_sum($y);

        $sumXY = 0;

        $sumX2 = 0;

        

        for ($i = 0; $i < $n; $i++) {

            $sumXY += $x[$i] * $y[$i];

            $sumX2 += $x[$i] * $x[$i];

        }

        

        $slope = ($n * $sumXY - $sumX * $sumY) / ($n * $sumX2 - $sumX * $sumX);

        $intercept = ($sumY - $slope * $sumX) / $n;

        

        // Generate forecast

        $forecast = [];

        for ($i = 1; $i <= $months; $i++) {

            $nextX = $count + $i;

            $predicted = $slope * $nextX + $intercept;

            $forecast[] = max($predicted, 0); // Ensure non-negative

        }

        

        return $forecast;

    }

    

    /**

     * Apply seasonal adjustments to forecast

     */

    private function applySeasonalAdjustments($forecast) {

        // Add seasonal factors (e.g., higher in September, January)

        $currentMonth = date('n');

        

        for ($i = 0; $i < count($forecast); $i++) {

            $month = ($currentMonth + $i - 1) % 12 + 1;

            

            // Seasonal multipliers

            $seasonalFactor = 1.0;

            if ($month == 9 || $month == 1) { // September and January (new terms)

                $seasonalFactor = 1.3;

            } elseif ($month == 12) { // December (holiday season)

                $seasonalFactor = 0.8;

            } elseif ($month == 7 || $month == 8) { // Summer break

                $seasonalFactor = 0.7;

            }

            

            $forecast[$i] *= $seasonalFactor;

        }

        

        return $forecast;

    }

    

    /**

     * Calculate confidence interval for forecast

     */

    private function calculateConfidenceInterval($forecast) {

        $stdDev = 0;

        $mean = array_sum($forecast) / count($forecast);

        

        foreach ($forecast as $value) {

            $stdDev += pow($value - $mean, 2);

        }

        $stdDev = sqrt($stdDev / count($forecast));

        

        return [

            'lower_bound' => $mean - 1.96 * $stdDev,

            'upper_bound' => $mean + 1.96 * $stdDev

        ];

    }

}