import 'dotenv/config';
import mongoose from 'mongoose';
import Appointment from '../models/Appointment';
import NotificationLog from '../models/NotificationLog';
import EmailService from '../services/EmailService';
import NotificationQueueService from '../services/NotificationQueueService';

const TEST_EMAIL = 'praveenjeeru2004@gmail.com';

async function runTest() {
    const mongoUri = process.env.MONGODB_URI;
    if (!mongoUri) {
        console.error('MONGODB_URI missing');
        process.exit(1);
    }

    await mongoose.connect(mongoUri);
    console.log('✓ Connected to MongoDB');

    const User = require('../models/User').default;
    const Patient = require('../models/Patient').default;
    const Doctor = require('../models/Doctor').default;

    // ═══════════════════════════════════════════
    // STEP 1: Test direct email sending first
    // ═══════════════════════════════════════════
    console.log('\n--- STEP 1: Testing direct email delivery ---');
    console.log(`Sending test email to ${TEST_EMAIL}...`);

    try {
        const emailResult = await EmailService.sendAppointmentReminder(
            TEST_EMAIL,
            'Praveen',
            new Date().toLocaleString(),
            'Dr. Test Doctor'
        );
        if (emailResult) {
            console.log('✓ Email sent successfully! Check your inbox.');
        } else {
            console.log('✗ Email sending returned false. Check your RESEND_API_KEY in .env');
        }
    } catch (err: any) {
        console.error('✗ Email sending failed:', err.message);
        console.log('Make sure RESEND_API_KEY is set in your .env file');
    }

    // ═══════════════════════════════════════════
    // STEP 2: Test the queue flow
    // ═══════════════════════════════════════════
    console.log('\n--- STEP 2: Testing queue-based notification flow ---');

    // Cleanup ALL previous test data thoroughly
    const oldUsers = await User.find({ email: { $in: [TEST_EMAIL, 'doctor-test-notif@test.com'] } });
    const oldUserIds = oldUsers.map((u: any) => u._id);
    if (oldUserIds.length > 0) {
        await Patient.deleteMany({ userId: { $in: oldUserIds } });
        await Doctor.deleteMany({ userId: { $in: oldUserIds } });
        await User.deleteMany({ _id: { $in: oldUserIds } });
        console.log('  Cleaned up previous test data');
    }

    // Create test User + Patient
    const user = await User.create({
        firstName: 'Praveen',
        lastName: 'Jeeru',
        email: TEST_EMAIL,
        password: 'password123',
        userType: 'patient'
    });
    console.log(`✓ Test patient user created: ${user._id}`);

    const docUser = await User.create({
        firstName: 'Dr. Test',
        lastName: 'Doctor',
        email: 'doctor-test-notif@test.com',
        password: 'password123',
        userType: 'doctor'
    });
    console.log(`✓ Test doctor user created: ${docUser._id}`);

    const patient = await Patient.create({
        userId: user._id,
        dateOfBirth: new Date('1990-01-01'),
        gender: 'Male',
        address: 'Test Address'
    });

    const doctor = await Doctor.create({
        userId: docUser._id,
        isDentist: false,
        licenseNumber: `TEST-${Date.now()}`
    });

    // Create appointment 15 seconds in the future
    const triggerTime = new Date(Date.now() + 15 * 1000);

    const appointment = await Appointment.create({
        patientId: patient._id,
        doctorId: doctor._id,
        appointmentDate: triggerTime,
        durationMinutes: 30,
        status: 'Scheduled',
        confirmationStatus: 'Confirmed',
        reasonForVisit: 'Test Notification System',
    });
    console.log(`✓ Appointment created: ${appointment._id}`);
    console.log(`  Scheduled for: ${triggerTime.toLocaleString()}`);

    // Schedule reminders via queue
    await NotificationQueueService.scheduleAppointmentReminders(appointment);
    console.log('✓ Reminders scheduled in queue');
    console.log('  Waiting for worker to process (up to 60 seconds)...');
    console.log('  IMPORTANT: Make sure the worker is running in another terminal: npm run worker\n');

    // Poll for notification logs - longer timeout, don't delete appointment
    let attempts = 0;
    const maxAttempts = 20; // 20 × 3s = 60 seconds

    const interval = setInterval(async () => {
        attempts++;
        const logs = await NotificationLog.find({ appointmentId: appointment._id });

        if (logs.length > 0) {
            console.log('\n✅ SUCCESS! Notification logs found:');
            logs.forEach(log => {
                console.log(`  - [${log.status}] ${log.purpose} | Job: ${log.jobId} | ${log.createdAt}`);
            });
            clearInterval(interval);

            // Cleanup
            console.log('\nCleaning up test data...');
            await Appointment.findByIdAndDelete(appointment._id);
            await NotificationLog.deleteMany({ appointmentId: appointment._id });
            await Patient.findByIdAndDelete(patient._id);
            await Doctor.findByIdAndDelete(doctor._id);
            await User.deleteMany({ email: { $in: [TEST_EMAIL, 'doctor-test-notif@test.com'] } });
            console.log('✓ Cleanup complete');
            process.exit(0);
        } else {
            process.stdout.write(`  Polling attempt ${attempts}/${maxAttempts}...\r`);
        }

        if (attempts >= maxAttempts) {
            console.log('\n\n✗ Timed out waiting for notification logs.');
            console.log('  Possible causes:');
            console.log('  1. Worker is not running → run "npm run worker" in another terminal');
            console.log('  2. Worker is running with OLD code → restart it (Ctrl+C then npm run worker)');
            console.log('  3. Redis connection issue → check Redis is running');
            clearInterval(interval);

            // Don't cleanup appointment so worker can still pick it up
            console.log(`\n  Appointment ${appointment._id} was NOT deleted so the worker can still process it.`);
            process.exit(1);
        }
    }, 3000);
}

runTest().catch(err => {
    console.error('Test failed:', err);
    process.exit(1);
});
