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

vi.mock('../api/client', () => ({
  default: {
    get: vi.fn(),
    post: vi.fn(),
    put: vi.fn(),
    delete: vi.fn(),
    interceptors: {
      request: { use: vi.fn() },
      response: { use: vi.fn() },
    },
  },
}))

import api from '../api/client'
import { useAuthStore } from '../store/auth'

describe('useAuthStore', () => {
  beforeEach(() => {
    useAuthStore.setState({
      user: null,
      isLoading: true,
      isAuthenticated: false,
    })
    localStorage.clear()
    vi.clearAllMocks()
  })

  it('should have correct initial state', () => {
    const state = useAuthStore.getState()
    expect(state.user).toBeNull()
    expect(state.isLoading).toBe(true)
    expect(state.isAuthenticated).toBe(false)
  })

  it('should login successfully', async () => {
    const mockResponse = {
      data: {
        user: { id: 1, email: 'test@test.com', username: 'test' },
        access_token: 'access-123',
        refresh_token: 'refresh-123',
      },
    }
    api.post.mockResolvedValueOnce(mockResponse)

    await useAuthStore.getState().login('test@test.com', 'password')

    expect(api.post).toHaveBeenCalledWith('/auth/login', {
      email: 'test@test.com',
      password: 'password',
    })
    expect(localStorage.getItem('access_token')).toBe('access-123')
    expect(localStorage.getItem('refresh_token')).toBe('refresh-123')
    expect(useAuthStore.getState().isAuthenticated).toBe(true)
    expect(useAuthStore.getState().user).toEqual(mockResponse.data.user)
  })

  it('should register successfully', async () => {
    const mockResponse = {
      data: {
        user: { id: 2, email: 'new@test.com', username: 'newuser' },
        access_token: 'access-456',
        refresh_token: 'refresh-456',
      },
    }
    api.post.mockResolvedValueOnce(mockResponse)

    await useAuthStore.getState().register('new@test.com', 'newuser', 'password123')

    expect(api.post).toHaveBeenCalledWith('/auth/register', {
      email: 'new@test.com',
      username: 'newuser',
      password: 'password123',
    })
    expect(useAuthStore.getState().isAuthenticated).toBe(true)
    expect(localStorage.getItem('access_token')).toBe('access-456')
  })

  it('should logout and clear tokens', () => {
    localStorage.setItem('access_token', 'old-token')
    localStorage.setItem('refresh_token', 'old-refresh')
    useAuthStore.setState({ user: { id: 1 }, isAuthenticated: true })

    useAuthStore.getState().logout()

    expect(localStorage.getItem('access_token')).toBeNull()
    expect(localStorage.getItem('refresh_token')).toBeNull()
    expect(useAuthStore.getState().user).toBeNull()
    expect(useAuthStore.getState().isAuthenticated).toBe(false)
  })

  it('should initialize with no token', async () => {
    await useAuthStore.getState().initialize()

    expect(useAuthStore.getState().isLoading).toBe(false)
    expect(useAuthStore.getState().isAuthenticated).toBe(false)
  })

  it('should initialize with valid token', async () => {
    localStorage.setItem('access_token', 'valid-token')
    api.get.mockResolvedValueOnce({
      data: { id: 1, email: 'test@test.com', username: 'test' },
    })

    await useAuthStore.getState().initialize()

    expect(api.get).toHaveBeenCalledWith('/auth/me')
    expect(useAuthStore.getState().isAuthenticated).toBe(true)
    expect(useAuthStore.getState().isLoading).toBe(false)
    expect(useAuthStore.getState().user.email).toBe('test@test.com')
  })

  it('should handle invalid token on initialize', async () => {
    localStorage.setItem('access_token', 'invalid-token')
    api.get.mockRejectedValueOnce(new Error('401'))

    await useAuthStore.getState().initialize()

    expect(useAuthStore.getState().isAuthenticated).toBe(false)
    expect(localStorage.getItem('access_token')).toBeNull()
    expect(localStorage.getItem('refresh_token')).toBeNull()
  })

  it('should handle login error', async () => {
    api.post.mockRejectedValueOnce(new Error('Invalid credentials'))

    await expect(
      useAuthStore.getState().login('bad@test.com', 'wrong')
    ).rejects.toThrow('Invalid credentials')

    expect(useAuthStore.getState().isAuthenticated).toBe(false)
  })
})
