<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Result;
use App\Models\FinalResult;
use App\Models\ResultMark;
use App\Models\Exam;
use App\Models\Student;
use App\Models\ExamSubjectRule;
use App\Models\Notice;
use App\Models\NoticeCategory;
use App\Models\Setting;
use App\Models\HeroSlide;
use App\Models\Teacher;
use Illuminate\Http\Request;

class ApiController extends Controller
{
    /**
     * Get result by roll (public_roll), session (season), class, and exam_name.
     */
    public function getResult(Request $request)
    {
        // Support both old and new API format for backward compatibility
        if ($request->has('year') && !$request->has('season') && !$request->has('exam_name')) {
            // Old API format - search in Result table
            $request->validate([
                'roll' => 'required|string',
                'class' => 'required|in:11,12',
                'year' => 'required|string',
            ]);

            $result = Result::where('roll', $request->roll)
                ->where('class', $request->class)
                ->where('year', $request->year)
                ->first();

            if ($result) {
                return response()->json([
                    'success' => true,
                    'data' => $result,
                ]);
            }

            return response()->json([
                'success' => false,
                'message' => 'Result not found',
            ], 404);
        }

        // New API format - search in FinalResult with joins
        $request->validate([
            'roll' => 'required|string',
            'class' => 'required|in:11,12',
            'season' => 'required|string',
            'exam_name' => 'required|string',
        ]);

        // Search for final result by joining Student and Exam
        $finalResult = FinalResult::with(['student', 'exam', 'exam.examType'])
            ->whereHas('student', function ($q) use ($request) {
                $q->where('roll', $request->roll)
                  ->where('current_class', $request->class)
                  ->where('session', $request->season);
            })
            ->whereHas('exam', function ($q) use ($request) {
                $q->where('name', 'like', '%' . $request->exam_name . '%')
                  ->where('class', $request->class)
                  ->where('session', $request->season);
            })
            ->where('is_published', true)
            ->first();

        if ($finalResult && $finalResult->student && $finalResult->exam) {
            // Get detailed marks
            $resultMarks = ResultMark::with('subject')
                ->where('exam_id', $finalResult->exam_id)
                ->where('student_id', $finalResult->student_id)
                ->get();

            // Load exam rules for real-time calculation
            $rules = ExamSubjectRule::where('exam_id', $finalResult->exam_id)
                ->get()
                ->keyBy('subject_id');

            // Recalculate subjects with real-time pass mark logic
            $recalculatedSubjects = [];
            $totalMarks = 0;
            $hasFailure = false;
            $subjectGpas = [];

            foreach ($resultMarks as $mark) {
                $rule = $rules->get($mark->subject_id);
                
                // Calculate total from components
                $subjectTotal = ($mark->first_paper_mcq ?? 0) +
                               ($mark->first_paper_cq ?? 0) +
                               ($mark->first_paper_practical ?? 0) +
                               ($mark->second_paper_mcq ?? 0) +
                               ($mark->second_paper_cq ?? 0) +
                               ($mark->second_paper_practical ?? 0);
                
                $totalMarks += $subjectTotal;
                
                // Real-time calculation: Check pass marks
                $isFailed = false;
                $subjectGpa = 0;
                $subjectGrade = 'F';
                
                if ($rule) {
                    // Check overall pass marks first
                    if ($subjectTotal < ($rule->pass_marks ?? 0)) {
                        $isFailed = true;
                    } else {
                        // Check individual section pass marks (CQ, MCQ)
                        $isFailed = $this->checkSubjectPassMarks($rule, [
                            'first_paper_mcq' => $mark->first_paper_mcq,
                            'first_paper_cq' => $mark->first_paper_cq,
                            'first_paper_practical' => $mark->first_paper_practical,
                            'second_paper_mcq' => $mark->second_paper_mcq,
                            'second_paper_cq' => $mark->second_paper_cq,
                            'second_paper_practical' => $mark->second_paper_practical,
                        ], $subjectTotal);
                    }
                    
                    if ($isFailed) {
                        $hasFailure = true;
                        $subjectGpa = 0.00;
                        $subjectGrade = 'F';
                    } else {
                        $percentage = $rule->total_marks > 0 ? ($subjectTotal / $rule->total_marks) * 100 : 0;
                        $gradeData = ResultMark::getGradeDataFromPercentage($percentage);
                        $subjectGpa = $gradeData['gpa'];
                        $subjectGrade = $gradeData['grade'];
                    }
                }
                
                $subjectGpas[] = $subjectGpa;
                
                $recalculatedSubjects[] = [
                    'subject_name' => ($mark->subject->name ?? 'N/A'),
                    'subject_code' => ($mark->subject->code ?? 'N/A'),
                    'first_paper_mcq' => $mark->first_paper_mcq,
                    'first_paper_cq' => $mark->first_paper_cq,
                    'first_paper_practical' => $mark->first_paper_practical,
                    'second_paper_mcq' => $mark->second_paper_mcq,
                    'second_paper_cq' => $mark->second_paper_cq,
                    'second_paper_practical' => $mark->second_paper_practical,
                    'total_marks' => $subjectTotal,
                    'subject_gpa' => $subjectGpa,
                    'subject_grade' => $subjectGrade,
                    'is_failed' => $isFailed,
                ];
            }

            // Recalculate final result
            // Step 1: Check if any subject is failed (is_failed = true or grade = 'F')
            $hasAnyFailedSubject = false;
            foreach ($recalculatedSubjects as $subject) {
                if ($subject['is_failed'] === true || $subject['subject_grade'] === 'F') {
                    $hasAnyFailedSubject = true;
                    break;
                }
            }
            
            // Step 2: Calculate final result
            if ($hasAnyFailedSubject) {
                // If any subject failed, final result is F with GPA 0.00
                $finalGpa = 0.00;
                $finalGrade = 'F';
            } else {
                // All subjects passed - calculate average GPA
                $finalGpa = count($subjectGpas) > 0 ? round(array_sum($subjectGpas) / count($subjectGpas), 2) : 0;
                
                // If GPA is 0, grade is F
                if ($finalGpa <= 0) {
                    $finalGrade = 'F';
                    $finalGpa = 0.00;
                } else {
                    // Use GPA-based direct mapping for final grade
                    // This ensures GPA 1.0 = D, not F
                    // Standard GPA to Grade mapping:
                    if ($finalGpa >= 5.00) {
                        $finalGrade = 'A+';
                    } elseif ($finalGpa >= 4.00) {
                        $finalGrade = 'A';
                    } elseif ($finalGpa >= 3.50) {
                        $finalGrade = 'A-';
                    } elseif ($finalGpa >= 3.00) {
                        $finalGrade = 'B';
                    } elseif ($finalGpa >= 2.00) {
                        $finalGrade = 'C';
                    } elseif ($finalGpa >= 1.00) {
                        $finalGrade = 'D';
                    } else {
                        $finalGrade = 'F';
                    }
                    
                    // Keep the calculated average GPA
                    // The final GPA is the average of all subject GPAs
                }
            }

            // Format result data with real-time calculated values
            $resultData = [
                'id' => $finalResult->id,
                'student_name' => $finalResult->student->name ?? 'N/A',
                'roll' => $finalResult->student->roll ?? 'N/A',
                'class' => $finalResult->exam->class ?? 'N/A',
                'session' => $finalResult->exam->session ?? 'N/A',
                'exam_name' => $finalResult->exam->name ?? 'N/A',
                'exam_type' => ($finalResult->exam->examType->name ?? 'N/A'),
                'total_marks' => $totalMarks,
                'gpa' => $finalGpa,
                'grade' => $finalGrade,
                'position' => $finalResult->position,
                'remarks' => $finalResult->remarks,
                'subjects' => $recalculatedSubjects,
            ];

            return response()->json([
                'success' => true,
                'data' => $resultData,
            ]);
        }

        return response()->json([
            'success' => false,
            'message' => 'Result not found. Please verify your roll number, session, class, and exam name.',
        ], 404);
    }

    /**
     * Get available sessions from students/exams
     */
    public function getSessions()
    {
        // Get unique sessions from both students and exams tables
        $studentSessions = Student::whereNotNull('session')
            ->where('session', '!=', '')
            ->distinct()
            ->pluck('session')
            ->toArray();
        
        $examSessions = Exam::whereNotNull('session')
            ->where('session', '!=', '')
            ->distinct()
            ->pluck('session')
            ->toArray();
        
        $allSessions = array_unique(array_merge($studentSessions, $examSessions));
        sort($allSessions);
        
        return response()->json([
            'success' => true,
            'data' => array_values($allSessions),
        ]);
    }

    /**
     * Get exams by session and class
     */
    public function getExamsBySessionAndClass(Request $request)
    {
        $request->validate([
            'session' => 'required|string',
            'class' => 'required|in:11,12',
        ]);

        // Get all exams for this session and class
        // Show all exams, but results will only be found if published
        $exams = Exam::with(['examType', 'finalResults'])
            ->where('session', $request->session)
            ->where('class', $request->class)
            ->orderBy('name')
            ->get(['id', 'name', 'exam_type_id', 'class', 'session']);

        $examList = $exams->map(function ($exam) {
            // Check if exam has published results using loaded relationship
            $hasPublishedResults = $exam->finalResults->where('is_published', true)->count() > 0;
            
            return [
                'id' => $exam->id,
                'name' => $exam->name,
                'exam_type' => $exam->examType->name ?? 'N/A',
                'has_published_results' => $hasPublishedResults,
            ];
        });

        return response()->json([
            'success' => true,
            'data' => $examList,
        ]);
    }

    /**
     * Get all active notices with advanced filtering.
     */
    public function getNotices(Request $request)
    {
        $limit = $request->input('limit', null);
        $department = $request->input('department', null);
        $category_id = $request->input('category_id', null);
        $priority = $request->input('priority', null);
        
        $query = Notice::active()->with('category')->pinnedFirst();
        
        // Filter by department
        if ($department && $department !== 'all') {
            $query->where('department', $department);
        }
        
        // Filter by category
        if ($category_id && $category_id !== 'all') {
            $query->where('category_id', $category_id);
        }
        
        // Filter by priority
        if ($priority && $priority !== 'all') {
            $query->where('priority', $priority);
        }
        
        if ($limit) {
            $notices = $query->take($limit)->get();
        } else {
            $notices = $query->get();
        }

        // Get unique departments for filter
        $departments = Notice::active()->distinct()->pluck('department')->filter()->values();
        
        // Get all active categories
        $categories = NoticeCategory::active()->ordered()->get(['id', 'name', 'slug', 'color', 'icon']);

        return response()->json([
            'success' => true,
            'data' => $notices,
            'departments' => $departments,
            'categories' => $categories,
        ]);
    }

    /**
     * Get a single notice by ID.
     */
    public function getNotice($id)
    {
        $notice = Notice::active()->find($id);

        if ($notice) {
            return response()->json([
                'success' => true,
                'data' => $notice,
            ]);
        }

        return response()->json([
            'success' => false,
            'message' => 'Notice not found',
        ], 404);
    }

    /**
     * Check if student passed all required section pass marks
     * First checks CQ and MCQ pass marks (if Must Pass is enabled), then checks total pass marks
     * This method mirrors the logic from ResultManagementController
     */
    private function checkSubjectPassMarks($rule, $row, $total)
    {
        // First check overall pass marks
        if ($total < ($rule->pass_marks ?? 0)) {
            return true;
        }

        $config = is_array($rule->config) ? $rule->config : json_decode($rule->config ?? '[]', true);
        $paperMode = $rule->paper_mode ?? 'merged';
        $passConfig = $config['pass_config'] ?? [];
        
        // Helper function to check if must pass (handle different boolean formats)
        $isMustPass = function($value) {
            if (is_bool($value)) return $value;
            if (is_string($value)) {
                return in_array(strtolower($value), ['true', '1', 'yes', 'on']);
            }
            if (is_numeric($value)) {
                return $value > 0;
            }
            return false;
        };

        if ($paperMode === 'merged') {
            // Merged mode: Check individual section pass marks
            // CQ Pass - Check if CQ is marked as "must pass" and below pass mark
            if (isset($passConfig['cq']) && $passConfig['cq'] > 0) {
                $cqTotal = ($row['first_paper_cq'] ?? 0);
                if ($cqTotal < $passConfig['cq']) {
                    $cqMustPass = $passConfig['cq_must_pass'] ?? false;
                    if ($isMustPass($cqMustPass)) {
                        return true; // Failed due to CQ pass mark
                    }
                }
            }

            // MCQ Pass - Check if MCQ is marked as "must pass" and below pass mark
            if (isset($passConfig['mcq']) && $passConfig['mcq'] > 0) {
                $mcqTotal = ($row['first_paper_mcq'] ?? 0);
                if ($mcqTotal < $passConfig['mcq']) {
                    $mcqMustPass = $passConfig['mcq_must_pass'] ?? false;
                    if ($isMustPass($mcqMustPass)) {
                        return true; // Failed due to MCQ pass mark
                    }
                }
            }

            // Practical Pass - Check if Practical is marked as "must pass"
            if (isset($passConfig['practical']) && $passConfig['practical'] > 0) {
                $practicalTotal = ($row['first_paper_practical'] ?? 0);
                if ($practicalTotal < $passConfig['practical']) {
                    $practicalMustPass = $passConfig['practical_must_pass'] ?? false;
                    if ($isMustPass($practicalMustPass)) {
                        return true; // Failed due to Practical pass mark
                    }
                }
            }
        } else {
            // Separate mode: Check combined pass marks
            // Combined CQ Pass (1st paper CQ + 2nd paper CQ)
            // Check FIRST if "Must Pass" is enabled, then check if below pass mark
            if (isset($passConfig['cq']) && $passConfig['cq'] > 0) {
                $cqMustPass = $passConfig['cq_must_pass'] ?? false;
                if ($isMustPass($cqMustPass)) {
                    $combinedCqTotal = ($row['first_paper_cq'] ?? 0) + ($row['second_paper_cq'] ?? 0);
                    if ($combinedCqTotal < $passConfig['cq']) {
                        return true; // Failed due to Combined CQ pass mark
                    }
                }
            }

            // Combined MCQ Pass (1st paper MCQ + 2nd paper MCQ)
            // Check FIRST if "Must Pass" is enabled, then check if below pass mark
            if (isset($passConfig['mcq']) && $passConfig['mcq'] > 0) {
                $mcqMustPass = $passConfig['mcq_must_pass'] ?? false;
                if ($isMustPass($mcqMustPass)) {
                    $combinedMcqTotal = ($row['first_paper_mcq'] ?? 0) + ($row['second_paper_mcq'] ?? 0);
                    if ($combinedMcqTotal < $passConfig['mcq']) {
                        return true; // Failed due to Combined MCQ pass mark
                    }
                }
            }

            // Combined Practical Pass - Check if Practical is marked as "must pass"
            if (isset($passConfig['practical']) && $passConfig['practical'] > 0) {
                $combinedPracticalTotal = ($row['first_paper_practical'] ?? 0) + ($row['second_paper_practical'] ?? 0);
                if ($combinedPracticalTotal < $passConfig['practical']) {
                    $practicalMustPass = $passConfig['practical_must_pass'] ?? false;
                    if ($isMustPass($practicalMustPass)) {
                        return true; // Failed due to Combined Practical pass mark
                    }
                }
            }
        }

        return false; // Passed all checks
    }

    /**
     * Public Home Configuration for frontend (site settings + hero slides)
     */
    public function getHomeConfig()
    {
        $site = [
            'college_name' => Setting::get('college_name', 'Sheikh Abdul Wohab Model College'),
            'tagline' => Setting::get('tagline', 'Excellence in Education'),
            'description' => Setting::get('description', 'Committed to excellence in education and character development'),
            'social_facebook' => Setting::get('social_facebook', ''),
            'social_youtube' => Setting::get('social_youtube', ''),
            'social_twitter' => Setting::get('social_twitter', ''),
            'principal' => Setting::get('principal', [
                'title' => 'Message from Principal',
                'subtitle' => 'Sheikh Abdul Wohab Model College',
                'message' => 'Welcome to our college where academic excellence meets character building.',
                'image_url' => null,
            ]),
        ];

        $slides = HeroSlide::where('is_active', true)
            ->orderBy('sort_order')
            ->get(['title', 'subtitle', 'image_url']);

        return response()->json([
            'success' => true,
            'data' => [
                'site' => $site,
                'heroSlides' => $slides,
            ],
        ]);
    }

    /**
     * Get all active teachers.
     */
    public function getTeachers()
    {
        $teachers = Teacher::active()->ordered()->get();

        return response()->json([
            'success' => true,
            'data' => $teachers,
        ]);
    }

    /**
     * Get contact page configuration from settings.
     */
    public function getContactConfig()
    {
        $config = [
            'full_address' => Setting::get('contact_full_address', "Sheikh Abdul Wohab Model College\n[Your Address Here]\n[City, District, Postal Code]\nBangladesh"),
            'office_phone' => Setting::get('contact_office_phone', '+880 XXX-XXXXXXX'),
            'mobile_phone' => Setting::get('contact_mobile_phone', '+880 XXXX-XXXXXX'),
            'principal_email' => Setting::get('contact_principal_email', 'principal@sawmc.edu.bd'),
            'general_email' => Setting::get('contact_general_email', 'info@sawmc.edu.bd'),
            'working_hours' => Setting::get('contact_working_hours', 'Saturday - Thursday: 9:00 AM - 4:00 PM'),
            'weekend_info' => Setting::get('contact_weekend_info', 'Friday: Closed'),
            'map_url' => Setting::get('contact_map_url', ''),
            'admission_title' => Setting::get('contact_admission_title', 'Admission Inquiries'),
            'admission_desc' => Setting::get('contact_admission_desc', 'Contact us for admission procedures and requirements'),
            'visits_title' => Setting::get('contact_visits_title', 'Office Visits'),
            'visits_desc' => Setting::get('contact_visits_desc', 'Welcome to visit our campus during office hours'),
            'support_title' => Setting::get('contact_support_title', 'Support'),
            'support_desc' => Setting::get('contact_support_desc', "We're here to assist you with any queries"),
            'social_facebook' => Setting::get('social_facebook', ''),
            'social_instagram' => Setting::get('social_instagram', ''),
            'social_twitter' => Setting::get('social_twitter', ''),
            'social_youtube' => Setting::get('social_youtube', ''),
        ];

        return response()->json([
            'success' => true,
            'data' => $config,
        ]);
    }
}

