import { describe, it, expect, vi, beforeEach } from 'vitest'
import { defineComponent, nextTick } from 'vue'
import { mount } from '@vue/test-utils'
import RoutineEditView from '../RoutineEditView.vue'

const mockPush = vi.fn()

vi.mock('vue-router', () => ({
  useRoute: vi.fn(() => ({
    params: {},
    query: { name: 'Timmy' },
  })),
  useRouter: vi.fn(() => ({
    push: mockPush,
    back: vi.fn(),
  })),
}))

vi.mock('@/common/imageCache', () => ({
  getCachedImageUrl: vi.fn(),
}))

vi.mock('@/assets/styles.css', () => ({}))

const EntityEditFormStub = defineComponent({
  name: 'EntityEditForm',
  props: [
    'entityLabel',
    'fields',
    'initialData',
    'isEdit',
    'loading',
    'error',
    'requireDirty',
    'submitDisabled',
  ],
  emits: ['submit', 'cancel', 'add-image'],
  template: `
    <div class="entity-edit-form-stub">
      <button type="button" class="submit-btn" :disabled="submitDisabled" @click="$emit('submit', { name: 'Morning Routine', points: 5, image_id: null })">Submit</button>
      <slot name="before-actions" />
    </div>
  `,
})

const ImagePickerStub = defineComponent({
  name: 'ImagePicker',
  template: '<div class="image-picker-stub" />',
})

describe('RoutineEditView', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    globalThis.fetch = vi
      .fn()
      .mockResolvedValue({ ok: true, json: async () => ({}) }) as typeof fetch
  })

  it('disables Create when there are no routine tasks', async () => {
    const wrapper = mount(RoutineEditView, {
      props: {},
      global: {
        stubs: {
          EntityEditForm: EntityEditFormStub,
          ImagePicker: ImagePickerStub,
        },
      },
    })

    await nextTick()

    const submitButton = wrapper.find('.submit-btn')
    expect(submitButton.exists()).toBe(true)
    expect((submitButton.element as HTMLButtonElement).disabled).toBe(true)
    expect(wrapper.findComponent(EntityEditFormStub).props('submitDisabled')).toBe(true)
  })

  it('creates routine items using nested routine id from create response', async () => {
    const fetchMock = vi.fn<typeof fetch>()
    fetchMock
      .mockResolvedValueOnce({
        ok: true,
        json: async () => ({ message: 'Routine added', routine: { id: 'routine-123' } }),
      } as Response)
      .mockResolvedValueOnce({ ok: true, json: async () => ({ id: 'item-1' }) } as Response)

    globalThis.fetch = fetchMock

    const wrapper = mount(RoutineEditView, {
      props: {},
      global: {
        stubs: {
          EntityEditForm: EntityEditFormStub,
          ImagePicker: ImagePickerStub,
        },
      },
    })

    await wrapper.find('.add-task-trigger').trigger('click')
    await nextTick()

    const nameInput = wrapper.find('#item-name')
    await nameInput.setValue('Make bed')
    await wrapper.find('.item-form-actions .btn.btn-primary').trigger('click')
    await nextTick()

    await wrapper.find('.submit-btn').trigger('click')
    await nextTick()

    expect(fetchMock).toHaveBeenNthCalledWith(
      1,
      '/api/routine/add',
      expect.objectContaining({ method: 'PUT' }),
    )
    expect(fetchMock).toHaveBeenNthCalledWith(
      2,
      '/api/routine/routine-123/item/add',
      expect.objectContaining({ method: 'PUT' }),
    )
    expect(mockPush).toHaveBeenCalledWith({ name: 'RoutineView' })
  })
})
