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

vi.mock('@/api/authApi', () => ({
  authApi: {
    login: vi.fn(),
    logout: vi.fn(() => Promise.resolve()),
    me: vi.fn(),
    signup: vi.fn(),
    signupEnabled: vi.fn(),
  },
}))

// 네이티브 저장소 — 테스트에선 no-op (localStorage 미러만 검증)
vi.mock('@capacitor/preferences', () => ({
  Preferences: {
    set: vi.fn(() => Promise.resolve()),
    get: vi.fn(() => Promise.resolve({ value: null })),
    remove: vi.fn(() => Promise.resolve()),
    clear: vi.fn(() => Promise.resolve()),
  },
}))

import { authApi } from '@/api/authApi'
import { useAuthStore } from '@/stores/auth'

describe('auth 스토어', () => {
  beforeEach(() => {
    setActivePinia(createPinia())
    localStorage.clear()
  })

  it('login: 토큰/사용자 저장 + localStorage 미러 + isAuthenticated', async () => {
    authApi.login.mockResolvedValue({
      token: 'tok123',
      member: { id: 1, loginId: 'u1', name: '홍길동', email: 'a@b.com' },
    })
    const store = useAuthStore()
    await store.login('u1', 'pw', true)

    expect(authApi.login).toHaveBeenCalledWith({ loginId: 'u1', password: 'pw', rememberMe: true })
    expect(store.token).toBe('tok123')
    expect(store.isAuthenticated).toBe(true)
    expect(store.user.email).toBe('a@b.com')
    expect(localStorage.getItem('token')).toBe('tok123')
    expect(JSON.parse(localStorage.getItem('auth_user')).name).toBe('홍길동')
  })

  it('logout: 상태/스토리지 정리', async () => {
    authApi.login.mockResolvedValue({ token: 't', member: { id: 1, loginId: 'u1' } })
    const store = useAuthStore()
    await store.login('u1', 'pw', false)
    expect(store.isAuthenticated).toBe(true)

    await store.logout()
    expect(authApi.logout).toHaveBeenCalled()
    expect(store.token).toBe('')
    expect(store.user).toBeNull()
    expect(store.isAuthenticated).toBe(false)
    expect(localStorage.getItem('token')).toBeNull()
    expect(localStorage.getItem('auth_user')).toBeNull()
  })

  it('logout: 서버 401 이어도 클라이언트는 정리', async () => {
    authApi.login.mockResolvedValue({ token: 't', member: { id: 1 } })
    authApi.logout.mockRejectedValueOnce(new Error('401'))
    const store = useAuthStore()
    await store.login('u1', 'pw', false)

    await store.logout()
    expect(store.token).toBe('')
    expect(store.isAuthenticated).toBe(false)
  })

  it('restore: localStorage 세션 복원 + ready', async () => {
    localStorage.setItem('token', 't2')
    localStorage.setItem('auth_user', JSON.stringify({ id: 2, name: '복원유저' }))
    const store = useAuthStore()
    await store.restore()

    expect(store.token).toBe('t2')
    expect(store.user.name).toBe('복원유저')
    expect(store.isAuthenticated).toBe(true)
    expect(store.ready).toBe(true)
  })

  it('applyUser: 변경 필드 병합 + 미러 갱신 (가입정보 변경 반영)', async () => {
    authApi.login.mockResolvedValue({
      token: 't',
      member: { id: 1, loginId: 'u1', name: '원래이름', email: 'old@b.com' },
    })
    const store = useAuthStore()
    await store.login('u1', 'pw', false)

    await store.applyUser({ name: '새이름', email: 'new@b.com' })
    expect(store.user.name).toBe('새이름')
    expect(store.user.loginId).toBe('u1') // 기존 필드 보존
    expect(JSON.parse(localStorage.getItem('auth_user')).email).toBe('new@b.com')
  })
})
