<?php

namespace App\Http\Controllers;


use App\Models\AcademicPeriod;
use App\Models\Classes;
use App\Models\Schedule;
use App\Models\Subject;
use App\Models\Teacher;
use App\Services\QrLinkService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Crypt;

class JadwalController extends Controller
{
    protected QrLinkService $qrLinkService;

    public function __construct(QrLinkService $qrLinkService)
    {
        $this->qrLinkService = $qrLinkService;
    }
    public function index()
    {
           $kelas = Classes::all();
           $mapel = Subject::all();

           // Join teachers dengan subjects berdasarkan kolom subject (code)
           $guru = Teacher::all()->map(function($teacher) {
               // Cari subject berdasarkan code yang ada di kolom subject teacher
               // Gunakan array_map('trim', ...) untuk menghilangkan spasi sebelum/sesudah koma
               $subjectCodes = array_map('trim', explode(',', $teacher->subject));
               $subjects = Subject::whereIn('code', $subjectCodes)->pluck('id')->toArray();
               $teacher->subject_ids = $subjects;
               return $teacher;
           });

           $periodes = AcademicPeriod::orderBy('start_date', 'desc')->get();
           $periode_aktif = AcademicPeriod::where('is_active', true)->first();
           $jadwal = Schedule::with(['class', 'subject', 'teacher'])->get();
           return view('pages.jadwal.jadwal', compact('kelas', 'mapel', 'guru', 'periodes', 'periode_aktif', 'jadwal'));
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'day_of_week' => 'required|string',
            'period_start' => 'required|integer',
            'period_end' => 'required|integer',
            'start_time' => 'required|string',
            'end_time' => 'required|string',
            'code' => 'nullable|string',
            'id_class' => 'required|exists:clases,id',
            'id_subject' => 'required|exists:subjects,id',
            'id_teacher' => 'required|exists:teachers,id',
            'id_academic_periods' => 'nullable|exists:academic_periods,id',
        ]);

        // Hitung jam mulai dan jam selesai
        $startHour = 7 + ($validated['period_start'] - 1);
        $endHour = 7 + ($validated['period_end'] - 1);
        $start_time = sprintf('%02d:00', $startHour);
        $end_time = sprintf('%02d:00', $endHour);

        // Ambil data untuk kode otomatis
        $class = Classes::find($validated['id_class']);
        $subject = Subject::find($validated['id_subject']);
        $period = $validated['id_academic_periods'] ?? '';
        $token = (string) random_int(1000, 9999);

        $day = strtoupper(substr($validated['day_of_week'], 0, 3));
        $className = $class ? $class->name : '';
        $subjectCode = $subject ? $subject->code : '';
        $periodCode = $period ?: '0';

        $autoCode = "{$className}-{$day}-{$validated['period_start']}-{$validated['period_end']}-{$subjectCode}-{$periodCode}-{$token}";

        $code = $request->input('code') ?: $autoCode;

        // Hash code sebelum simpan ke database
        $hashedCode = Crypt::encryptString($code);

        Schedule::create([
            // make day of week to lowercase
            'day_of_week' => strtolower($validated['day_of_week']),
            'period_start' => $validated['period_start'],
            'period_end' => $validated['period_end'],
            'start_time' => $validated['start_time'],
            'end_time' => $validated['end_time'],
            'code' => $hashedCode,
            'id_class' => $validated['id_class'],
            'id_subject' => $validated['id_subject'],
            'id_teacher' => $validated['id_teacher'],
            'id_academic_periods' => $validated['id_academic_periods'] ?? null,
        ]);

        return redirect()->route('jadwal.index')->with('success', 'Jadwal berhasil ditambahkan!');
    }

     public function update(Request $request, $id)
    {
        $validated = $request->validate([
            'day_of_week' => 'required|string',
            'period_start' => 'required|integer',
            'period_end' => 'required|integer',
            'start_time' => 'required|string',
            'end_time' => 'required|string',
            'code' => 'required|string',
            'id_class' => 'required|exists:clases,id',
            'id_subject' => 'required|exists:subjects,id',
            'id_teacher' => 'required|exists:teachers,id',
            'id_academic_periods' => 'nullable|exists:academic_periods,id',
        ]);

        // Hitung jam mulai dan jam selesai
        $startHour = 7 + ($validated['period_start'] - 1);
        $endHour = 7 + ($validated['period_end'] - 1);
        $start_time = sprintf('%02d:00', $startHour);
        $end_time = sprintf('%02d:00', $endHour);

        // Ambil schedule lama untuk cek perubahan dan avoid double encryption
        $jadwalLama = Schedule::findOrFail($id);

        // Cek apakah ada perubahan di field-field yang mempengaruhi code
        $codeChanged = false;
        if ($jadwalLama->day_of_week != strtolower($validated['day_of_week']) ||
            $jadwalLama->period_start != $validated['period_start'] ||
            $jadwalLama->period_end != $validated['period_end'] ||
            $jadwalLama->id_subject != $validated['id_subject'] ||
            $jadwalLama->id_class != $validated['id_class'] ||
            $jadwalLama->id_academic_periods != $validated['id_academic_periods']) {
            $codeChanged = true;
        }

        // Generate code baru jika ada perubahan, atau gunakan code lama
        if ($codeChanged) {
            // Generate code baru
            $class = Classes::find($validated['id_class']);
            $subject = Subject::find($validated['id_subject']);
            $period = $validated['id_academic_periods'] ?? '';
            $token = (string) random_int(1000, 9999);

            $day = strtoupper(substr($validated['day_of_week'], 0, 3));
            $className = $class ? $class->name : '';
            $subjectCode = $subject ? $subject->code : '';
            $periodCode = $period ?: '0';

            $autoCode = "{$className}-{$day}-{$validated['period_start']}-{$validated['period_end']}-{$subjectCode}-{$periodCode}-{$token}";
            $hashedCode = Crypt::encryptString($autoCode);
        } else {
            // Gunakan code lama tanpa encrypt ulang (avoid double encryption)
            $hashedCode = $jadwalLama->code;
        }

        $jadwalLama->update([
            'day_of_week' => strtolower($validated['day_of_week']),
            'period_start' => $validated['period_start'],
            'period_end' => $validated['period_end'],
            'start_time' => $validated['start_time'],
            'end_time' => $validated['end_time'],
            'code' => $hashedCode,
            'id_class' => $validated['id_class'],
            'id_subject' => $validated['id_subject'],
            'id_teacher' => $validated['id_teacher'],
            'id_academic_periods' => $validated['id_academic_periods'] ?? null,
        ]);

        return redirect()->route('jadwal.index')->with('success', 'Jadwal berhasil diupdate!');
    }

    public function destroy(Request $request)
    {
        $ids = $request->input('ids');
        if (!$ids) {
            return redirect()->route('jadwal.index')->with('error', 'Tidak ada jadwal yang dipilih untuk dihapus.');
        }
        // Ubah string menjadi array jika perlu
        if (is_string($ids)) {
            $ids = explode(',', $ids);
        }
        Schedule::destroy($ids);
        return redirect()->route('jadwal.index')->with('success', 'Jadwal berhasil dihapus!');
    }

    public function showQr($id)
    {
        $jadwal = Schedule::findOrFail($id);
        return view('pages.jadwal.qr', compact('jadwal'));
    }

    public function showPublicQr($token)
    {
        $tokenData = Cache::get("public_qr_link:$token");

        if (!$tokenData) {
            return view('public.attendance.qr-error', [
                'status' => 'expired',
                'message' => 'Link QR sudah expired atau tidak valid. Silakan minta link baru dari guru.'
            ]);
        }

        $idSchedule = $tokenData['schedule_id'];
        $expiresAt = $tokenData['expires_at'];

        $jadwal = Schedule::with(['class', 'subject', 'teacher'])->find($idSchedule);

        if (!$jadwal) {
            return view('public.attendance.qr-error', [
                'status' => 'notfound',
                'message' => 'Data jadwal tidak ditemukan.'
            ]);
        }

        $publicUrl = route('jadwal.qr.public', ['token' => $token]);

        return view('public.attendance.qr', compact('jadwal', 'publicUrl', 'expiresAt'));
    }

    public function generateQrLink($id)
    {
        $result = $this->qrLinkService->generateLink($id);
        return response()->json($result);
    }
}
