import { describe, it, expect, vi, beforeEach } from 'vitest'
import { createPinia, setActivePinia } from 'pinia'
import { useSessionsStore } from '@/stores/sessions.js'

vi.mock('@/api/index.js', () => ({
  getSessions: vi.fn(),
  createSession: vi.fn(),
  deleteSession: vi.fn(),
  pinSession: vi.fn(),
}))

import * as api from '@/api/index.js'

describe('Sessions store', () => {
  beforeEach(() => {
    setActivePinia(createPinia())
    vi.clearAllMocks()
  })

  it('fetchSessions loads sessions', async () => {
    api.getSessions.mockResolvedValue({
      items: [{ session_id: 's1', profile_id: 'secretary', pinned: false }],
      has_more: true,
      next_offset: 1,
    })
    const store = useSessionsStore()
    await store.fetchSessions('developer')
    expect(api.getSessions).toHaveBeenCalledWith({ limit: 30, offset: 0, profileId: 'developer', search: null })
    expect(store.sessions).toHaveLength(1)
    expect(store.sessions[0].session_id).toBe('s1')
    expect(store.hasMore).toBe(true)
    expect(store.currentProfileId).toBe('developer')
    expect(store.loading).toBe(false)
  })

  it('fetchMoreSessions appends the next page', async () => {
    api.getSessions
      .mockResolvedValueOnce({
        items: [{ session_id: 's1', profile_id: 'secretary', pinned: false }],
        has_more: true,
        next_offset: 1,
      })
      .mockResolvedValueOnce({
        items: [{ session_id: 's2', profile_id: 'developer', pinned: false }],
        has_more: false,
        next_offset: 2,
      })
    const store = useSessionsStore()
    await store.fetchSessions('developer')
    await store.fetchMoreSessions()
    expect(api.getSessions).toHaveBeenLastCalledWith({ limit: 30, offset: 1, profileId: 'developer', search: null })
    expect(store.sessions.map(s => s.session_id)).toEqual(['s1', 's2'])
    expect(store.hasMore).toBe(false)
    expect(store.loadingMore).toBe(false)
  })

  it('fetchMoreSessions does nothing without more pages', async () => {
    api.getSessions.mockResolvedValue({
      items: [],
      has_more: false,
      next_offset: 0,
    })
    const store = useSessionsStore()
    await store.fetchSessions()
    await store.fetchMoreSessions()
    expect(api.getSessions).toHaveBeenCalledTimes(1)
  })

  it('createSession prepends placeholder and returns session', async () => {
    api.createSession.mockResolvedValue({
      session_id: 's2',
      profile_id: 'developer',
      created_at: '2024-01-01T00:00:00Z',
    })
    const store = useSessionsStore()
    const result = await store.createSession('developer')
    expect(api.createSession).toHaveBeenCalledWith('developer')
    expect(store.sessions).toHaveLength(1)
    expect(store.sessions[0].session_id).toBe('s2')
    expect(store.sessions[0].message_count).toBe(0)
    expect(result.session_id).toBe('s2')
  })

  it('deleteSession filters out the session', async () => {
    api.deleteSession.mockResolvedValue()
    const store = useSessionsStore()
    store.sessions = [
      { session_id: 's1' },
      { session_id: 's2' },
    ]
    await store.deleteSession('s1')
    expect(api.deleteSession).toHaveBeenCalledWith('s1')
    expect(store.sessions).toHaveLength(1)
    expect(store.sessions[0].session_id).toBe('s2')
  })

  it('pinSession sorts pinned to top', async () => {
    api.pinSession.mockResolvedValue()
    const store = useSessionsStore()
    store.sessions = [
      { session_id: 's1', pinned: false },
      { session_id: 's2', pinned: false },
    ]
    await store.pinSession('s2', true)
    expect(api.pinSession).toHaveBeenCalledWith('s2', true)
    expect(store.sessions[0].session_id).toBe('s2')
    expect(store.sessions[0].pinned).toBe(true)
  })

  it('updatePreview mutates session preview', () => {
    const store = useSessionsStore()
    store.sessions = [{ session_id: 's1', preview: '' }]
    store.updatePreview('s1', 'hello')
    expect(store.sessions[0].preview).toBe('hello')
  })

  it('updateName mutates session name', () => {
    const store = useSessionsStore()
    store.sessions = [{ session_id: 's1', name: null }]
    store.updateName('s1', 'Work')
    expect(store.sessions[0].name).toBe('Work')
  })
})
