<?php

namespace App\Commands;

use App\Controllers\View\EmailController;
use App\Models\ClassSectionModel;
use App\Models\ConfigurationModel;
use App\Models\TeacherSubmissionNotificationHistoryModel;
use App\Models\UserModel;
use CodeIgniter\CLI\BaseCommand;
use CodeIgniter\CLI\CLI;
use Config\Database;

class SendExamDraftDeadlineReminders extends BaseCommand
{
    protected $group = 'Exam Drafts';
    protected $name = 'exam-drafts:deadline-reminders';
    protected $description = 'Sends exam draft deadline reminders to teachers who have not submitted drafts.';

    public function run(array $params)
    {
        helper('date');

        $configModel = new ConfigurationModel();
        $schoolYear = (string) ($configModel->getConfig('school_year') ?? '');
        $semester = (string) ($configModel->getConfig('semester') ?? '');
        $deadlineValue = trim((string) ($configModel->getConfig('exam_draft_deadline') ?? ''));
        if ($deadlineValue === '') {
            CLI::write('exam_draft_deadline is not configured.', 'yellow');
            return;
        }

        $tz = new \DateTimeZone(config('App')->appTimezone ?? 'UTC');
        try {
            $deadline = new \DateTimeImmutable($deadlineValue, $tz);
        } catch (\Throwable $e) {
            CLI::write('Invalid exam_draft_deadline value.', 'red');
            return;
        }
        $deadline = $deadline->setTime(0, 0, 0);
        $today = new \DateTimeImmutable('now', $tz);
        $today = $today->setTime(0, 0, 0);

        if ($today > $deadline) {
            CLI::write('Deadline has passed. No reminders sent.', 'yellow');
            return;
        }

        $daysToDeadline = (int) $today->diff($deadline)->format('%r%a');
        if (!$this->shouldSendOnDay($daysToDeadline)) {
            CLI::write('No reminder scheduled for today.', 'yellow');
            return;
        }

        $db = Database::connect();
        $teacherClassRows = $db->table('teacher_class')
            ->select('teacher_id, class_section_id, school_year')
            ->when($schoolYear !== '', static function ($builder) use ($schoolYear) {
                return $builder->where('school_year', $schoolYear);
            })
            ->get()
            ->getResultArray();

        if (empty($teacherClassRows)) {
            CLI::write('No teacher assignments found.', 'yellow');
            return;
        }

        $draftTable = 'exam_drafts';
        $fields = $db->getFieldNames($draftTable);
        $teacherColumn = in_array('teacher_id', $fields, true) ? 'teacher_id' : 'author_id';
        $hasStatusColumn = in_array('status', $fields, true);
        $hasIsLegacyColumn = in_array('is_legacy', $fields, true);

        $draftsQuery = $db->table($draftTable)
            ->select("{$teacherColumn} AS teacher_id, class_section_id")
            ->when($schoolYear !== '', static function ($builder) use ($schoolYear) {
                return $builder->where('school_year', $schoolYear);
            })
            ->when($semester !== '', static function ($builder) use ($semester) {
                return $builder->where('semester', $semester);
            });

        if ($hasStatusColumn) {
            $draftsQuery = $draftsQuery->where('status !=', 'legacy');
        }
        if ($hasIsLegacyColumn) {
            $draftsQuery = $draftsQuery->where('is_legacy', 0);
        }

        $draftRows = $draftsQuery->get()->getResultArray();
        $submittedMap = [];
        foreach ($draftRows as $row) {
            $key = (int) ($row['teacher_id'] ?? 0) . '|' . (int) ($row['class_section_id'] ?? 0);
            $submittedMap[$key] = true;
        }

        $missingByTeacher = [];
        foreach ($teacherClassRows as $row) {
            $teacherId = (int) ($row['teacher_id'] ?? 0);
            $classSectionId = (int) ($row['class_section_id'] ?? 0);
            if ($teacherId <= 0 || $classSectionId <= 0) {
                continue;
            }
            $key = $teacherId . '|' . $classSectionId;
            if (!isset($submittedMap[$key])) {
                $missingByTeacher[$teacherId][] = $classSectionId;
            }
        }

        if (empty($missingByTeacher)) {
            CLI::write('All teachers have submitted drafts.', 'green');
            return;
        }

        $userModel = new UserModel();
        $classSectionModel = new ClassSectionModel();
        $historyModel = new TeacherSubmissionNotificationHistoryModel();
        $mailer = new EmailController();

        $classSections = $classSectionModel
            ->select('class_section_id, class_section_name')
            ->findAll();
        $classLookup = [];
        foreach ($classSections as $section) {
            $classLookup[(int) ($section['class_section_id'] ?? 0)] = $section['class_section_name'] ?? '';
        }

        $todayStamp = $today->format('Y-m-d');
        foreach ($missingByTeacher as $teacherId => $sectionIds) {
            $teacher = $userModel->find($teacherId);
            $email = $teacher['email'] ?? '';
            if ($email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
                continue;
            }

            $alreadySent = $historyModel
                ->where('teacher_id', $teacherId)
                ->where('notification_category', 'exam_draft_deadline')
                ->where('school_year', $schoolYear)
                ->where('semester', $semester)
                ->like('sent_at', $todayStamp)
                ->countAllResults() > 0;
            if ($alreadySent) {
                continue;
            }

            $classNames = array_map(static function ($id) use ($classLookup) {
                return $classLookup[(int) $id] ?? "Class {$id}";
            }, $sectionIds);
            $classList = implode(', ', $classNames);
            $teacherName = trim(($teacher['firstname'] ?? '') . ' ' . ($teacher['lastname'] ?? ''));
            if ($teacherName === '') {
                $teacherName = 'Teacher';
            }

            $subject = 'Reminder: Exam draft submission deadline';
            $body = '<p>Dear ' . esc($teacherName) . ',</p>'
                . '<p>This is a reminder to submit your exam draft(s) for: ' . esc($classList) . '.</p>'
                . '<p>Deadline: <strong>' . esc($deadline->format('Y-m-d')) . '</strong></p>'
                . '<p>Please submit your draft at <a href="' . esc(base_url('teacher/exam-drafts')) . '">Teacher Exam Drafts</a>.</p>'
                . '<p>Thank you.</p>';

            $status = 'failed';
            if ($mailer->sendEmail($email, $subject, $body, 'notifications')) {
                $status = 'sent';
                CLI::write("Sent reminder to {$email}", 'green');
            }

            $historyModel->insert([
                'teacher_id' => $teacherId,
                'class_section_id' => 0,
                'admin_id' => null,
                'notification_category' => 'exam_draft_deadline',
                'message' => strip_tags($body),
                'status' => $status,
                'school_year' => $schoolYear,
                'semester' => $semester,
                'sent_at' => utc_now(),
            ]);
        }
    }

    private function shouldSendOnDay(int $daysToDeadline): bool
    {
        if ($daysToDeadline < 0) {
            return false;
        }
        if ($daysToDeadline <= 4) {
            return true;
        }
        return in_array($daysToDeadline, [28, 21, 14, 7], true);
    }
}
