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

vi.mock('./auth.employee.repo', () => ({
  findActiveEmployeeByEmail: vi.fn(),
  findEmployeeById: vi.fn(),
  findEmployeeByResetToken: vi.fn(),
  resetPassword: vi.fn(),
}))

vi.mock('../../services/notificationService', () => ({
  sendTransactionalEmail: vi.fn().mockResolvedValue(undefined),
}))

import * as repo from './auth.employee.repo'
import { sendTransactionalEmail } from '../../services/notificationService'
import { forgotPassword, resetPassword } from './auth.employee.service'

describe('auth.employee.service forgotPassword', () => {
  const originalDashboardUrl = process.env.DASHBOARD_URL
  const originalJwtSecret = process.env.JWT_SECRET

  beforeEach(() => {
    vi.clearAllMocks()
    process.env.DASHBOARD_URL = 'http://localhost:3000/dashboard'
    process.env.JWT_SECRET = 'test-secret'
  })

  afterAll(() => {
    process.env.DASHBOARD_URL = originalDashboardUrl
    process.env.JWT_SECRET = originalJwtSecret
  })

  it('sends the reset email to the canonical stored address', async () => {
    vi.mocked(repo.findActiveEmployeeByEmail).mockResolvedValue({
      id: 'emp_1',
      email: 'owner@company.com',
      firstName: 'Aya',
      preferredLanguage: 'en',
      passwordHash: '$2a$12$abcdefghijklmnopqrstuv',
    } as any)

    await forgotPassword('Owner@Company.com')

    expect(sendTransactionalEmail).toHaveBeenCalledWith(
      expect.objectContaining({
        to: 'owner@company.com',
        html: expect.stringContaining('/dashboard/reset-password?token='),
        text: expect.stringContaining('/dashboard/reset-password?token='),
      }),
    )
  })

  it('accepts stateless reset tokens', async () => {
    const employee = {
      id: 'emp_1',
      isActive: true,
      passwordHash: '$2a$12$abcdefghijklmnopqrstuv',
    } as any

    vi.mocked(repo.findActiveEmployeeByEmail).mockResolvedValue({
      ...employee,
      email: 'owner@company.com',
      firstName: 'Aya',
      preferredLanguage: 'en',
    })
    vi.mocked(repo.findEmployeeByResetToken).mockResolvedValue(null)
    vi.mocked(repo.findEmployeeById).mockResolvedValue(employee)
    vi.mocked(repo.resetPassword).mockResolvedValue({} as any)

    await forgotPassword('Owner@Company.com')

    const emailCall = vi.mocked(sendTransactionalEmail).mock.calls[0]?.[0]
    const match = emailCall?.text.match(/token=([^\s]+)/)
    expect(match?.[1]).toBeTruthy()

    await expect(resetPassword(decodeURIComponent(match![1]), 'new-password-123')).resolves.toEqual({
      message: 'Password updated successfully. You can now sign in.',
    })
    expect(repo.resetPassword).toHaveBeenCalledWith('emp_1', expect.any(String))
  })
})
