<?php
require_once APP_PATH . '/Core/BaseModel.php';

/**
 * BOAFO AI Recommendation Engine
 * Implements all 5 AI algorithms:
 * 1. Mentor Matching
 * 2. University Recommendation
 * 3. Scholarship Recommendation
 * 4. Admission Readiness Analysis
 * 5. Scholarship Success Prediction
 */
class RecommendationEngine extends BaseModel {
    protected string $table = 'recommendation_logs';

    // ============================================================
    // MODULE 8: MENTOR MATCHING ENGINE
    // ============================================================
    public function matchMentors(int $studentId): array {
        $student = $this->fetchOne(
            "SELECT sp.*, u.first_name, u.last_name
             FROM student_profiles sp
             JOIN users u ON u.id = sp.user_id
             WHERE sp.user_id = ?",
            [$studentId]
        );

        if (!$student) return [];

        // Load all verified mentors
        $mentors = $this->fetchAll(
            "SELECT mp.*, u.first_name, u.last_name, u.avatar,
                    uni.name AS university_name, uni.slug AS university_slug
             FROM mentor_profiles mp
             JOIN users u ON u.id = mp.user_id
             LEFT JOIN universities uni ON uni.id = mp.university_id
             WHERE u.status = 'active' AND mp.verified = 1
             ORDER BY mp.sessions_completed DESC"
        );

        $weights = AI_MENTOR_WEIGHTS;
        $scored  = [];

        foreach ($mentors as $mentor) {
            $score = 0.0;
            $reasons = [];

            // University match (30%)
            if (!empty($student['preferred_university']) && !empty($mentor['university_name'])) {
                if (stripos($mentor['university_name'], $student['preferred_university']) !== false ||
                    stripos($student['preferred_university'], $mentor['university_name']) !== false) {
                    $score += $weights['university'];
                    $reasons[] = "Studies at your preferred university";
                }
            }

            // Program match (30%)
            if (!empty($student['intended_program']) && !empty($mentor['program'])) {
                similar_text(
                    strtolower($student['intended_program']),
                    strtolower($mentor['program']),
                    $programSimilarity
                );
                $programScore = ($programSimilarity / 100) * $weights['program'];
                $score += $programScore;
                if ($programSimilarity > 60) {
                    $reasons[] = "In a similar program ({$mentor['program']})";
                }
            }

            // Career interest match (20%)
            if (!empty($student['career_interests']) && !empty($mentor['career_goals'])) {
                $studentCareers = array_map('trim', explode(',', strtolower($student['career_interests'])));
                $mentorCareers  = array_map('trim', explode(',', strtolower($mentor['career_goals'])));
                $intersection   = array_intersect($studentCareers, $mentorCareers);
                if (count($intersection) > 0) {
                    $careerScore = min(1.0, count($intersection) / max(1, count($studentCareers)));
                    $score += $careerScore * $weights['career'];
                    $reasons[] = "Shares career interests: " . implode(', ', $intersection);
                }
            }

            // Region match (10%)
            if (!empty($student['region_id']) && !empty($mentor['region_id'])) {
                if ($student['region_id'] === $mentor['region_id']) {
                    $score += $weights['region'];
                    $reasons[] = "From the same region";
                }
            }

            // Availability (10%)
            if ($mentor['is_available'] && $mentor['current_mentees'] < $mentor['max_mentees']) {
                $score += $weights['available'];
                $reasons[] = "Currently accepting mentees";
            }

            $percentage = round($score * 100);
            $mentor['compatibility_score'] = $percentage;
            $mentor['compatibility_reasons'] = $reasons;
            $mentor['compatibility_label']  = $this->scoreLabel($percentage);
            $scored[] = $mentor;
        }

        // Sort by compatibility descending
        usort($scored, fn($a, $b) => $b['compatibility_score'] <=> $a['compatibility_score']);

        $result = array_slice($scored, 0, 10);

        // Log recommendation
        $this->logRecommendation($studentId, 'mentor', $student, $result);

        return $result;
    }

    // ============================================================
    // MODULE 6: ADMISSION ELIGIBILITY ANALYZER
    // ============================================================
    public function analyzeAdmission(int $studentId): array {
        // Get student WASSCE results
        $wassce = $this->fetchAll(
            "SELECT subject, grade FROM wassce_results WHERE user_id = ?",
            [$studentId]
        );

        if (empty($wassce)) {
            return ['error' => 'No WASSCE results found. Please add your WASSCE grades first.'];
        }

        // Calculate aggregate
        $grades = array_column($wassce, 'grade');
        $aggregate = calculateAggregate($grades);
        $subjectMap = [];
        foreach ($wassce as $row) {
            $subjectMap[strtolower($row['subject'])] = $row['grade'];
        }

        // Get student profile
        $profile = $this->fetchOne(
            "SELECT * FROM student_profiles WHERE user_id = ?",
            [$studentId]
        );
        $intendedProgram = $profile['intended_program'] ?? '';

        // Get all active programs with their requirements
        $programs = $this->fetchAll(
            "SELECT p.*, u.name AS university_name, u.slug AS university_slug
             FROM programs p
             JOIN universities u ON u.id = p.university_id
             WHERE p.is_active = 1 AND p.degree_level = 'bachelor'
             ORDER BY u.name, p.name"
        );

        $eligible   = [];
        $ineligible = [];

        foreach ($programs as $program) {
            $analysis = $this->checkProgramEligibility($program, $subjectMap, $aggregate);
            $program['eligibility'] = $analysis;

            if ($analysis['eligible']) {
                $eligible[] = $program;
            } else {
                $ineligible[] = $program;
            }
        }

        // Overall readiness score
        $totalPrograms = count($programs);
        $eligibleCount = count($eligible);
        $readinessScore = $totalPrograms > 0
            ? round(($eligibleCount / $totalPrograms) * 100)
            : 0;

        // Intended program match
        $intendedMatch = null;
        if ($intendedProgram) {
            foreach ($programs as $p) {
                if (stripos($p['name'], $intendedProgram) !== false) {
                    $intendedMatch = $p;
                    break;
                }
            }
        }

        $result = [
            'wassce_results'    => $wassce,
            'aggregate'         => $aggregate,
            'readiness_score'   => $readinessScore,
            'eligible_programs' => $eligible,
            'ineligible_programs' => array_slice($ineligible, 0, 5),
            'intended_program_match' => $intendedMatch,
            'total_eligible'    => $eligibleCount,
            'total_programs'    => $totalPrograms,
            'subject_map'       => $subjectMap,
        ];

        $this->logRecommendation($studentId, 'university', ['aggregate' => $aggregate], $result);

        return $result;
    }

    private function checkProgramEligibility(array $program, array $studentSubjects, int $aggregate): array {
        $reasons  = [];
        $missing  = [];
        $eligible = true;

        // Check aggregate
        if ($program['min_aggregate'] && $aggregate > $program['min_aggregate']) {
            $eligible = false;
            $reasons[] = "Aggregate {$aggregate} exceeds cutoff of {$program['min_aggregate']}";
            $missing[] = "Improve aggregate from {$aggregate} to {$program['min_aggregate']}";
        } else {
            $reasons[] = "✓ Aggregate {$aggregate} meets requirement (≤{$program['min_aggregate']})";
        }

        // Check required subjects
        if ($program['required_subjects']) {
            $required = json_decode($program['required_subjects'], true) ?? [];
            foreach ($required as $subject) {
                $key = strtolower($subject);
                if (!isset($studentSubjects[$key])) {
                    $eligible = false;
                    $missing[] = "Missing required subject: {$subject}";
                } else {
                    $grade = $studentSubjects[$key];
                    if (gradeToPoint($grade) > 6) {
                        $eligible = false;
                        $missing[] = "Need at least C6 in {$subject} (you have {$grade})";
                    } else {
                        $reasons[] = "✓ {$subject}: {$grade}";
                    }
                }
            }
        }

        // Score for eligible programs
        $admissionScore = 0;
        if ($eligible && $program['min_aggregate']) {
            $admissionScore = round(max(0, ($program['min_aggregate'] - $aggregate) / $program['min_aggregate'] * 100 + 30));
        }

        return [
            'eligible'        => $eligible,
            'reasons'         => $reasons,
            'missing'         => $missing,
            'admission_score' => min(100, $admissionScore),
        ];
    }

    // ============================================================
    // MODULE 5: SCHOLARSHIP RECOMMENDATION ENGINE
    // ============================================================
    public function recommendScholarships(int $studentId): array {
        $student = $this->fetchOne(
            "SELECT sp.*, u.first_name, u.last_name
             FROM student_profiles sp
             JOIN users u ON u.id = sp.user_id
             WHERE sp.user_id = ?",
            [$studentId]
        );

        $wassce = $this->fetchAll(
            "SELECT subject, grade FROM wassce_results WHERE user_id = ?",
            [$studentId]
        );

        $grades    = array_column($wassce, 'grade');
        $aggregate = !empty($grades) ? calculateAggregate($grades) : 99;

        // Fetch all open scholarships
        $scholarships = $this->fetchAll(
            "SELECT * FROM scholarships WHERE is_active = 1 AND status = 'open' ORDER BY is_featured DESC"
        );

        $recommended = [];
        foreach ($scholarships as $sch) {
            $score    = $this->scoreScholarshipFit($sch, $student, $aggregate);
            $sch['fit_score']   = $score['score'];
            $sch['fit_label']   = $this->scoreLabel($score['score']);
            $sch['fit_reasons'] = $score['reasons'];
            $recommended[]      = $sch;
        }

        // Sort by fit score descending
        usort($recommended, fn($a, $b) => $b['fit_score'] <=> $a['fit_score']);

        $result = array_slice($recommended, 0, 12);
        $this->logRecommendation($studentId, 'scholarship', ['aggregate' => $aggregate], $result);

        return $result;
    }

    private function scoreScholarshipFit(array $sch, ?array $student, int $aggregate): array {
        $score   = 0.0;
        $reasons = [];

        if (!$student) return ['score' => 30, 'reasons' => []];

        // Aggregate / grade match (40%)
        if ($sch['min_aggregate']) {
            if ($aggregate <= $sch['min_aggregate']) {
                $score += 0.40;
                $reasons[] = "Your aggregate meets the requirement";
            } else {
                $diff = $aggregate - $sch['min_aggregate'];
                $reasons[] = "Aggregate {$diff} points above cutoff (needs improvement)";
            }
        } else {
            $score += 0.30; // No grade requirement = open to all
            $reasons[] = "No strict grade requirement";
        }

        // Financial need match (30%)
        if ($sch['financial_need']) {
            if (in_array($student['financial_need'] ?? '', ['high', 'moderate'])) {
                $score += 0.30;
                $reasons[] = "Matches your financial need profile";
            }
        } else {
            $score += 0.15; // Still partially relevant
        }

        // Competition factor (20%) — based on beneficiaries vs estimated applicants
        if ($sch['num_beneficiaries'] && $sch['num_applicants_est']) {
            $ratio = $sch['num_beneficiaries'] / $sch['num_applicants_est'];
            $competitionScore = min(0.20, $ratio * 2);
            $score += $competitionScore;
            $acceptRate = round($ratio * 100, 1);
            $reasons[] = "Acceptance rate: ~{$acceptRate}%";
        } else {
            $score += 0.10;
        }

        // Gender match (10%)
        if ($sch['gender_restriction'] === 'all') {
            $score += 0.10;
        } elseif (!empty($student['gender'])) {
            if ($sch['gender_restriction'] === $student['gender']) {
                $score += 0.10;
                $reasons[] = "Gender-specific scholarship you qualify for";
            }
        }

        return ['score' => min(100, round($score * 100)), 'reasons' => $reasons];
    }

    // ============================================================
    // MODULE 7: SCHOLARSHIP SUCCESS PROBABILITY
    // ============================================================
    public function predictScholarshipSuccess(int $scholarshipId, int $studentId): array {
        $scholarship = $this->fetchOne("SELECT * FROM scholarships WHERE id = ?", [$scholarshipId]);
        if (!$scholarship) return ['error' => 'Scholarship not found'];

        $wassce  = $this->fetchAll("SELECT subject, grade FROM wassce_results WHERE user_id = ?", [$studentId]);
        $grades  = array_column($wassce, 'grade');
        $aggregate = !empty($grades) ? calculateAggregate($grades) : 99;

        $student = $this->fetchOne("SELECT * FROM student_profiles WHERE user_id = ?", [$studentId]);

        $weights = AI_SCHOLARSHIP_WEIGHTS;
        $score   = 0.0;
        $reasons = [];
        $improvements = [];

        // 1. Grade match (40%)
        if ($scholarship['min_aggregate']) {
            if ($aggregate <= $scholarship['min_aggregate']) {
                $gradeScore = 1.0;
                $reasons[] = "✓ Academic performance meets requirements";
            } else {
                $gradeScore = max(0, 1 - (($aggregate - $scholarship['min_aggregate']) / 10));
                $improvements[] = "Improve aggregate score to {$scholarship['min_aggregate']} or better";
            }
        } else {
            $gradeScore = 0.75; // No strict requirement
            $reasons[]  = "No strict grade cutoff — open to all";
        }
        $score += $gradeScore * $weights['grade'];

        // 2. Eligibility match (30%)
        $eligibilityScore = 0.80; // Base eligibility
        if ($scholarship['financial_need'] && in_array($student['financial_need'] ?? '', ['high', 'moderate'])) {
            $eligibilityScore = 1.0;
            $reasons[] = "✓ Financial need profile matches";
        }
        if ($scholarship['gender_restriction'] !== 'all') {
            if (($student['gender'] ?? '') !== $scholarship['gender_restriction']) {
                $eligibilityScore = 0.0;
                $reasons[] = "✗ Gender restriction does not match";
            }
        }
        $score += $eligibilityScore * $weights['eligibility'];

        // 3. Competition ratio (20%)
        $competitionScore = 0.5;
        if ($scholarship['num_beneficiaries'] && $scholarship['num_applicants_est']) {
            $ratio = $scholarship['num_beneficiaries'] / $scholarship['num_applicants_est'];
            $competitionScore = min(1.0, $ratio * 3);
            $rate = round($ratio * 100, 1);
            $reasons[] = "Historical acceptance rate: ~{$rate}%";
            if ($ratio < 0.10) {
                $improvements[] = "Very competitive — strengthen all other aspects of your application";
            }
        }
        $score += $competitionScore * $weights['competition'];

        // 4. Document readiness (10%) — based on profile completion
        $docScore = $student && $student['profile_completed'] ? 0.90 : 0.50;
        $score += $docScore * $weights['documents'];
        if (!($student['profile_completed'] ?? false)) {
            $improvements[] = "Complete your student profile to improve your score";
        }

        $finalScore = min(100, round($score * 100));

        return [
            'scholarship'  => $scholarship,
            'probability'  => $finalScore,
            'label'        => probabilityLabel($finalScore),
            'color'        => probabilityColor($finalScore),
            'reasons'      => $reasons,
            'improvements' => $improvements,
            'aggregate'    => $aggregate,
        ];
    }

    // ============================================================
    // University Recommendation (companion to admission analyzer)
    // ============================================================
    public function recommendUniversities(int $studentId): array {
        $analysis = $this->analyzeAdmission($studentId);
        if (isset($analysis['error'])) return [];

        $eligible = $analysis['eligible_programs'];

        // Group by university and pick best program
        $universities = [];
        foreach ($eligible as $program) {
            $uniSlug = $program['university_slug'];
            if (!isset($universities[$uniSlug])) {
                $universities[$uniSlug] = [
                    'university_name' => $program['university_name'],
                    'university_slug' => $program['university_slug'],
                    'programs'        => [],
                    'best_score'      => 0,
                ];
            }
            $universities[$uniSlug]['programs'][] = $program;
            $universities[$uniSlug]['best_score']  = max(
                $universities[$uniSlug]['best_score'],
                $program['eligibility']['admission_score']
            );
        }

        usort($universities, fn($a, $b) => $b['best_score'] <=> $a['best_score']);

        return array_values($universities);
    }

    // ============================================================
    // Helper: Score Label
    // ============================================================
    private function scoreLabel(float $score): string {
        if ($score >= 70) return 'Excellent Match';
        if ($score >= 50) return 'Good Match';
        if ($score >= 30) return 'Fair Match';
        return 'Low Match';
    }

    // ============================================================
    // Log recommendation
    // ============================================================
    private function logRecommendation(int $userId, string $type, array $input, array $results): void {
        $this->execute(
            "INSERT INTO recommendation_logs (user_id, type, input_snapshot, results) VALUES (?, ?, ?, ?)",
            [$userId, $type, json_encode($input), json_encode(array_slice($results, 0, 5))]
        );
    }
}
