// pages/api/shifts.ts

import axiosServer from '../../src/axiosServer';
import { getToken } from "next-auth/jwt";

import type { NextApiRequest, NextApiResponse } from "next";
import { Prisma, PrismaClient, DayOfWeek, Publisher, Shift } from "@prisma/client";
import { levenshteinEditDistance } from "levenshtein-edit-distance";
import { filterPublishers, /* other functions */ } from './index';

import CAL from "../../src/helpers/calendar";
//const common = require("@common");
import common from "../../src/helpers/common";
import { Axios } from 'axios';
const path = require("path");
const fs = require("fs");

const generateTemplateFile = async (data, templateSrc) => {
    const handlebars = require("handlebars");
    const htmlDocx = require("html-docx-js");

    // Compile the Handlebars template
    const template = handlebars.compile(templateSrc);

    // Generate the HTML output using the template and the events data
    const html = template(data);
    return html;
}

function splitNotes(notes) {
    if (!notes) {
        return { notes: '', notes_bold: '' };
    }

    // Combine both dash types into a single pattern for the regex
    const dashPattern = /[-–]/g;

    // Find all occurrences of either dash
    let allDashes = [...notes.matchAll(dashPattern)];

    if (allDashes.length === 0) {
        // No dash found, return the original notes in both parts
        return { notes: notes, notes_bold: '' };
    }

    // Get the index of the first and last dash
    const firstDashIndex = allDashes[0].index;
    const lastDashIndex = allDashes[allDashes.length - 1].index;

    // Extract parts before the first dash and after the last dash
    const notesBeforeFirstDash = notes.substring(0, firstDashIndex + 1);
    const notesAfterLastDash = notes.substring(lastDashIndex + 1);

    return {
        notes: notesBeforeFirstDash,
        notes_bold: notesAfterLastDash
    };
}

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
    console.log(req.url);
    console.log(req.query);
    const prisma = common.getPrismaClient();

    // If you don't have the NEXTAUTH_SECRET environment variable set,
    // you will have to pass your secret as `secret` to `getToken`
    const axios = await axiosServer({ req: req, res: res });
    const token = await getToken({ req: req });
    if (!token) {
        // If no token or invalid token, return unauthorized status
        return res.status(401).json({ message: "Unauthorized" });
    }


    if (req.method === 'GET') {
        const { year, month } = req.query;

        //ToDo: maybe we don't need that anymore as we are publishing the shifts and show all published shifts
        let fromDate = new Date();
        fromDate.setDate(fromDate.getDate() - 1);
        fromDate.setHours(0, 0, 0, 0);
        if (year && month) {
            fromDate = new Date(parseInt(year as string), parseInt(month as string) - 1, 1);
        }
        const monthInfo = common.getMonthDatesInfo(fromDate);
        //let toDate = new Date(monthInfo.lastSunday);
        if (year && month) {
            fromDate = monthInfo.firstMonday;
        }

        try {

            const shifts = await prisma.shift.findMany({
                where: {
                    isActive: true,
                    isPublished: true,
                    // OR: [
                    //     { isPublished: true },
                    //     { user: { role: 'admin' } } // Todo: example. fix this
                    // ],
                    startTime: {
                        gte: fromDate,
                        //lt: toDate,
                    },
                },
                orderBy: {
                    startTime: 'asc',
                },
                include: {
                    assignments: {
                        where: {},
                        include: {
                            publisher: true,
                        },
                    },
                    cartEvent: {
                        include: {
                            location: true,
                        },
                    },
                },
            });

            let json = JSON.stringify(shifts);
            const groupedShifts = {};
            const startDate = new Date(shifts[0].startTime);
            let i = 0;
            try {
                for (const shift of shifts) {
                    i++;
                    const date = new Date(shift.startTime);
                    const day = common.getISODateOnly(date)
                    const time = common.getTimeRange(shift.startTime, shift.endTime); //common.getLocalTime(date);
                    if (!groupedShifts[day]) {
                        groupedShifts[day] = {};
                    }
                    if (!groupedShifts[day][time]) {
                        groupedShifts[day][time] = [];
                    }

                    // let { notes, notes_bold } =  splitNotes(shift.notes);//.substring(Math.max(shift.notes.lastIndexOf("-"), shift.notes.lastIndexOf("–")) + 1).trim() || "";
                    let notes = "", notes_bold = "";

                    if (shift.assignments.some(a => a.isWithTransport)) {
                        if (shift.requiresTransport) {
                            notes = "Транспорт: ";
                            notes_bold = " " + shift.assignments.filter(a => a.isWithTransport).map(a => common.getInitials(a.publisher.firstName + " " + a.publisher.lastName)).join(", ");
                        }
                    }

                    let shiftSchedule = {
                        date: date,
                        placeOfEvent: shift.cartEvent.location.name,
                        time: time,
                        requiresTransport: shift.requiresTransport,
                        //bold the text after - in the notes
                        notes: notes,
                        notes_bold: notes_bold,
                        names: shift.assignments.length > 0
                            ? shift.assignments
                                .map((assignment) => {
                                    return (
                                        assignment.publisher.firstName +
                                        " " +
                                        assignment.publisher.lastName
                                    );
                                })
                                .join(", ")
                            : shift.name,
                    };

                    if (shiftSchedule.names.length > 0) {
                        groupedShifts[day][time].push(shiftSchedule);
                    }
                }
            } catch (err) {
                console.log(err + " " + JSON.stringify(shifts[i]));
            }

            for (const day in groupedShifts) {
                const times = Object.keys(groupedShifts[day]);
                for (const time of times) {
                    const shift = groupedShifts[day][time][0];
                    if (shift) {
                        // Determine the first shift of the day if it requires transport
                        if (time === times[0] && shift.requiresTransport) { // Check if this is the first time slot of the day
                            shift.notes = "Докарва количка от Люлин -"; // Update the first shift in the first time slot
                        }

                        // Determine the last shift of the day if it requires transport
                        if (time === times[times.length - 1] && shift.requiresTransport) { // Check if this is the last time slot of the day
                            shift.notes = "Прибира количка в Люлин -"; // Update the last shift in the last time slot
                        }
                    }
                }
            }

            // Create the output object in the format of the second JSON file
            const monthlySchedule = {
                month: common.getMonthName(shifts[0].startTime.getMonth()),
                year: startDate.getFullYear(),
                events: [],
            };

            for (const day in groupedShifts) {
                var dayEvent = null;

                for (const time in groupedShifts[day]) {
                    if (dayEvent == null) {
                        const shift = groupedShifts[day][time][0];
                        if (!shift) {
                            console.log("shift is null");
                            continue;
                        }

                        let weekday = common.getDayOfWeekName(shift.date);
                        let monthName = common.getMonthName(shift.date.getMonth());
                        weekday = weekday.charAt(0).toUpperCase() + weekday.slice(1);
                        let weekNr = common.getWeekNumber(shift.date);
                        console.log("weekday = " + weekday, " weekNr = " + weekNr);
                        dayEvent = {
                            week: weekNr,
                            dayOfWeek: weekday,
                            dayOfMonth: shift.date.getDate(),
                            placeOfEvent: shift.placeOfEvent,
                            shifts: [],
                            transport: shift.notes,
                            monthName: monthName,
                        };
                    }

                    dayEvent.shifts.push(...groupedShifts[day][time]);
                }
                if (dayEvent) {
                    monthlySchedule.events.push(dayEvent);
                }
            }

            const outputPath = path.join(process.cwd(), 'public', 'content', 'output');
            if (!fs.existsSync(outputPath)) {
                fs.mkdirSync(outputPath, { recursive: true });
            }

            //fs.writeFileSync(path.join(outputPath, `shifts ${year}.${month}.json`), JSON.stringify(monthlySchedule), 'utf8');
            // Load the Handlebars template from a file
            const template = fs.readFileSync("./src/templates/schedule.hbs", "utf8");
            generateTemplateFile(monthlySchedule, template).then((result) => {
                const filename = path.join(outputPath, `schedule.html`)
                //fs.writeFileSync(filename, result, "utf8");
                res.end(result);
            }
            );
        }
        catch (error) {
            console.log(error);
            res.status(500).json({ error: "Internal Server Error" });
        }
    } else {
        res.setHeader('Allow', ['GET']);
        res.status(405).end(`Method ${req.method} Not Allowed`);
    }
}