<?php

namespace App\Controllers\Guru;

use App\Controllers\BaseController;
use App\Models\TeacherModel;
use App\Models\HomeroomAssignmentModel;
use App\Models\AttendanceModel;
use App\Models\AcademicPeriodModel;
use App\Models\ClassroomModel;
use App\Models\SchoolSettingModel;
use App\Services\StorageService;

class HomeroomReport extends BaseController
{
    protected $teacherModel;
    protected $homeroomModel;
    protected $attendanceModel;
    protected $periodModel;
    protected $classroomModel;
    protected $schoolSettingModel;

    public function __construct()
    {
        $this->teacherModel = new TeacherModel();
        $this->homeroomModel = new HomeroomAssignmentModel();
        $this->attendanceModel = new AttendanceModel();
        $this->periodModel = new AcademicPeriodModel();
        $this->classroomModel = new ClassroomModel();
        $this->schoolSettingModel = new SchoolSettingModel();
    }

    private function getTeacherAndAssignment()
    {
        $teacher = $this->teacherModel->where('user_id', session()->get('user_id'))->first();
        if (!$teacher) {
            return [null, null, null];
        }

        $activePeriod = $this->periodModel->getActive();
        if (!$activePeriod) {
            return [$teacher, null, null];
        }

        $assignment = $this->homeroomModel->where('teacher_id', $teacher['id'])
                                          ->where('academic_period_id', $activePeriod['id'])
                                          ->first();

        return [$teacher, $activePeriod, $assignment];
    }

    private function getDefaultMonthYear($activePeriod)
    {
        $currentMonth = date('m');
        $currentYear = date('Y');
        $currentDate = date('Y-m-d');

        if ($currentDate > $activePeriod['end_date']) {
            $defaultMonth = date('m', strtotime($activePeriod['end_date']));
            $defaultYear = date('Y', strtotime($activePeriod['end_date']));
        } elseif ($currentDate < $activePeriod['start_date']) {
            $defaultMonth = date('m', strtotime($activePeriod['start_date']));
            $defaultYear = date('Y', strtotime($activePeriod['start_date']));
        } else {
            $defaultMonth = $currentMonth;
            $defaultYear = $currentYear;
        }

        return [$defaultMonth, $defaultYear];
    }

    public function studentList()
    {
        list($teacher, $activePeriod, $assignment) = $this->getTeacherAndAssignment();

        if (!$teacher) {
            return redirect()->to('/dashboard')->with('error', 'Data guru tidak ditemukan!');
        }
        if (!$activePeriod) {
            return redirect()->to('/guru/dashboard')->with('error', 'Periode akademik aktif tidak ditemukan.');
        }
        if (!$assignment) {
            return redirect()->to('/guru/dashboard')->with('error', 'Akses ditolak! Anda bukan Wali Kelas pada periode aktif.');
        }

        $classroom = $this->classroomModel->select('classrooms.name as classroom_name, grades.name as grade_name')
                                          ->join('grades', 'grades.id = classrooms.grade_id')
                                          ->where('classrooms.id', $assignment['classroom_id'])
                                          ->first();

        $db = \Config\Database::connect();
        $students = $db->table('student_academic_histories as sah')
            ->select('
                students.id,
                students.nis,
                students.nisn,
                students.full_name,
                students.gender,
                students.phone,
                students.father_name,
                students.mother_name,
                students.address,
                students.photo
            ')
            ->join('students', 'students.id = sah.student_id')
            ->where('sah.classroom_id', $assignment['classroom_id'])
            ->where('sah.academic_period_id', $activePeriod['id'])
            ->where('students.deleted_at', null)
            ->where('students.status', 'Aktif')
            ->orderBy('students.full_name', 'ASC')
            ->get()
            ->getResultArray();

        foreach ($students as &$s) {
            $s['photo_url'] = StorageService::getUrl($s['photo'], 'students');
        }

        $data = [
            'title'        => 'Daftar Siswa Kelas ' . $classroom['classroom_name'],
            'students'     => $students,
            'classroom'    => $classroom,
            'activePeriod' => $activePeriod,
        ];

        return view('guru/homeroom_students', $data);
    }

    public function index()
    {
        list($teacher, $activePeriod, $assignment) = $this->getTeacherAndAssignment();

        if (!$teacher) {
            return redirect()->to('/dashboard')->with('error', 'Data guru tidak ditemukan!');
        }
        if (!$activePeriod) {
            return redirect()->to('/guru/dashboard')->with('error', 'Periode akademik aktif tidak ditemukan.');
        }
        if (!$assignment) {
            return redirect()->to('/guru/dashboard')->with('error', 'Akses ditolak! Anda bukan Wali Kelas pada periode aktif.');
        }

        $classroom = $this->classroomModel->select('classrooms.name as classroom_name, grades.name as grade_name')
                                          ->join('grades', 'grades.id = classrooms.grade_id')
                                          ->where('classrooms.id', $assignment['classroom_id'])
                                          ->first();

        list($defaultMonth, $defaultYear) = $this->getDefaultMonthYear($activePeriod);

        $startYear = (int)date('Y', strtotime($activePeriod['start_date']));
        $endYear = (int)date('Y', strtotime($activePeriod['end_date']));
        $years = range($startYear, $endYear);

        $months = [
            '01' => 'Januari', '02' => 'Februari', '03' => 'Maret', '04' => 'April',
            '05' => 'Mei', '06' => 'Juni', '07' => 'Juli', '08' => 'Agustus',
            '09' => 'September', '10' => 'Oktober', '11' => 'November', '12' => 'Desember'
        ];

        // Hitung today's absent
        $db = \Config\Database::connect();
        $today = date('Y-m-d');
        $todayAbsences = $db->table('attendances')
            ->select('attendances.status, students.nis, students.full_name')
            ->join('students', 'students.id = attendances.student_id')
            ->where('attendances.classroom_id', $assignment['classroom_id'])
            ->where('attendances.academic_period_id', $activePeriod['id'])
            ->where('attendances.date', $today)
            ->orderBy('students.full_name', 'ASC')
            ->get()
            ->getResultArray();

        $totalStudents = $db->table('student_academic_histories')
            ->join('students', 'students.id = student_academic_histories.student_id')
            ->where('student_academic_histories.classroom_id', $assignment['classroom_id'])
            ->where('student_academic_histories.academic_period_id', $activePeriod['id'])
            ->where('students.deleted_at', null)
            ->where('students.status', 'Aktif')
            ->countAllResults();

        return view('guru/homeroom_report/index', [
            'title' => 'Laporan Wali Kelas',
            'teacher' => $teacher,
            'activePeriod' => $activePeriod,
            'classroom' => $classroom,
            'defaultMonth' => $defaultMonth,
            'defaultYear' => $defaultYear,
            'years' => $years,
            'months' => $months,
            'todayAbsences' => $todayAbsences,
            'totalStudents' => $totalStudents,
        ]);
    }

    public function getRekap()
    {
        list($teacher, $activePeriod, $assignment) = $this->getTeacherAndAssignment();

        if (!$teacher || !$activePeriod || !$assignment) {
            return $this->response->setJSON([
                'success' => false,
                'message' => 'Unauthorized or invalid configuration'
            ])->setStatusCode(403);
        }

        list($defaultMonth, $defaultYear) = $this->getDefaultMonthYear($activePeriod);

        $month = $this->request->getGet('month') ?? $defaultMonth;
        $year = $this->request->getGet('year') ?? $defaultYear;

        $startDate = "$year-$month-01";
        $endDate = date('Y-m-t', strtotime($startDate));
        $activeDays = $this->attendanceModel->countActiveDays($startDate, $endDate);

        $db = \Config\Database::connect();
        
        // Fetch academic calendar holidays
        $holidayMap = [];
        $holidays = $db->table('calendar_events')
            ->select('calendar_events.start_date, calendar_events.end_date, calendar_events.title')
            ->join('calendar_categories', 'calendar_categories.id = calendar_events.category_id')
            ->where('calendar_categories.is_libur', 1)
            ->where('calendar_events.deleted_at', null)
            ->where('calendar_events.start_date <=', $endDate)
            ->where('calendar_events.end_date >=', $startDate)
            ->get()
            ->getResultArray();

        foreach ($holidays as $h) {
            $start = strtotime($h['start_date']);
            $end = strtotime($h['end_date']);
            for ($curr = $start; $curr <= $end; $curr = strtotime('+1 day', $curr)) {
                $dateStr = date('Y-m-d', $curr);
                if ($dateStr >= $startDate && $dateStr <= $endDate) {
                    $holidayMap[$dateStr] = $h['title'];
                }
            }
        }

        $days = [];
        $daysInMonth = (int)date('t', strtotime($startDate));
        for ($d = 1; $d <= $daysInMonth; $d++) {
            $currentDateString = sprintf('%s-%s-%02d', $year, $month, $d);
            $dayOfWeek = date('N', strtotime($currentDateString));
            $isSunday = ($dayOfWeek == 7);
            $isHoliday = isset($holidayMap[$currentDateString]);
            $holidayTitle = $holidayMap[$currentDateString] ?? null;
            
            $days[] = [
                'day' => $d,
                'is_off' => ($isSunday || $isHoliday),
                'holiday_title' => $holidayTitle,
            ];
        }

        $students = $db->table('student_academic_histories')
            ->select('students.id, students.nis, students.full_name, students.gender')
            ->join('students', 'students.id = student_academic_histories.student_id')
            ->where('student_academic_histories.classroom_id', $assignment['classroom_id'])
            ->where('student_academic_histories.academic_period_id', $activePeriod['id'])
            ->where('students.deleted_at', null)
            ->where('students.status', 'Aktif')
            ->orderBy('students.full_name', 'ASC')
            ->get()
            ->getResultArray();

        $attendancesRaw = $db->table('attendances')
            ->select('student_id, date, status')
            ->where('classroom_id', $assignment['classroom_id'])
            ->where('academic_period_id', $activePeriod['id'])
            ->where('date >=', $startDate)
            ->where('date <=', $endDate)
            ->get()
            ->getResultArray();

        $attMap = [];
        $attDailyMap = [];
        foreach ($attendancesRaw as $a) {
            $sId = $a['student_id'];
            $status = $a['status'];
            $day = (int)date('j', strtotime($a['date']));
            
            if (!isset($attMap[$sId])) {
                $attMap[$sId] = ['sakit' => 0, 'izin' => 0, 'alpha' => 0];
            }
            if ($status === 'Sakit') $attMap[$sId]['sakit']++;
            elseif ($status === 'Izin') $attMap[$sId]['izin']++;
            elseif ($status === 'Alpha') $attMap[$sId]['alpha']++;

            $attDailyMap[$sId][$day] = $status;
        }

        $recap = [];
        $totalAttendanceRate = 0;
        $attentionRequired = [];

        foreach ($students as $student) {
            $sId = $student['id'];
            $sakit = $attMap[$sId]['sakit'] ?? 0;
            $izin = $attMap[$sId]['izin'] ?? 0;
            $alpha = $attMap[$sId]['alpha'] ?? 0;
            $absent = $sakit + $izin + $alpha;
            
            $presentDays = $activeDays - $absent;
            if ($presentDays < 0) $presentDays = 0;
            
            $attendanceRate = $activeDays > 0 ? ($presentDays / $activeDays) * 100 : 100;
            $attendanceRate = round($attendanceRate, 2);
            
            $totalAttendanceRate += $attendanceRate;

            $studentDailyStatuses = [];
            for ($d = 1; $d <= $daysInMonth; $d++) {
                $status = $attDailyMap[$sId][$d] ?? null;
                if ($status === 'Sakit') {
                    $studentDailyStatuses[$d] = 'S';
                } elseif ($status === 'Izin') {
                    $studentDailyStatuses[$d] = 'I';
                } elseif ($status === 'Alpha') {
                    $studentDailyStatuses[$d] = 'A';
                } else {
                    $studentDailyStatuses[$d] = '.';
                }
            }
            
            $recap[] = [
                'nis'             => $student['nis'],
                'full_name'       => $student['full_name'],
                'gender'          => $student['gender'],
                'sakit'           => $sakit,
                'izin'            => $izin,
                'alpha'           => $alpha,
                'attendance_rate' => $attendanceRate,
                'statuses'        => $studentDailyStatuses,
            ];
            
            // Warnings (Sakit >= 3, Izin >= 3, Alpha >= 2)
            $needsAttention = false;
            $reasons = [];
            if ($alpha >= 2) {
                $needsAttention = true;
                $reasons[] = "Alpha $alpha hari";
            }
            if ($sakit >= 3) {
                $needsAttention = true;
                $reasons[] = "Sakit $sakit hari";
            }
            if ($izin >= 3) {
                $needsAttention = true;
                $reasons[] = "Izin $izin hari";
            }
            
            if ($needsAttention) {
                $attentionRequired[] = [
                    'nis'       => $student['nis'],
                    'full_name' => $student['full_name'],
                    'reason'    => implode(', ', $reasons),
                    'sakit'     => $sakit,
                    'izin'      => $izin,
                    'alpha'     => $alpha,
                ];
            }
        }

        $averageRate = count($students) > 0 ? round($totalAttendanceRate / count($students), 2) : 100;

        return $this->response->setJSON([
            'success' => true,
            'active_days' => $activeDays,
            'average_rate' => $averageRate . '%',
            'days' => $days,
            'recap' => $recap,
            'attention_required' => $attentionRequired
        ]);
    }

    public function exportPdf()
    {
        list($teacher, $activePeriod, $assignment) = $this->getTeacherAndAssignment();

        if (!$teacher || !$activePeriod || !$assignment) {
            return redirect()->to('/dashboard')->with('error', 'Akses ditolak!');
        }

        $month = $this->request->getGet('month');
        $year = $this->request->getGet('year');

        if (!$month || !$year) {
            list($defaultMonth, $defaultYear) = $this->getDefaultMonthYear($activePeriod);
            $month = $defaultMonth;
            $year = $defaultYear;
        }

        $months = [
            '01' => 'Januari', '02' => 'Februari', '03' => 'Maret', '04' => 'April',
            '05' => 'Mei', '06' => 'Juni', '07' => 'Juli', '08' => 'Agustus',
            '09' => 'September', '10' => 'Oktober', '11' => 'November', '12' => 'Desember'
        ];

        $monthName = $months[$month] ?? '';

        $startDate = "$year-$month-01";
        $endDate = date('Y-m-t', strtotime($startDate));
        $activeDays = $this->attendanceModel->countActiveDays($startDate, $endDate);

        $db = \Config\Database::connect();
        
        // Fetch academic calendar holidays
        $holidayMap = [];
        $holidays = $db->table('calendar_events')
            ->select('calendar_events.start_date, calendar_events.end_date, calendar_events.title')
            ->join('calendar_categories', 'calendar_categories.id = calendar_events.category_id')
            ->where('calendar_categories.is_libur', 1)
            ->where('calendar_events.deleted_at', null)
            ->where('calendar_events.start_date <=', $endDate)
            ->where('calendar_events.end_date >=', $startDate)
            ->get()
            ->getResultArray();

        foreach ($holidays as $h) {
            $start = strtotime($h['start_date']);
            $end = strtotime($h['end_date']);
            for ($curr = $start; $curr <= $end; $curr = strtotime('+1 day', $curr)) {
                $dateStr = date('Y-m-d', $curr);
                if ($dateStr >= $startDate && $dateStr <= $endDate) {
                    $holidayMap[$dateStr] = $h['title'];
                }
            }
        }

        $days = [];
        $daysInMonth = (int)date('t', strtotime($startDate));
        for ($d = 1; $d <= $daysInMonth; $d++) {
            $currentDateString = sprintf('%s-%s-%02d', $year, $month, $d);
            $dayOfWeek = date('N', strtotime($currentDateString));
            $isSunday = ($dayOfWeek == 7);
            $isHoliday = isset($holidayMap[$currentDateString]);
            $holidayTitle = $holidayMap[$currentDateString] ?? null;
            
            $days[] = [
                'day' => $d,
                'is_off' => ($isSunday || $isHoliday),
                'holiday_title' => $holidayTitle,
            ];
        }

        $students = $db->table('student_academic_histories')
            ->select('students.id, students.nis, students.full_name, students.gender')
            ->join('students', 'students.id = student_academic_histories.student_id')
            ->where('student_academic_histories.classroom_id', $assignment['classroom_id'])
            ->where('student_academic_histories.academic_period_id', $activePeriod['id'])
            ->where('students.deleted_at', null)
            ->where('students.status', 'Aktif')
            ->orderBy('students.full_name', 'ASC')
            ->get()
            ->getResultArray();

        $attendancesRaw = $db->table('attendances')
            ->select('student_id, date, status')
            ->where('classroom_id', $assignment['classroom_id'])
            ->where('academic_period_id', $activePeriod['id'])
            ->where('date >=', $startDate)
            ->where('date <=', $endDate)
            ->get()
            ->getResultArray();

        $attMap = [];
        $attDailyMap = [];
        foreach ($attendancesRaw as $a) {
            $sId = $a['student_id'];
            $status = $a['status'];
            $day = (int)date('j', strtotime($a['date']));
            
            if (!isset($attMap[$sId])) {
                $attMap[$sId] = ['sakit' => 0, 'izin' => 0, 'alpha' => 0];
            }
            if ($status === 'Sakit') $attMap[$sId]['sakit']++;
            elseif ($status === 'Izin') $attMap[$sId]['izin']++;
            elseif ($status === 'Alpha') $attMap[$sId]['alpha']++;

            $attDailyMap[$sId][$day] = $status;
        }

        $recap = [];
        $totalAttendanceRate = 0;

        foreach ($students as $student) {
            $sId = $student['id'];
            $sakit = $attMap[$sId]['sakit'] ?? 0;
            $izin = $attMap[$sId]['izin'] ?? 0;
            $alpha = $attMap[$sId]['alpha'] ?? 0;
            $absent = $sakit + $izin + $alpha;
            
            $presentDays = $activeDays - $absent;
            if ($presentDays < 0) $presentDays = 0;
            
            $attendanceRate = $activeDays > 0 ? ($presentDays / $activeDays) * 100 : 100;
            $attendanceRate = round($attendanceRate, 2);
            
            $totalAttendanceRate += $attendanceRate;

            $studentDailyStatuses = [];
            for ($d = 1; $d <= $daysInMonth; $d++) {
                $status = $attDailyMap[$sId][$d] ?? null;
                if ($status === 'Sakit') {
                    $studentDailyStatuses[$d] = 'S';
                } elseif ($status === 'Izin') {
                    $studentDailyStatuses[$d] = 'I';
                } elseif ($status === 'Alpha') {
                    $studentDailyStatuses[$d] = 'A';
                } else {
                    $studentDailyStatuses[$d] = '.';
                }
            }
            
            $recap[] = [
                'nis'             => $student['nis'],
                'full_name'       => $student['full_name'],
                'gender'          => $student['gender'],
                'sakit'           => $sakit,
                'izin'            => $izin,
                'alpha'           => $alpha,
                'attendance_rate' => $attendanceRate,
                'statuses'        => $studentDailyStatuses,
            ];
        }

        $averageRate = count($students) > 0 ? round($totalAttendanceRate / count($students), 2) : 100;

        $classroom = $this->classroomModel->select('classrooms.name as classroom_name, grades.name as grade_name')
                                          ->join('grades', 'grades.id = classrooms.grade_id')
                                          ->where('classrooms.id', $assignment['classroom_id'])
                                          ->first();

        $schoolSettings = $this->schoolSettingModel->getSettings();

        return view('guru/homeroom_report/export_pdf', [
            'title' => 'Laporan Presensi Kelas ' . $classroom['grade_name'] . ' ' . $classroom['classroom_name'],
            'activePeriod' => $activePeriod,
            'classroom' => $classroom,
            'monthName' => $monthName,
            'month' => $month,
            'year' => $year,
            'activeDays' => $activeDays,
            'days' => $days,
            'recap' => $recap,
            'averageRate' => $averageRate . '%',
            'schoolSettings' => $schoolSettings,
            'teacher' => $teacher,
        ]);
    }
}
