<?php

namespace App\Models;

use CodeIgniter\Model;

class StudentModel extends Model
{
    protected $table = 'students';
    protected $primaryKey = 'id'; // Primary key of the students table
    protected $allowedFields = [
        'school_id',
        'firstname',
        'lastname',
        'dob',
        'age',
        'gender',
        'registration_grade',
        'photo_consent',
        'is_new',
        'parent_id',
        'registration_date',
        'tuition_paid',
        'year_of_registration',
        'rfid_tag',
        'is_active'
    ];
    protected $useTimestamps = false;

    // File: app/Models/StudentModel.php
    /**
     * Get all students marked as new (is_new = 1).
     *
     * @return array
     */
    public function getNewStudents(): array
    {
        return $this->where('is_new', 1)
            ->orderBy('lastname', 'ASC')
            ->orderBy('firstname', 'ASC')
            ->findAll();
    }

    public function getNewStudentsWithParents(): array
    {
        return $this->select([
            'students.*',
            'u.id        AS parent_id',
            'u.firstname AS parent_firstname',
            'u.lastname  AS parent_lastname',
            'u.email     AS parent_email',
            'u.cellphone AS parent_phone',
        ])
            ->join('users u', 'u.id = students.parent_id', 'left')
            ->where('students.is_new', 1)
            ->orderBy('students.lastname', 'ASC')
            ->orderBy('students.firstname', 'ASC')
            ->findAll();
    }

    /**
     * Fetch only new students (is_new=1) with parent info and a single emergency contact.
     * - Parent fields: parent_firstname, parent_lastname, parent_email, parent_phone
     * - Emergency fields: emergency_name, emergency_relationship, emergency_phone
     */
    public function getNewStudentsWithParentsAndEmergency(): array
    {
        return $this->select([
            'students.*',
            'u.firstname AS parent_firstname',
            'u.lastname  AS parent_lastname',
            'u.email     AS parent_email',
            'u.cellphone AS parent_phone',

            // Pick one emergency contact (MIN() works fine if you group by student)
            'MIN(ec.emergency_contact_name) AS emergency_name',
            'MIN(ec.relation)               AS emergency_relationship',
            'MIN(ec.cellphone)              AS emergency_phone',
        ])
            ->join('users u', 'u.id = students.parent_id', 'left')
            ->join('emergency_contacts ec', 'ec.parent_id = students.parent_id', 'left')
            ->where('students.is_new', 1)               // strictly 1; change to 'Yes' if your data uses Yes/No
            ->groupBy('students.id')
            ->orderBy('students.lastname', 'ASC')
            ->orderBy('students.firstname', 'ASC')
            ->findAll();
    }

    /**
     * Fetch students with parent + one emergency contact.
     * @param null|int $isNew  Pass 1 for only new, 0 for only not-new, null for both.
     */
    /**
     * Fetch students with parent + one emergency contact.
     *
     * @param null|int    $isNew       1 = only new, 0 = only not-new, null = both
     * @param null|string $schoolYear  e.g. "2025-2026"; pass null or "all" for no filter
     * @return array
     */
    public function getStudentsWithParentsAndEmergency(?string $schoolYear = null, ?int $isNew = null): array
    {
        $builder = $this->select([
            'students.*',
            'u.firstname AS parent_firstname',
            'u.lastname  AS parent_lastname',
            'u.email     AS parent_email',
            'u.cellphone AS parent_phone',
            'MIN(ec.emergency_contact_name) AS emergency_name',
            'MIN(ec.relation)               AS emergency_relationship',
            'MIN(ec.cellphone)              AS emergency_phone',
        ])
            ->join('users u', 'u.id = students.parent_id', 'left')
            ->join('emergency_contacts ec', 'ec.parent_id = students.parent_id', 'left');

        // is_new filter
        if ($isNew === 0 || $isNew === 1) {
            $builder->where('students.is_new', $isNew);
        } else {
            $builder->whereIn('students.is_new', [0, 1]); // both
        }

        // school_year filter (skip if null or "all")
        if ($schoolYear !== null && strtolower($schoolYear) !== 'all') {
            $builder
                ->join('student_class sc_filter', 'sc_filter.student_id = students.id', 'inner')
                ->where('sc_filter.school_year', $schoolYear);
        }

        return $builder
            ->groupBy('students.id')
            ->orderBy('students.is_new', 'DESC')   // new first
            ->orderBy('students.lastname', 'ASC')
            ->orderBy('students.firstname', 'ASC')
            ->findAll();
    }



    public function getStudentSchoolIdByStudentId(int $studentId): ?string
    {
        $result = $this->select('school_id')
            ->where('id', $studentId)
            ->first();

        return $result['school_id'] ?? null;
    }

    /**
     * Get all students with assignments, current semester, and school year.
     */
    public function getStudentsWithAssignments()
    {
        // Retrieve school year and semester from the configuration table
        $configTable = $this->db->table('configuration');
        $schoolYear = $configTable->select('config_value')
            ->where('config_key', 'school_year')
            ->get()
            ->getRowArray()['config_value'];

        $semester = $configTable->select('config_value')
            ->where('config_key', 'semester')
            ->get()
            ->getRowArray()['config_value'];

        return $this->db->table('students')
            ->select('
                students.id,
                students.firstname,
                students.lastname,
                students.age,
                users.email,
                users.cellphone as phone,
                students.registration_grade,
                classSection.class_section_name as current_class,
                student_class.school_year,
                "' . $semester . '" as semester
            ')
            ->join('users', 'users.id = students.parent_id', 'left')
            ->join('student_class', 'student_class.student_id = students.id', 'left')
            ->join('classSection', 'student_class.class_section_id = classSection.class_section_id', 'left')
            ->where('student_class.school_year', $schoolYear)
            ->get()
            ->getResultArray();
    }

    /**
     * Get students assigned to a specific teacher.
     *
     * @param int $teacherId
     * @return array
     */
    public function getStudentsByTeacher($teacherId)
    {
        return $this->db->table('students')
            ->select('
                students.firstname,
                students.lastname,
                students.age,
                classSection.class_section_name,
                student_class.school_year
            ')
            ->join('student_class', 'students.id = student_class.student_id', 'left')
            ->join('teacher_class', 'student_class.class_section_id = teacher_class.class_section_id', 'left')
            ->join('classSection', 'student_class.class_section_id = classSection.class_section_id', 'left')
            ->where('teacher_class.teacher_id', $teacherId)
            ->get()
            ->getResultArray();
    }

    /**
     * Get all students in a specific class section.
     *
     * @param int $classSectionId
     * @return array
     */
    public function getStudentsByClass($classSectionId)
    {
        return $this->db->table('students')
            ->join('student_class', 'students.id = student_class.student_id', 'left')
            ->where('student_class.class_section_id', $classSectionId)
            ->select('students.*, student_class.class_section_id')
            ->get()
            ->getResultArray();
    }

    /**
     * Get all students.
     *
     * @return array
     */
    public function getAllStudents()
    {
        return $this->findAll();
    }

    /**
     * Get the total number of students.
     *
     * @return int
     */
    public function getTotalStudents()
    {
        return $this->countAllResults();
    }


    public function getFullNameById($studentId)
    {
        // Fetch student record by ID
        $student = $this->find($studentId);

        // Return null if student not found
        if (empty($student)) {
            return null;
        }

        // Extract first and last name (support common variations)
        $firstName = $student['firstname'] ?? $student['first_name'] ?? $student['first'] ?? '';
        $lastName  = $student['lastname']  ?? $student['last_name']  ?? $student['last']  ?? '';

        // Return null if both names are empty
        if ($firstName === '' && $lastName === '') {
            return null;
        }

        // Return names separately
        return [
            'firstname' => $firstName,
            'lastname'  => $lastName,
        ];
    }
    /**
     * Get the full name of a student.
     *
     * @param array $student
     * @return string
     */
    public function getFullName($student)
    {
        return ($student['firstname'] ?? '') . ' ' . ($student['lastname'] ?? '');
    }

    // In the StudentModel
    public function getLastRegistrationDate($ParentId)
    {
        return $this->select('registration_date')
            ->where('parent_id', $ParentId)
            ->orderBy('registration_date', 'DESC') // Order by most recent registration date
            ->limit(1) // Get only the most recent registration
            ->first(); // Return the first record
    }

    public function getByClassAndYear($class_section_id, $school_year, ?string $semester = null): array
    {
        $studentClassModel = new \App\Models\StudentClassModel();

        $builder = $studentClassModel
            ->select('student_id')
            ->where('class_section_id', $class_section_id)
            ->where('school_year', $school_year);

        $studentIds = $builder->findAll();

        $studentIds = array_column($studentIds, 'student_id');

        if (empty($studentIds)) {
            return [];
        }

        return $this->whereIn('id', $studentIds)
            ->where('is_active', 1)
            ->orderBy('firstname', 'ASC')
            ->orderBy('lastname', 'ASC')
            ->findAll();
    }

    public function getByParentAndYear(int $parentId, string $schoolYear): array
    {
        $schoolYear = trim($schoolYear);

        if ($parentId <= 0 || $schoolYear === '') {
            return [];
        }

        return $this->select('students.id, students.school_id, students.firstname, students.lastname')
            ->join('student_class', 'student_class.student_id = students.id', 'inner')
            ->where('students.parent_id', $parentId)
            ->where('students.is_active', 1)
            ->where('student_class.school_year', $schoolYear)
            ->groupBy('students.id, students.school_id, students.firstname, students.lastname')
            ->orderBy('students.lastname', 'ASC')
            ->orderBy('students.firstname', 'ASC')
            ->findAll();
    }

    public function getSchoolIdByStudentId($studentId)
    {
        return $this->select('school_id')
            ->where('id', $studentId)
            ->first()['school_id'] ?? null;
    }

    public function getSchoolIdsByParentId($parentId)
    {
        $results = $this->select('school_id')
            ->where('parent_id', $parentId)
            ->distinct()
            ->findAll();

        return array_column($results, 'school_id');
    }

    public function getStudentIdsByParentId($parentId)
    {
        $results = $this->select('id')
            ->where('parent_id', $parentId)
            ->distinct()
            ->findAll();

        return array_column($results, 'id');
    }

    public function getStudentsWithClassAndEnrollment(?string $schoolYear = null)
    {
        $schoolYear = trim((string) $schoolYear);
        $studentClassJoin = 'student_class.student_id = students.id';
        $enrollmentJoin = 'enrollments.student_id = students.id';
        $selectedYearFilter = '';

        if ($schoolYear !== '') {
            $escapedSchoolYear = $this->db->escape($schoolYear);
            $studentClassJoin .= ' AND student_class.school_year = ' . $escapedSchoolYear;
            $enrollmentJoin .= ' AND enrollments.school_year = ' . $escapedSchoolYear;
            $selectedYearFilter = "
                (
                    student_class.student_id IS NOT NULL
                    OR enrollments.student_id IS NOT NULL
                    OR (
                        NOT EXISTS (
                            SELECT 1
                            FROM student_class sc_history
                            WHERE sc_history.student_id = students.id
                        )
                        AND NOT EXISTS (
                            SELECT 1
                            FROM enrollments e_history
                            WHERE e_history.student_id = students.id
                        )
                    )
                )
            ";
        }

        $builder = $this->select('
            students.*,
            student_class.class_section_id,
            enrollments.enrollment_status,
            enrollments.admission_status,
            u.firstname AS parent_firstname,
            u.lastname  AS parent_lastname
        ')
            ->join('student_class', $studentClassJoin, 'left')
            ->join('enrollments', $enrollmentJoin, 'left')
            ->join('users u',       'u.id = students.parent_id',              'left');

        if ($selectedYearFilter !== '') {
            $builder->where($selectedYearFilter, null, false);
        }

        return $builder
            // keep your original grouping as-is so behavior doesn't change
            ->groupBy('students.id, student_class.class_section_id, enrollments.enrollment_status, enrollments.admission_status')
            ->findAll();
    }

    /*
    public function getStudentsWithClassAndEnrollment()
    {
        return $this->select('students.*, student_class.class_section_id, enrollments.enrollment_status, enrollments.admission_status')
            ->join('student_class', 'student_class.student_id = students.id', 'left')
            ->join('enrollments', 'enrollments.student_id = students.id', 'left')
            ->groupBy('students.id, student_class.class_section_id, enrollments.enrollment_status, enrollments.admission_status')
            ->findAll();
    }
*/

    /**
     * Get student and teacher information based on class_section_id.
     *
     * @param int $classSectionId
     * @param string|null $semester Deprecated/ignored (assignments now tracked per school year only).
     * @param string|null $schoolYear
     * @return array
     */
    public function getStudentInfoByClassSectionId($classSectionId, ?string $semester = null, ?string $schoolYear = null): array
    {
        $classSectionId = (int) $classSectionId;
        if ($classSectionId <= 0) {
            return [];
        }

        // Start from this model's table (likely 'students')
        $builder = $this->builder();

        $builder
            ->select('students.id AS student_id, students.school_id, students.firstname, students.lastname, sc.class_section_id')
            ->join('student_class sc', 'sc.student_id = students.id', 'inner')
            ->where('sc.class_section_id', $classSectionId)
            ->where('students.is_active', 1);

        // Optional term scoping (safe no-ops if null)
        if ($schoolYear !== null) {
            $builder->where('sc.school_year', $schoolYear);
        }

        // Prevent accidental dupes if student_class has multiple rows
        $builder->distinct();
        $builder->orderBy('students.lastname', 'ASC')
            ->orderBy('students.firstname', 'ASC');

        $results = $builder->get()->getResultArray();

        // 🔹 Instead of saving, just add `updated_by` to each result row
        $userId = (int) (session()->get('user_id') ?? 0);
        if (!empty($results)) {
            foreach ($results as &$row) {
                $row['updated_by'] = $userId; // add actor id for use downstream
            }
            unset($row); // good practice to break ref
        }

        return $results ?: [];
    }


    // In your existing StudentModel
    public function getStudentBasic(int $studentId): ?array
    {
        return $this->select('id, firstname, lastname, grade')->find($studentId);
    }

    /**
     * Returns students with:
     * - class/enrollment/admission info
     * - primary parent (guardian) info as aliases the view expects:
     *   parent_firstname, parent_lastname, parent_phone, parent_email
     * - emergency contact info as: emergency_name, emergency_relationship, emergency_phone
     *
     * Adjust table/column names to your schema where noted.
     */
    /*
    public function getStudentsWithClassAndEnrollment(): array
    {
        $db = $this->db;

        // ---- Notes: adjust these names if your schema differs ----
        // users table fields:
        //   users.first_name, users.last_name, users.email, users.phone
        // students table may already have emergency_* columns; if not, enable the alt join below.
        // class/enrollment sources: adjust joins to your real tables/fields.
        // ----------------------------------------------------------

        $builder = $db->table('students s');

        // Base student fields used by the view/controller
        $builder->select([
            's.id',
            's.firstname',
            's.lastname',
            's.is_new',
            's.dob',
            's.registration_date',
            's.photo_consent',
            // If your students table stores class_section_id directly; otherwise replace with a subquery/join
            's.class_section_id',
            // Optional emergency columns ON students table (comment out if you use separate table)
            's.emergency_name',
            's.emergency_relationship',
            's.emergency_phone',
        ]);

        // ---------- Enrollment / Admission status ----------
        // Replace these with your real sources:
        // Example 1: statuses live on students (already selected) – then alias directly:
        // $builder->select('s.enrollment_status, s.admission_status');

        // Example 2: join enrollment/admission tables:
        // $builder->join('enrollments e', 'e.student_id = s.id AND e.is_current = 1', 'left');
        // $builder->select('e.status AS enrollment_status');
        // $builder->join('admissions a', 'a.student_id = s.id', 'left');
        // $builder->select('a.status AS admission_status');

        // If you actually store on students, uncomment this line and remove the example joins above:
        $builder->select('s.enrollment_status, s.admission_status');

        // ---------- Class Section readable name ----------
        // If you already have a helper to resolve the name, the controller uses it.
        // But it’s faster to produce a label here:
        // Example: class_sections (id, name), classes (name) etc. Adjust join/concat as needed.
        $builder->join('class_sections cs', 'cs.id = s.class_section_id', 'left');
        $builder->select("COALESCE(cs.name, 'Class not Assigned') AS class_section");

        // ---------- Family/Guardian (primary parent) ----------
        // Link student -> family via family_students
        $builder->join('family_students fs', 'fs.student_id = s.id', 'left');
        // Join to primary guardian for that family
        $builder->join('family_guardians fg', 'fg.family_id = fs.family_id AND fg.is_primary = 1', 'left');
        // Join to users for the guardian details (ADJUST field names!)
        $builder->join('users pu', 'pu.id = fg.user_id', 'left');

        // Produce the aliases your view expects
        $builder->select([
            'pu.first_name AS parent_firstname',
            'pu.last_name  AS parent_lastname',
            'pu.email      AS parent_email',
            'pu.phone      AS parent_phone',
        ]);

        // ---------- OPTIONAL: If emergency contact lives in a separate table ----------
        // Comment OUT the s.emergency_* selections above and use this instead:
        // $builder->join('student_emergency_contacts sec', 'sec.student_id = s.id AND sec.is_primary = 1', 'left');
        // $builder->select([
        //     'sec.name        AS emergency_name',
        //     'sec.relationship AS emergency_relationship',
        //     'sec.phone        AS emergency_phone',
        // ]);

        // If you need only currently active / current semester, apply where here:
        // $builder->where('s.is_active', 1);

        // Avoid duplicate rows (e.g., if multiple guardians slipped in)
        $builder->groupBy('s.id');

        // Optional: order
        $builder->orderBy('s.lastname', 'ASC')->orderBy('s.firstname', 'ASC');

        return $builder->get()->getResultArray();
    }
        */
}
