import { NextRequest, NextResponse } from 'next/server';
import webPush from 'web-push';
import { getUsersForRemindersD1, updateLastNotifiedD1, deletePushSubscriptionD1 } from '@/lib/d1';

// Configure web-push - Helper called inside handler to ensure env is ready
function ensureVapidConfig() {
    console.log('--- VAPID Debug ---');
    console.log('VAPID_PUBLIC:', process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY ? `Present (Starts with: ${process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY.substring(0, 5)}...)` : 'MISSING');
    console.log('VAPID_PRIVATE:', process.env.VAPID_PRIVATE_KEY ? 'Present' : 'MISSING');
    console.log('VAPID_SUBJECT:', process.env.VAPID_SUBJECT || 'MISSING (Defaulting to mailto:admin@quittraq.com)');
    console.log('Available Env Keys:', Object.keys(process.env).filter(k => k.includes('VAPID') || k.includes('KEY')));
    console.log('-------------------');

    if (process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY && process.env.VAPID_PRIVATE_KEY) {
        webPush.setVapidDetails(
            process.env.VAPID_SUBJECT || 'mailto:example@yourdomain.org',
            process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY,
            process.env.VAPID_PRIVATE_KEY
        );
        return true;
    }
    return false;
}

const MESSAGES = {
    morning: [
        "Rise and shine! Today is a perfect day to stay on track.",
        "New morning, new strength. Let's keep that streak alive!",
        "Success starts with your first choice today. You've got this!",
        "Your morning check-in starts now. Every smoke-free minute counts!",
        "The morning is yours. Claim it by logging your progress.",
        "Small steps lead to big changes. Start your day by logging in!"
    ],
    afternoon: [
        "Keep the momentum going! You're doing great this afternoon.",
        "Halfway through the day and looking strong. Log your progress!",
        "The afternoon slump is no match for your willpower. Stay focused!",
        "Just checking in—how's your journey going? Log it now!",
        "You're stronger than any craving. Keep pushing forward!",
        "Consistency is key to mastery. You’re doing amazing today!"
    ],
    evening: [
        "Wind down with a win. Another day closer to your goal!",
        "Evening reflection: You faced the day and won. Log your success!",
        "Don't let the evening cravings win. You're almost there!",
        "Sweet dreams are made of smoke-free days. Keep it up!",
        "The night is calm, and so are you. Finish the day strong!",
        "Final check-in for the day! Log your progress and sleep proud.",
        "Progress isn't always linear, but you're showing up. Great job!",
        "You survived another day. Celebrate with a quick log!"
    ]
};

function getNotificationData(timeStr: string) {
    // timeStr is HH:MM
    const [h, m] = timeStr.split(':').map(Number);
    const totalMinutes = h * 60 + m;

    let category: 'morning' | 'afternoon' | 'evening';

    // Morning: 5:30 (330m) - 11:00 (660m)
    // Afternoon: 11:00 (660m) - 16:30 (990m)
    // Evening: 16:30 (990m) - 5:30 (330m)

    if (totalMinutes >= 330 && totalMinutes < 660) {
        category = 'morning';
    } else if (totalMinutes >= 660 && totalMinutes < 990) {
        category = 'afternoon';
    } else {
        category = 'evening';
    }

    const options = MESSAGES[category];
    const message = options[Math.floor(Math.random() * options.length)];

    const titles = [
        "QuitTraq Motivation",
        "QuitTraq Milestone",
        "QuitTraq Strength",
        "QuitTraq Journey",
        "QuitTraq Check-in"
    ];
    const title = titles[Math.floor(Math.random() * titles.length)];

    return { title, message };
}

export async function GET(request: NextRequest) {
    try {
        const isVapidReady = ensureVapidConfig();
        if (!isVapidReady) {
            console.error('VAPID Configuration missing! Keys:', {
                public: !!process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY,
                private: !!process.env.VAPID_PRIVATE_KEY
            });
            // We don't return early here so we can see which users fail below,
            // but generateRequestDetails will likely throw.
        }

        // Protect with a secret if configured
        const authHeader = request.headers.get('authorization');
        if (process.env.CRON_SECRET && authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
            return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
        }

        const users = await getUsersForRemindersD1();
        console.log(`Cron Ping: Processing ${users.length} users...`);
        const now = new Date();
        const processed = [];

        for (const user of users) {
            if (!user.endpoint || !user.p256dh || !user.auth) continue;

            try {
                // Determine User's Local Time
                const userTimezone = user.timezone || 'UTC';
                const userDateString = now.toLocaleDateString('en-CA', { timeZone: userTimezone }); // YYYY-MM-DD
                const userTimeString = now.toLocaleTimeString('en-GB', { timeZone: userTimezone, hour: '2-digit', minute: '2-digit' }); // HH:MM

                console.log(`Checking user ${user.userId}: Time ${userTimeString} (${userTimezone}) - Freq: ${user.frequency}`);

                let shouldSend = false;
                let notificationBody = '';
                let notificationTitle = '';
                let tag = '';

                if (user.frequency === 'hourly') {
                    const [currentH, currentM] = userTimeString.split(':');
                    const [startH, startM] = (user.hourlyStart || '09:00').split(':');
                    const currentHourKey = `${userDateString}-${currentH}`; // YYYY-MM-DD-HH

                    // Check active hours
                    const startStr = user.hourlyStart || '09:00';
                    const endStr = user.hourlyEnd || '21:00';

                    // Only send if we are in the time window AND the current minute matches the start minute
                    if (userTimeString >= startStr && userTimeString <= endStr && currentM === startM) {
                        if (user.lastNotifiedDate !== currentHourKey) {
                            shouldSend = true;
                            const { title: t, message } = getNotificationData(userTimeString);
                            notificationBody = message;
                            notificationTitle = t;
                            tag = 'hourly-reminder';

                            // Update to match current Hour Key so we don't send again this hour
                            await updateLastNotifiedD1(user.userId, currentHourKey);
                        }
                    }

                } else {
                    // Daily
                    // Check if current user time matches reminder time
                    // We allow a small window (e.g. within the same minute). Cron runs every minute.
                    // But we also check lastNotifiedDate to ensure we only send ONCE per day.

                    if (userTimeString === user.reminderTime) {
                        if (user.lastNotifiedDate !== userDateString) {
                            shouldSend = true;
                            const { title: t, message } = getNotificationData(userTimeString);
                            notificationBody = message;
                            notificationTitle = t;
                            tag = 'daily-reminder';

                            await updateLastNotifiedD1(user.userId, userDateString);
                        }
                    }
                }

                if (shouldSend) {
                    const payload = JSON.stringify({
                        title: notificationTitle,
                        body: notificationBody,
                        tag: tag,
                        url: '/'
                    });

                    // Use generateRequestDetails + fetch to avoid https dependency
                    const requestDetails = await webPush.generateRequestDetails(
                        {
                            endpoint: user.endpoint,
                            keys: { p256dh: user.p256dh, auth: user.auth }
                        },
                        payload,
                        {
                            vapidDetails: {
                                subject: (process.env.VAPID_SUBJECT || 'mailto:admin@quittraq.com').trim(),
                                publicKey: process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY!.trim(),
                                privateKey: process.env.VAPID_PRIVATE_KEY!.trim()
                            }
                        }
                    );

                    const response = await fetch(requestDetails.endpoint, {
                        method: 'POST',
                        headers: requestDetails.headers as Record<string, string>,
                        // @ts-expect-error - WebPush returns a Buffer which fetch in Workers supports but TS definitions might not match
                        body: requestDetails.body
                    });

                    if (!response.ok) {
                        const text = await response.text();
                        throw new Error(`Upstream error: ${response.status} ${text}`);
                    }

                    processed.push({ userId: user.userId, status: 'sent', tag });
                }

            } catch (err) {
                console.error(`Failed to process user ${user.userId}:`, err);

                // Check for 410 Gone - subscription expired, delete from DB
                const errorStr = String(err);
                if (errorStr.includes('410') || errorStr.includes('Gone') || errorStr.includes('expired')) {
                    console.log(`Subscription expired for user ${user.userId}, cleaning up...`);
                    try {
                        await deletePushSubscriptionD1(user.userId);
                        processed.push({ userId: user.userId, status: 'expired_cleaned', error: 'Subscription expired and removed' });
                    } catch (deleteErr) {
                        console.error(`Failed to delete expired subscription for ${user.userId}:`, deleteErr);
                        processed.push({ userId: user.userId, status: 'error', error: String(err) });
                    }
                } else {
                    processed.push({ userId: user.userId, status: 'error', error: String(err) });
                }
            }
        }

        return NextResponse.json({
            success: true,
            vapid: {
                ready: isVapidReady,
                public_present: !!process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY,
                private_present: !!process.env.VAPID_PRIVATE_KEY,
                env_keys: Object.keys(process.env).filter(k => k.includes('VAPID'))
            },
            processed
        });
    } catch (error) {
        console.error('Cron error:', error);
        return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
    }
}
