import Customer from '../Features/customers/schema/customer.schema';

type CustomerInput = {
  fullName: string;
  email?: string;
  phone: string;
  notes?: string;
};

export async function upsertCustomer({ fullName, email, phone, notes }: CustomerInput) {
  const normalizedEmail = String(email || '').trim().toLowerCase();
  const normalizedPhone = String(phone || '').trim();

  if (!normalizedPhone) {
    throw new Error('Phone is required for customer');
  }

  const lookup: Array<Record<string, string>> = [{ phone: normalizedPhone }];
  if (normalizedEmail) {
    lookup.push({ email: normalizedEmail });
  }

  let customer = await Customer.findOne({ $or: lookup });

  if (!customer) {
    customer = await Customer.create({
      fullName: String(fullName || '').trim(),
      email: normalizedEmail,
      phone: normalizedPhone,
      notes: notes || '',
    });
    return customer;
  }

  customer.fullName = String(fullName || customer.fullName).trim();
  customer.phone = normalizedPhone;
  customer.email = normalizedEmail || customer.email || '';
  if (notes !== undefined) customer.notes = notes;
  await customer.save();
  return customer;
}

export async function resolveAppointmentCustomer(input: {
  customerId?: string | null;
  fullName?: string;
  phone?: string;
  email?: string;
  notes?: string;
}) {
  if (input.customerId) {
    const linked = await Customer.findById(input.customerId);
    if (!linked) {
      throw new Error('Customer not found');
    }

    return upsertCustomer({
      fullName: input.fullName || linked.fullName,
      phone: input.phone || linked.phone,
      email: input.email !== undefined ? input.email : linked.email || '',
      notes: input.notes,
    });
  }

  if (!input.fullName || !input.phone) {
    throw new Error('Customer name and phone are required');
  }

  return upsertCustomer({
    fullName: input.fullName,
    phone: input.phone,
    email: input.email || '',
    notes: input.notes,
  });
}

export async function backfillCustomersFromAppointments() {
  const Appointments = (await import('../Features/appointments/schema/appointments.schema')).default;

  const groups = await Appointments.aggregate([
    {
      $match: {
        $or: [{ customerId: null }, { customerId: { $exists: false } }, { customerId: '' }],
      },
    },
    {
      $group: {
        _id: '$phone',
        fullName: { $first: '$fullName' },
        email: { $first: '$email' },
        phone: { $first: '$phone' },
      },
    },
  ]);

  let upserted = 0;
  for (const group of groups) {
    if (!group.phone) continue;
    const customer = await upsertCustomer({
      fullName: group.fullName,
      email: group.email || '',
      phone: group.phone,
    });
    await Appointments.updateMany(
      {
        $and: [
          { $or: [{ customerId: null }, { customerId: { $exists: false } }, { customerId: '' }] },
          { phone: group.phone },
        ],
      },
      { $set: { customerId: customer._id.toString() } }
    );
    upserted += 1;
  }

  return { processed: groups.length, upserted };
}
