require('dotenv').config();
const fetch = require('node-fetch');
const fs = require('fs');
const path = require('path');

const calendarUid = process.env.ZOHO_CALENDAR_UID;
let accessToken = process.env.ZOHO_ACCESS_TOKEN;
const refreshToken = process.env.ZOHO_REFRESH_TOKEN;
const clientId = process.env.ZOHO_CLIENT_ID;
const clientSecret = process.env.ZOHO_CLIENT_SECRET;

// Dates for current month
const currentDate = new Date();
const currentYear = currentDate.getFullYear();
const currentMonth = (currentDate.getMonth() + 1).toString().padStart(2, '0');
const lastDay = new Date(currentYear, currentDate.getMonth() + 1, 0).getDate();
const startDate = `${currentYear}${currentMonth}01`;
const endDate = `${currentYear}${currentMonth}${lastDay}`;

const zohoApiUrl = `https://calendar.zoho.com/api/v1/calendars/${calendarUid}`;

async function refreshAccessToken() {
    const params = new URLSearchParams();
    params.append('grant_type', 'refresh_token');
    params.append('client_id', clientId);
    params.append('client_secret', clientSecret);
    params.append('refresh_token', refreshToken);

    const response = await fetch('https://accounts.zoho.com/oauth/v2/token', {
        method: 'POST',
        body: params
    });

    const data = await response.json();
    if (!data.access_token) {
        throw new Error('Failed to refresh access token: ' + JSON.stringify(data));
    }

    const envPath = path.resolve(process.cwd(), '.env');
    const envContents = fs.readFileSync(envPath, 'utf-8')
        .split('\n')
        .map(line => line.startsWith('ZOHO_ACCESS_TOKEN=') ? `ZOHO_ACCESS_TOKEN=${data.access_token}` : line)
        .join('\n');
    fs.writeFileSync(envPath, envContents, 'utf-8');

    accessToken = data.access_token;
}

function parseZohoTimestamp(start, isAllDay) {
    if (isAllDay) {
        const year = parseInt(start.slice(0, 4));
        const month = parseInt(start.slice(4, 6)) - 1;
        const day = parseInt(start.slice(6, 8));
        return new Date(year, month, day);
    } else {
        const year = parseInt(start.slice(0, 4));
        const month = parseInt(start.slice(4, 6)) - 1;
        const day = parseInt(start.slice(6, 8));
        const hour = parseInt(start.slice(9, 11));
        const minute = parseInt(start.slice(11, 13));
        const second = parseInt(start.slice(13, 15));
        return new Date(year, month, day, hour, minute, second);
    }
}

function formatEventDate(startDate, endDate, isAllDay) {
    const start = parseZohoTimestamp(startDate, isAllDay);
    if (isAllDay) {
        return start.toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' });
    } else {
        const end = parseZohoTimestamp(endDate, isAllDay);
        const optionsDate = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
        const optionsTime = { hour: 'numeric', minute: '2-digit', hour12: true };
        const dateStr = start.toLocaleDateString('en-US', optionsDate);
        const startTimeStr = start.toLocaleTimeString('en-US', optionsTime);
        const endTimeStr = end.toLocaleTimeString('en-US', optionsTime);
        return `${dateStr} • ${startTimeStr} – ${endTimeStr}`;
    }
}

module.exports = async function() {
    try {
        const eventsListUrl = `${zohoApiUrl}/events?range={"start":"${startDate}","end":"${endDate}"}`;
        console.log(`Making initial API call to: ${eventsListUrl}`);
        console.log(`Using access token`);

        let response = await fetch(eventsListUrl, {
            headers: { Authorization: `Zoho-oauthtoken ${accessToken}` }
        });

        if (response.status === 401) {
            console.log("Access token is expired, refreshing...");
            await refreshAccessToken();
            response = await fetch(eventsListUrl, {
                headers: { Authorization: `Zoho-oauthtoken ${accessToken}` }
            });
        }

        if (!response.ok) {
            const text = await response.text();
            throw new Error(`API call failed: ${response.status} ${response.statusText} - ${text}`);
        }

        const data = await response.json();
        console.log("Initial API call successful. Received data:");
        console.dir(data, { depth: null });

        const normalizedEventsPromises = data.events.map(async (event) => {
            const basicEvent = {
                calid: event.calid,
                title: event.title,
                uid: event.uid,
                start: event.dateandtime.start,
                end: event.dateandtime.end,
                isallday: event.isallday,
                location: event.location,
                displayDate: formatEventDate(event.dateandtime.start, event.dateandtime.end, event.isallday),
                color: event.color,
            };

            // This logic is necessary to get the description from a second API call
            if (basicEvent.uid) {
                const eventDetailsUrl = `${zohoApiUrl}/events/${basicEvent.uid}`;
                console.log(`Making details API call to: ${eventDetailsUrl}`);

                const detailsResponse = await fetch(eventDetailsUrl, {
                    headers: { Authorization: `Zoho-oauthtoken ${accessToken}` }
                });

                if (detailsResponse.ok) {
                    const detailsData = await detailsResponse.json();
                    if (detailsData.events && detailsData.events.length > 0) {
                        basicEvent.description = detailsData.events[0].description;
                        console.log(`Description added for event UID: ${basicEvent.uid}`);
                    }
                } else {
                    console.warn(`Failed to fetch details for event UID: ${basicEvent.uid}`);
                }
            }

            // Assign category based on color
            switch (basicEvent.color) {
                case '#7CAA56':
                    basicEvent.category = 'sales';
                    break;
                case '#FC6060':
                    basicEvent.category = 'workshop';
                    break;
                case '#FFC464':
                    basicEvent.category = 'community';
                    break;
                default:
                    basicEvent.category = 'uncategorized';
            }

            return basicEvent;
        });

        const normalizedEvents = await Promise.all(normalizedEventsPromises);
        console.log("All events processed. Final normalized events array:", normalizedEvents);

        const filePath = path.resolve(__dirname, '..', '_data', 'eventsJson.js');
        const fileContents = `module.exports = { normalizedEvents: ${JSON.stringify(normalizedEvents, null, 2)} };`;
        fs.writeFileSync(filePath, fileContents, 'utf-8');
        console.log(`Data successfully written to ${filePath}`);

        return normalizedEvents;

    } catch (error) {
        console.error("Error fetching Zoho events:", error);
        return [];
    }
};