import dotenv from 'dotenv';
import mongoose from 'mongoose';
import path from 'path';
import Appointment from '../models/Appointment';
import Doctor from '../models/Doctor';
import Patient from '../models/Patient';
import User from '../models/User';

dotenv.config({ path: path.resolve(__dirname, '../../.env') });

const TARGET_MIN_APPOINTMENTS = 100;

const TARGETS: Array<{ label: string; emails: string[] }> = [
  {
    label: 'doctor',
    emails: ['tejasimma033+doctor@gmail.com'],
  },
  {
    label: 'dentist',
    emails: ['tejasimma033+dentist@gmail.com', 'tejasimma033+dentist@gmail.come'],
  },
];

const NOTES = [
  'Follow-up consultation',
  'Routine checkup',
  'Pain assessment',
  'Treatment review',
  'Initial consultation',
];

const STATUSES: Array<'Scheduled' | 'Completed' | 'Cancelled'> = [
  'Scheduled',
  'Completed',
  'Cancelled',
];

function pick<T>(arr: T[]): T {
  return arr[Math.floor(Math.random() * arr.length)];
}

function randomAppointmentDate(index: number): Date {
  // Spread appointments around current date: past, near-future, and future.
  const now = Date.now();
  const dayMs = 24 * 60 * 60 * 1000;
  const offsetDays = (index % 120) - 60; // -60 to +59
  const hourOffset = Math.floor(Math.random() * 9) + 8; // 8 AM - 4 PM
  return new Date(now + offsetDays * dayMs + hourOffset * 60 * 60 * 1000);
}

function statusForDate(date: Date): 'Scheduled' | 'Completed' | 'Cancelled' {
  if (date.getTime() > Date.now()) return 'Scheduled';
  return Math.random() < 0.15 ? 'Cancelled' : 'Completed';
}

async function getDoctorByEmails(emails: string[]) {
  const normalized = emails.map((email) => email.toLowerCase());
  const user = await User.findOne({ email: { $in: normalized } });
  if (!user) return null;
  const doctor = await Doctor.findOne({ userId: user._id });
  if (!doctor) return null;
  return { user, doctor };
}

async function run() {
  const mongoUri = process.env.MONGODB_URI;
  if (!mongoUri) throw new Error('MONGODB_URI is not set');

  await mongoose.connect(mongoUri);

  for (const target of TARGETS) {
    const found = await getDoctorByEmails(target.emails);
    if (!found) {
      console.log(`[SKIP] ${target.label}: no matching doctor found for emails ${target.emails.join(', ')}`);
      continue;
    }

    const { user, doctor } = found;
    const patients = await Patient.find({ doctorId: doctor._id }).select('_id').lean();
    if (!patients.length) {
      console.log(`[SKIP] ${target.label}: ${user.email} has no patients`);
      continue;
    }

    const existing = await Appointment.countDocuments({ doctorId: doctor._id });
    const needed = Math.max(0, TARGET_MIN_APPOINTMENTS - existing);

    console.log(`[INFO] ${target.label}: ${user.email} -> existing appointments ${existing}, creating ${needed}`);

    if (needed > 0) {
      const docs = Array.from({ length: needed }, (_, i) => {
        const patient = patients[i % patients.length];
        const appointmentDate = randomAppointmentDate(i + 1);
        const status = statusForDate(appointmentDate);
        return {
          patientId: patient._id,
          doctorId: doctor._id,
          appointmentDate,
          durationMinutes: 30,
          status,
          confirmationStatus: status === 'Scheduled' ? 'Pending' : 'Confirmed',
          notes: pick(NOTES),
          remindersSent: {
            email: false,
            sms: false,
            whatsapp: false,
          },
          scheduledJobIds: [],
          notificationVersion: 1,
        };
      });

      await Appointment.insertMany(docs, { ordered: false });
    }

    const after = await Appointment.countDocuments({ doctorId: doctor._id });
    console.log(`[DONE] ${target.label}: ${user.email} -> total appointments ${after}`);
  }
}

run()
  .catch((error) => {
    console.error('[ERROR]', error);
    process.exitCode = 1;
  })
  .finally(async () => {
    await mongoose.disconnect();
  });
