import { beforeEach, describe, expect, it, vi } from 'vitest'
import { AppError } from '../../http/errors'
import * as repo from './auth.renter.repo'
import * as service from './auth.renter.service'

vi.mock('./auth.renter.repo', () => ({
  findRenterProfile: vi.fn(),
  findSavedCompanies: vi.fn(),
  updateRenterProfile: vi.fn(),
  updateRenterFcmToken: vi.fn(),
}))

describe('auth.renter.service', () => {
  beforeEach(() => vi.clearAllMocks())

  it('keeps renter self-signup disabled with an explicit product error', () => {
    expect(() => service.signupDisabled()).toThrow(AppError)
    try {
      service.signupDisabled()
    } catch (err) {
      expect(err).toMatchObject({ statusCode: 403, error: 'renter_signup_disabled' })
    }
  })

  it('keeps renter login disabled with an explicit product error', () => {
    expect(() => service.loginDisabled()).toThrow(AppError)
    try {
      service.loginDisabled()
    } catch (err) {
      expect(err).toMatchObject({ statusCode: 403, error: 'renter_login_disabled' })
    }
  })

  it('loads saved company brand data only for company IDs attached to the renter profile', async () => {
    vi.mocked(repo.findRenterProfile).mockResolvedValue({
      id: 'renter_1',
      firstName: 'Youssef',
      lastName: 'Amrani',
      email: 'youssef@example.com',
      phone: null,
      preferredLocale: 'fr',
      preferredCurrency: 'MAD',
      emailVerified: true,
      savedCompanies: [{ companyId: 'company_2' }, { companyId: 'company_1' }],
    } as never)
    vi.mocked(repo.findSavedCompanies).mockResolvedValue([
      { id: 'company_1', brand: { displayName: 'Atlas', subdomain: 'atlas', logoUrl: null } },
      { id: 'company_2', brand: { displayName: 'Desert Cars', subdomain: 'desert', logoUrl: '/desert.png' } },
    ] as never)

    await expect(service.getMe('renter_1')).resolves.toMatchObject({
      id: 'renter_1',
      savedCompanies: [
        { id: 'company_2', brand: { displayName: 'Desert Cars' } },
        { id: 'company_1', brand: { displayName: 'Atlas' } },
      ],
    })
    expect(repo.findSavedCompanies).toHaveBeenCalledWith(['company_2', 'company_1'])
  })

  it('delegates profile updates without inventing side effects in the service layer', async () => {
    vi.mocked(repo.updateRenterProfile).mockResolvedValue({ id: 'renter_1', firstName: 'Nora' } as never)

    await expect(service.updateMe('renter_1', { firstName: 'Nora', preferredLocale: 'ar' })).resolves.toEqual({
      id: 'renter_1',
      firstName: 'Nora',
    })
    expect(repo.updateRenterProfile).toHaveBeenCalledWith('renter_1', { firstName: 'Nora', preferredLocale: 'ar' })
  })

  it('updates the renter FCM token and returns a stable success contract', async () => {
    vi.mocked(repo.updateRenterFcmToken).mockResolvedValue({} as never)

    await expect(service.updateFcmToken('renter_1', 'fcm_123')).resolves.toEqual({ success: true })
    expect(repo.updateRenterFcmToken).toHaveBeenCalledWith('renter_1', 'fcm_123')
  })
})
