<?php

namespace App\Modules\Academic\Controllers;

use App\Core\BaseApiController;
use App\Modules\Academic\Models\LessonSlotModel;
use App\Modules\Academic\Models\ScheduleModel;
use CodeIgniter\HTTP\ResponseInterface;

/**
 * Weekly Schedule Management API (ADMIN only).
 */
class ScheduleManagementController extends BaseApiController
{
    protected ScheduleModel   $scheduleModel;
    protected LessonSlotModel $lessonSlotModel;

    public function __construct()
    {
        $this->scheduleModel   = new ScheduleModel();
        $this->lessonSlotModel = new LessonSlotModel();
    }

    /**
     * GET /api/academic/schedules/class/{classId}
     * Returns weekly schedule grid: slots with days 1–5, each cell schedule or null.
     */
    public function getByClass($classId): ResponseInterface
    {
        $classId = (int) $classId;
        $slots   = $this->lessonSlotModel->where('is_active', 1)->orderBy('slot_number', 'ASC')->findAll();
        $rows    = $this->scheduleModel->where('class_id', $classId)->findAll();

        $bySlotDay = [];
        foreach ($rows as $row) {
            $slotId = $row->lesson_slot_id ?? 0;
            $day    = (int) $row->day_of_week;
            if ($slotId && $day >= 1 && $day <= 7) {
                $bySlotDay[$slotId][$day] = $this->scheduleToArray($row);
            }
        }

        $grid = [];
        foreach ($slots as $slot) {
            $slotId = (int) $slot->id;
            $days   = [];
            for ($d = 1; $d <= 5; $d++) {
                $days[$d] = $bySlotDay[$slotId][$d] ?? null;
            }
            $grid[] = [
                'lesson_slot_id' => $slotId,
                'slot_number'    => (int) $slot->slot_number,
                'start_time'     => (string) $slot->start_time,
                'end_time'       => (string) $slot->end_time,
                'days'           => $days,
            ];
        }

        return $this->successResponse($grid, 'Weekly schedule');
    }

    /**
     * POST /api/academic/schedules/bulk-save
     * Body: { class_id, schedules: [ { day_of_week, lesson_slot_id, subject_id, teacher_user_id [, room] }, ... ] }
     * Deletes existing schedules for class then inserts new ones in a transaction.
     */
    public function bulkSave(): ResponseInterface
    {
        $input = $this->request->getJSON(true) ?? [];
        $classId = (int) ($input['class_id'] ?? 0);
        $items   = $input['schedules'] ?? [];

        if ($classId <= 0) {
            return $this->errorResponse('class_id is required and must be positive', null, null, 422);
        }

        if (!is_array($items)) {
            return $this->errorResponse('schedules must be an array', null, null, 422);
        }

        $db = \Config\Database::connect();
        $db->transStart();

        try {
            $this->scheduleModel->where('class_id', $classId)->delete();
            $this->scheduleModel->skipValidation(true);
            foreach ($items as $item) {
                $day   = (int) ($item['day_of_week'] ?? 0);
                $slot  = (int) ($item['lesson_slot_id'] ?? 0);
                $subj  = (int) ($item['subject_id'] ?? 0);
                $teacher = (int) ($item['teacher_user_id'] ?? 0);
                if ($day < 1 || $day > 7 || $slot <= 0 || $subj <= 0) {
                    $db->transRollback();
                    return $this->errorResponse('Each schedule must have day_of_week (1-7), lesson_slot_id, subject_id', null, null, 422);
                }
                $data = [
                    'class_id'        => $classId,
                    'subject_id'      => $subj,
                    'teacher_user_id' => $teacher ?: null,
                    'lesson_slot_id'  => $slot,
                    'day_of_week'     => $day,
                    'room'            => isset($item['room']) ? (string) $item['room'] : null,
                    'is_active'       => 1,
                ];
                if ($this->scheduleModel->insert($data) === false) {
                    $db->transRollback();
                    return $this->errorResponse('Failed to insert schedule', null, null, 422);
                }
            }
            $this->scheduleModel->skipValidation(false);
            $db->transComplete();
        } catch (\Throwable $e) {
            if ($db->transStatus() === false) {
                $db->transRollback();
            }
            return $this->errorResponse($e->getMessage(), null, null, 500);
        }

        if ($db->transStatus() === false) {
            return $this->errorResponse('Database transaction failed', null, null, 500);
        }

        return $this->successResponse(null, 'Schedules saved');
    }

    protected function scheduleToArray($schedule): array
    {
        if (is_array($schedule)) {
            return [
                'id'              => (int) ($schedule['id'] ?? 0),
                'class_id'        => (int) ($schedule['class_id'] ?? 0),
                'subject_id'      => (int) ($schedule['subject_id'] ?? 0),
                'teacher_user_id' => isset($schedule['teacher_user_id']) ? (int) $schedule['teacher_user_id'] : null,
                'lesson_slot_id'  => (int) ($schedule['lesson_slot_id'] ?? 0),
                'day_of_week'     => (int) ($schedule['day_of_week'] ?? 0),
                'room'            => isset($schedule['room']) ? (string) $schedule['room'] : null,
            ];
        }
        return [
            'id'              => (int) $schedule->id,
            'class_id'        => (int) $schedule->class_id,
            'subject_id'      => (int) $schedule->subject_id,
            'teacher_user_id' => $schedule->teacher_user_id !== null ? (int) $schedule->teacher_user_id : null,
            'lesson_slot_id'  => (int) $schedule->lesson_slot_id,
            'day_of_week'     => (int) $schedule->day_of_week,
            'room'            => $schedule->room !== null ? (string) $schedule->room : null,
        ];
    }
}
