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

import { clearStoredAuthSession } from '@/lib/authStorage';
import { clearSupabaseAuthStorage, getSupabaseClient } from '@/lib/supabase';
import { logout, restoreSession } from '@/services/authService';

vi.mock('@/lib/supabase', () => ({
  getSupabaseClient: vi.fn(),
  clearSupabaseAuthStorage: vi.fn(),
}));

vi.mock('@/lib/authStorage', () => ({
  clearStoredAuthSession: vi.fn(),
}));

describe('authService', () => {
  beforeEach(() => {
    vi.resetAllMocks();
  });

  it('clears persisted auth state when the refresh token is invalid during restore', async () => {
    vi.mocked(getSupabaseClient).mockReturnValue({
      auth: {
        getSession: vi.fn().mockRejectedValue(new Error('Invalid Refresh Token: Refresh Token Not Found')),
      },
    } as unknown as ReturnType<typeof getSupabaseClient>);

    await expect(restoreSession()).resolves.toBeNull();

    expect(clearStoredAuthSession).toHaveBeenCalledTimes(1);
    expect(clearSupabaseAuthStorage).toHaveBeenCalledTimes(1);
  });

  it('rethrows unrelated restore errors', async () => {
    vi.mocked(getSupabaseClient).mockReturnValue({
      auth: {
        getSession: vi.fn().mockRejectedValue(new Error('network down')),
      },
    } as unknown as ReturnType<typeof getSupabaseClient>);

    await expect(restoreSession()).rejects.toThrow('network down');

    expect(clearStoredAuthSession).not.toHaveBeenCalled();
    expect(clearSupabaseAuthStorage).not.toHaveBeenCalled();
  });

  it('clears persisted auth state even when logout fails', async () => {
    vi.mocked(getSupabaseClient).mockReturnValue({
      auth: {
        signOut: vi.fn().mockRejectedValue(new Error('sign out failed')),
      },
    } as unknown as ReturnType<typeof getSupabaseClient>);

    await expect(logout()).rejects.toThrow('sign out failed');

    expect(clearStoredAuthSession).toHaveBeenCalledTimes(1);
    expect(clearSupabaseAuthStorage).toHaveBeenCalledTimes(1);
  });
});