import "dotenv/config";
import { createClient } from "@supabase/supabase-js";
import * as fs from "fs";
import * as path from "path";

const supabase = createClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    "sb_secret_N7UND0UgjKTVK-Uodkm0Hg_xSvEMPvz",
    { auth: { persistSession: false } }
);

const SUBJECTS: Record<string, number> = {
    Math: 1,
    Science: 2,
    English: 3,
    History: 4,
    Art: 5,
    Music: 6,
    PE: 7,
    Computer: 8,
    Geography: 9,
    Biology: 10
};

// -------------------------------------------------------------
// CONFIGURATION: Adjust the timeline spread and generation odds
// -------------------------------------------------------------
const CONFIG = {
    monthsPast: 3,                 // How many months backward to generate lessons
    monthsFuture: 9,               // How many months forward to generate lessons
    baseDate: new Date("2026-02-23T00:00:00.000Z"), // "Present" date
    examProbability: 0.05,         // 5% chance of an Exam per lesson
    assignmentProbability: 0.1,    // 10% chance of an Assignment per lesson
    attendanceProbability: 0.95,   // 95% attendance rate for past lessons
};

// Helper to chunk large arrays for Supabase batch inserts
function chunkArray<T>(array: T[], size: number): T[][] {
    const chunks = [];
    for (let i = 0; i < array.length; i += size) {
        chunks.push(array.slice(i, i + size));
    }
    return chunks;
}

async function insertInChunks(table: string, data: any[]) {
    if (data.length === 0) return;
    console.log(`Inserting ${data.length} records into ${table}...`);
    const chunks = chunkArray(data, 1000);
    for (let i = 0; i < chunks.length; i++) {
        const chunk = chunks[i];
        const { error } = await supabase.from(table).insert(chunk);
        if (error) {
            console.error(`Error inserting into ${table} (chunk ${i}):`, error);
        }
    }
}

async function main() {
    try {
        console.log("Loading user IDs from seed-data.json...");
        const seedDataPath = path.join(process.cwd(), "scripts", "seed-data.json");
        if (!fs.existsSync(seedDataPath)) {
            throw new Error("seed-data.json not found! Please run `npm run seed:users` first.");
        }
        const data = JSON.parse(fs.readFileSync(seedDataPath, "utf-8"));
        const { teacherMap, studentMap, classes, defaultSchoolId } = data;

        console.log("Cleaning old Schedule & Attendance data...");
        const tablesToClean = ["LessonWhiteboard", "Attendance", "Result", "Assignment", "Exam", "Lesson"];
        for (const table of tablesToClean) {
            await supabase.from(table).delete().neq("id", "0" as any);
        }

        console.log(`Building full year timetable...`);
        console.log(`- Past months: ${CONFIG.monthsPast}`);
        console.log(`- Future months: ${CONFIG.monthsFuture}`);

        const days = ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY"];
        const periods = [8, 9, 10, 11, 13, 14]; // Expanded periods (8 AM - 2 PM, skipping 12 PM lunch)

        let lessonIdCounter = 1;
        let examIdCounter = 1;
        let assignmentIdCounter = 1;
        let resultIdCounter = 1;
        let attendanceIdCounter = 1;

        const lessonsData = [];
        const whiteboardsData = [];
        const examsData = [];
        const assignmentsData = [];
        const resultsData = [];
        const attendancesData = [];

        // Compute start of generation (aligned to a Monday)
        const startDate = new Date(CONFIG.baseDate);
        startDate.setMonth(startDate.getMonth() - CONFIG.monthsPast);
        const startDayOfWeek = startDate.getDay();
        const daysToMonday = startDayOfWeek === 0 ? -6 : 1 - startDayOfWeek;
        startDate.setDate(startDate.getDate() + daysToMonday);

        // Compute end of generation
        const endDate = new Date(CONFIG.baseDate);
        endDate.setMonth(endDate.getMonth() + CONFIG.monthsFuture);

        let currentWeekStart = new Date(startDate);

        while (currentWeekStart < endDate) {
            for (let classIndex = 0; classIndex < classes.length; classIndex++) {
                const classInfo = classes[classIndex];

                // Gather students belonging to this class based on seed logic
                const studentList: string[] = [];
                for (let i = 1; i <= 50; i++) {
                    const studentBase = classIndex === 0 ? 6 : classIndex;
                    const studentIdx = studentBase + 6 * (i % 8);
                    if (studentMap[studentIdx] && !studentList.includes(studentMap[studentIdx])) {
                        studentList.push(studentMap[studentIdx]);
                    }
                }

                for (let dayOffset = 0; dayOffset < days.length; dayOffset++) {
                    const dayName = days[dayOffset];
                    const currentDate = new Date(currentWeekStart);
                    currentDate.setDate(currentDate.getDate() + dayOffset);

                    for (let period = 0; period < periods.length; period++) {
                        const startHour = periods[period];

                        const subjectIdx = (classIndex + dayOffset + period) % 10;
                        const subjectKey = Object.keys(SUBJECTS)[subjectIdx];
                        const subjectId = SUBJECTS[subjectKey];
                        const teacherId = teacherMap[subjectId]; // Authorized teacher

                        const startTime = new Date(currentDate);
                        startTime.setUTCHours(startHour, 0, 0, 0);

                        const endTime = new Date(currentDate);
                        endTime.setUTCHours(startHour + 1, 0, 0, 0);

                        // 1. Insert Lesson
                        lessonsData.push({
                            id: lessonIdCounter,
                            name: `${classInfo.name} ${subjectKey} (${dayName})`,
                            startTime: startTime.toISOString(),
                            endTime: endTime.toISOString(),
                            subjectId: subjectId,
                            classId: classInfo.id,
                            teacherId: teacherId,
                            schoolId: defaultSchoolId
                        });

                        whiteboardsData.push({
                            lessonId: lessonIdCounter
                        });

                        // 2. Insert Exam / Results (Random Probability)
                        if (Math.random() < CONFIG.examProbability) {
                            examsData.push({
                                id: examIdCounter,
                                title: `${subjectKey} Assessment`,
                                startTime: startTime.toISOString(),
                                endTime: endTime.toISOString(),
                                lessonId: lessonIdCounter,
                                schoolId: defaultSchoolId
                            });

                            // Only give results to a subset to prevent table explosions
                            for (const sId of studentList.slice(0, 4)) {
                                resultsData.push({
                                    id: resultIdCounter++,
                                    score: 60 + Math.floor(Math.random() * 41), // 60-100
                                    studentId: sId,
                                    examId: examIdCounter,
                                    schoolId: defaultSchoolId
                                });
                            }
                            examIdCounter++;
                        }

                        // 3. Insert Assignment
                        if (Math.random() < CONFIG.assignmentProbability) {
                            assignmentsData.push({
                                id: assignmentIdCounter++,
                                title: `${subjectKey} Practice`,
                                startDate: startTime.toISOString(),
                                dueDate: new Date(startTime.getTime() + 7 * 24 * 60 * 60 * 1000).toISOString(),
                                lessonId: lessonIdCounter,
                                schoolId: defaultSchoolId
                            });
                        }

                        // 4. Insert Attendance (ONLY for dates occurring in the past)
                        if (startTime < CONFIG.baseDate) {
                            for (const sId of studentList) {
                                attendancesData.push({
                                    id: attendanceIdCounter++,
                                    date: startTime.toISOString(),
                                    present: Math.random() < CONFIG.attendanceProbability,
                                    studentId: sId,
                                    lessonId: lessonIdCounter,
                                    schoolId: defaultSchoolId
                                });
                            }
                        }

                        lessonIdCounter++;
                    }
                }
            }

            // Advance to the next week safely
            currentWeekStart.setDate(currentWeekStart.getDate() + 7);
        }

        // Send payload in bulk batches to Supabase to prevent network/memory bottlenecks
        await insertInChunks("Lesson", lessonsData);
        await insertInChunks("LessonWhiteboard", whiteboardsData);
        await insertInChunks("Exam", examsData);
        await insertInChunks("Assignment", assignmentsData);
        await insertInChunks("Result", resultsData);
        await insertInChunks("Attendance", attendancesData);

        // Keep Lesson id sequence in sync so "Generate lessons" from templates does not hit duplicate key
        const { error: syncErr } = await supabase.rpc("sync_lesson_id_sequence");
        if (syncErr) {
            console.warn("Lesson sequence sync skipped (run migrations if you use Generate lessons):", syncErr.message);
        }

        console.log(`\n✅ Timeline successfully generated!`);
        console.log(`- Lessons: ${lessonsData.length}`);
        console.log(`- Whiteboards: ${whiteboardsData.length}`);
        console.log(`- Exams: ${examsData.length}`);
        console.log(`- Assignments: ${assignmentsData.length}`);
        console.log(`- Results: ${resultsData.length}`);
        console.log(`- Attendance Records: ${attendancesData.length}`);

    } catch (err) {
        console.error("Schedule Seeding Failed:", err);
    }
}

main();
