import { beforeEach, describe, expect, it, vi } from 'vitest';

const mocked = vi.hoisted(() => ({
  poolQuery: vi.fn(),
  poolEnd: vi.fn(),
  poolOn: vi.fn(),
  sendMonthlyPassExpiryEmail: vi.fn(async () => undefined),
}));

vi.mock('../../db', () => ({
  default: {
    query: mocked.poolQuery,
    end: mocked.poolEnd,
    on: mocked.poolOn,
  },
}));

vi.mock('../../services/email', () => ({
  sendMonthlyPassExpiryEmail: mocked.sendMonthlyPassExpiryEmail,
}));

describe('monthly pass reminders worker', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    process.env.VITEST = 'true';
  });

  it('emails and marks users whose monthly pass expires within 24 hours', async () => {
    mocked.poolQuery
      .mockResolvedValueOnce({
        rows: [{
          id: 'user-1',
          email: 'rain@example.com',
          monthly_pass_expires: '2026-03-30T15:00:00.000Z',
        }],
      })
      .mockResolvedValueOnce({ rows: [] });

    const { processMonthlyPassRenewalReminders } = await import('../monthly-pass-reminders');
    const sent = await processMonthlyPassRenewalReminders(new Date('2026-03-29T18:00:00.000Z'));

    expect(sent).toBe(1);
    expect(mocked.sendMonthlyPassExpiryEmail).toHaveBeenCalledWith('rain@example.com', {
      expiresAt: '2026-03-30T15:00:00.000Z',
    });
    expect(String(mocked.poolQuery.mock.calls[0]?.[0])).toContain('monthly_pass_renewal_reminder_sent_at IS NULL');
    expect(String(mocked.poolQuery.mock.calls[1]?.[0])).toContain('SET monthly_pass_renewal_reminder_sent_at = NOW()');
  });

  it('does nothing when no passes are near expiry', async () => {
    mocked.poolQuery.mockResolvedValueOnce({ rows: [] });

    const { processMonthlyPassRenewalReminders } = await import('../monthly-pass-reminders');
    const sent = await processMonthlyPassRenewalReminders(new Date('2026-03-29T18:00:00.000Z'));

    expect(sent).toBe(0);
    expect(mocked.sendMonthlyPassExpiryEmail).not.toHaveBeenCalled();
    expect(mocked.poolQuery).toHaveBeenCalledTimes(1);
  });
});
