import { describe, it, expect, beforeEach } from 'vitest'
import { useSoloStore } from '@/stores/solo-store'
import type { RealtimeEvent } from '@/stores/solo-store'
import type { SoloTask } from '@/components/solo/solo-board'

const baseTask = (id: string, overrides: Partial<SoloTask> = {}): SoloTask => ({
  id,
  title: `Task ${id}`,
  description: null,
  implementation_plan: null,
  priority: 1,
  sort_order: 1,
  status: 'TO_DO',
  verify_only: false,
  verify_required: 'ALIGNED_OR_PARTIAL',
  story_id: 'story-1',
  story_code: 'ST-100',
  story_title: 'Original Story',
  task_code: 'ST-100.1',
  pbi_code: null,
  pbi_title: null,
  pbi_description: null,
  ...overrides,
})

const taskEvent = (overrides: Partial<RealtimeEvent>): RealtimeEvent => ({
  op: 'U',
  entity: 'task',
  id: 'task-1',
  story_id: 'story-1',
  product_id: 'prod-1',
  sprint_id: 'sprint-1',
  assignee_id: 'user-1',
  ...overrides,
})

const storyEvent = (overrides: Partial<RealtimeEvent>): RealtimeEvent => ({
  op: 'U',
  entity: 'story',
  id: 'story-1',
  product_id: 'prod-1',
  sprint_id: 'sprint-1',
  assignee_id: 'user-1',
  ...overrides,
})

describe('solo-store realtime', () => {
  beforeEach(() => {
    useSoloStore.setState({ tasks: {}, pendingOps: new Set() })
  })

  it('applies a task status update', () => {
    useSoloStore.getState().initTasks([baseTask('task-1', { status: 'TO_DO' })])
    useSoloStore.getState().handleRealtimeEvent(taskEvent({ task_status: 'IN_PROGRESS' }))
    expect(useSoloStore.getState().tasks['task-1'].status).toBe('IN_PROGRESS')
  })

  it('skips a task update when pendingOps has the id', () => {
    useSoloStore.getState().initTasks([baseTask('task-1', { status: 'TO_DO' })])
    useSoloStore.getState().markPending('task-1')
    useSoloStore.getState().handleRealtimeEvent(taskEvent({ task_status: 'DONE' }))
    expect(useSoloStore.getState().tasks['task-1'].status).toBe('TO_DO')
  })

  it('applies the update again once pendingOps is cleared', () => {
    useSoloStore.getState().initTasks([baseTask('task-1', { status: 'TO_DO' })])
    useSoloStore.getState().markPending('task-1')
    useSoloStore.getState().handleRealtimeEvent(taskEvent({ task_status: 'DONE' }))
    expect(useSoloStore.getState().tasks['task-1'].status).toBe('TO_DO')
    useSoloStore.getState().clearPending('task-1')
    useSoloStore.getState().handleRealtimeEvent(taskEvent({ task_status: 'DONE' }))
    expect(useSoloStore.getState().tasks['task-1'].status).toBe('DONE')
  })

  it('removes a task on D op', () => {
    useSoloStore.getState().initTasks([baseTask('task-1'), baseTask('task-2')])
    useSoloStore.getState().handleRealtimeEvent(taskEvent({ id: 'task-1', op: 'D' }))
    expect(useSoloStore.getState().tasks['task-1']).toBeUndefined()
    expect(useSoloStore.getState().tasks['task-2']).toBeDefined()
  })

  it('ignores task INSERT/UPDATE for tasks not in the store', () => {
    useSoloStore.getState().initTasks([baseTask('task-1')])
    useSoloStore.getState().handleRealtimeEvent(taskEvent({ id: 'task-other', task_status: 'DONE' }))
    expect(Object.keys(useSoloStore.getState().tasks)).toEqual(['task-1'])
  })

  it('updates story_title/code on all child tasks via story UPDATE', () => {
    useSoloStore.getState().initTasks([
      baseTask('task-1', { story_id: 'story-1' }),
      baseTask('task-2', { story_id: 'story-1' }),
      baseTask('task-3', { story_id: 'story-other', story_title: 'Other' }),
    ])
    useSoloStore.getState().handleRealtimeEvent(
      storyEvent({ story_title: 'Renamed Story', story_code: 'ST-100B' }),
    )
    expect(useSoloStore.getState().tasks['task-1'].story_title).toBe('Renamed Story')
    expect(useSoloStore.getState().tasks['task-1'].story_code).toBe('ST-100B')
    expect(useSoloStore.getState().tasks['task-2'].story_title).toBe('Renamed Story')
    expect(useSoloStore.getState().tasks['task-3'].story_title).toBe('Other')
  })

  it('removes all tasks of a story on story DELETE', () => {
    useSoloStore.getState().initTasks([
      baseTask('task-1', { story_id: 'story-1' }),
      baseTask('task-2', { story_id: 'story-1' }),
      baseTask('task-3', { story_id: 'story-other' }),
    ])
    useSoloStore.getState().handleRealtimeEvent(storyEvent({ op: 'D' }))
    expect(useSoloStore.getState().tasks['task-1']).toBeUndefined()
    expect(useSoloStore.getState().tasks['task-2']).toBeUndefined()
    expect(useSoloStore.getState().tasks['task-3']).toBeDefined()
  })
})
