// ====== tests

import { nextTick } from 'vue'

import { mount } from '../framework'
import { FilterPosts } from '../app/FilterPosts'

describe('FilterPosts', () => {
  it('renders today posts by default', async () => {
    const wrapper = mount(FilterPosts)

    expect(wrapper.find('.post').text()).toBe('In the news today...')
    expect(wrapper.findAll('.post')).toHaveLength(1)
  })

  it('toggles the filter', async () => {
    const wrapper = mount(FilterPosts)

    wrapper.findAll('button')[1].trigger('click')
    await nextTick()

    expect(wrapper.findAll('.post')).toHaveLength(2)
    expect(wrapper.find('h1').text()).toBe('Posts from this week')
    expect(wrapper.findAll('.post')[0].text()).toBe('In the news today...')
    expect(wrapper.findAll('.post')[1].text()).toBe('In the news this week...')
  })
})

// ====== component

import { defineComponent, ref, h, computed } from 'vue'
import moment, { Moment } from 'moment'

interface Post {
  id: number
  title: string
  created: Moment
}

const posts: Post[] = [
  {
    id: 1,
    title: 'In the news today...',
    created: moment()
  },
  {
    id: 2,
    title: 'In the news this week...',
    created: moment().add(4 ,'days')
  }
]

export const NewsPost = defineComponent({
  props: {
    post: {
      type: Object as () => Post,
      required: true
    },
  },

  setup(props) {
    return () => h('div', { className: 'post' }, props.post.title)
  }
})

type FilterPeriod = 'today' | 'this week'
const filters: FilterPeriod[] = ['today', 'this week']

export const Filter = defineComponent({
  props: {
    filter: {
      type: String as () => FilterPeriod,
      required: true
    }
  },

  setup(props, ctx) { 
    return () => h('button', { onClick: () => ctx.emit('select', props.filter) }, props.filter)
  }
})

export const FilterPosts = defineComponent({
  setup() {
    const selectedFilter = ref<FilterPeriod>('today')
    const filteredPosts = computed(() => {
      return posts.filter(post => {
        if (selectedFilter.value === 'today') {
          return post.created.isSameOrBefore(moment().add(0, 'days'))
        }

        if (selectedFilter.value === 'this week') {
          return post.created.isSameOrBefore(moment().add(1, 'week'))
        }

        return post
      })
    })

    return () => 
      h('div',
        [
          h('h1', `Posts from ${selectedFilter.value}`),
          filters.map(filter => h(Filter, { filter, onSelect: filter => selectedFilter.value = filter })),
          filteredPosts.value.map(post => h(NewsPost, { post }))
        ]
      )
  }
})