import { Request, Response } from "express";
import { createEvent, getEventAttendance, getEventDetails, getShortEventsInRange, setAttendanceStatus, setEventCancelled, updateEvent } from "../services/calendarService";
import { CalendarAttendance, CalendarEvent } from "@app/shared/types/calendar";
import { requireLogin, requireMemberState, requireRole } from "../middleware/auth";
import { MemberState } from "@app/shared/types/member";

const express = require('express');
const r = express.Router();

function addMonths(date: Date, months: number): Date {
    const d = new Date(date)
    d.setMonth(d.getMonth() + months)
    return d
}

//get calendar events paged, requires a query string with from= and to= as mariadb ISO strings
r.get('/', async (req, res) => {
    try {
        const fromDate: string = req.query.from;
        const toDate: string = req.query.to;

        if (fromDate === undefined || toDate === undefined) {
            res.status(400).send("Missing required query parameters 'from' and 'to'");
            return;
        }

        const events = await getShortEventsInRange(fromDate, toDate);

        res.status(200).json(events);
    } catch (error) {
        console.error('Error fetching calendar events:', error);
        res.status(500).send('Error fetching calendar events');
    }
});

r.get('/upcoming', async (req, res) => {
    res.sendStatus(501);
})

r.post('/:id/cancel', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => {
    try {
        const eventID = Number(req.params.id);
        setEventCancelled(eventID, true);
        res.sendStatus(200);
    } catch (error) {
        console.error('Error setting cancel status:', error);
        res.status(500).send('Error setting cancel status');
    }
})
r.post('/:id/uncancel', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => {
    try {
        const eventID = Number(req.params.id);
        setEventCancelled(eventID, false);
        res.sendStatus(200);
    } catch (error) {
        console.error('Error setting cancel status:', error);
        res.status(500).send('Error setting cancel status');
    }
})


r.post('/:id/attendance', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => {
    try {
        let member = req.user.id;
        let event = Number(req.params.id);
        let state = req.query.state as CalendarAttendance;
        setAttendanceStatus(member, event, state);
        res.sendStatus(200);
    } catch (error) {
        console.error('Failed to set attendance:', error);
        res.status(500).json(error);
    }
})
//get event details
r.get('/:id', async (req: Request, res: Response) => {
    try {
        const eventID: number = Number(req.params.id);

        let details: CalendarEvent = await getEventDetails(eventID);
        details.eventSignups = await getEventAttendance(eventID);
        res.status(200).json(details);
    } catch (err) {
        console.error('Insert failed:', err);
        res.status(500).json(err);
    }
})


//post a new calendar event 
r.post('/', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => {
    try {
        const member = req.user.id;
        let event: CalendarEvent = req.body;
        event.creator_id = member;
        event.start = new Date(event.start);
        event.end = new Date(event.end);
        createEvent(event);
        res.sendStatus(200);
    } catch (error) {
        console.error('Failed to create event:', error);
        res.status(500).json(error);
    }
})

r.put('/', [requireLogin, requireMemberState(MemberState.Member)], async (req: Request, res: Response) => {
    try {
        let event: CalendarEvent = req.body;
        event.start = new Date(event.start);
        event.end = new Date(event.end);
        updateEvent(event);
        res.sendStatus(200);
    } catch (error) {
        console.error('Failed to update event:', error);
        res.status(500).json(error);
    }
})

export const calendarRouter = r;
