import { gql } from 'graphql-request'
import type { PreviewData } from '@/lib/types'
import fetchAPI from '@/lib/api/fetchAPI'
import { nodesFromEdges } from '@/lib/utilities'
import { POST_FRAGMENT } from './fragments'

/**
 * Query a single post by slug
 */
export async function getPostBySlug(slug: string, preview: boolean, previewData: PreviewData) {
  const postPreview = preview ? previewData.post : ({} as PreviewData['post'])
  // The slug may be the id of an unpublished post
  const isSlugId = Number.isInteger(Number(slug))
  const isSamePost = isSlugId ? Number(slug) === Number(postPreview?.id) : slug === postPreview.slug
  const isDraft = isSamePost && postPreview?.status === 'draft'
  const isRevision = isSamePost && postPreview?.status === 'publish'

  const revisionsConnection = gql`
    revisions(first: 1, where: { orderby: { field: MODIFIED, order: DESC } }) {
      edges {
        node {
          title
          excerpt
          content
          author {
            node {
              ...UserFields
            }
          }
        }
      }
    }
  `

  const data = await fetchAPI(
    gql`
      ${POST_FRAGMENT}
      query PostBySlug($id: ID!, $idType: PostIdType!, $isIndex: Boolean!) {
        page: post(id: $id, idType: $idType) {
          ...PostFields
          content
          # Only some of the fields of a revision are considered as there are some inconsistencies
          ${isRevision ? revisionsConnection : ''}
        }

        morePosts: posts(first: 4) {
          edges {
            node {
              ...PostFields
            }
          }
        }
      }
    `,
    {
      variables: {
        id: isDraft ? postPreview.id : slug,
        idType: isDraft ? 'DATABASE_ID' : 'SLUG',
        isIndex: false,
      },
    }
  )

  // Draft posts may not have an slug
  if (isDraft) data.page.slug = postPreview.id

  // Apply a revision (changes in a published post)
  if (isRevision && data.page.revisions) {
    const revision = data.page.revisions.edges[0]?.node

    if (revision) Object.assign(data.page, revision)
    delete data.page.revisions
  }

  // Filter out current ID and only return 3 more posts
  if (data.morePosts?.edges) {
    data.morePosts.edges = data.morePosts?.edges.filter((x: any) => x.id !== data.page.id).slice(0, 3)
  }

  return data
}

/**
 * Query all posts
 */
export async function getPostsPage() {
  const data = await fetchAPI(
    gql`
      ${POST_FRAGMENT}
      query PostsPage($isIndex: Boolean!) {
        page(id: "blog", idType: URI) {
          id
          title
          seo {
            fullHead
          }
          featuredBlogHeroSection {
            featuredBlog {
              ... on Post {
                uri
                title
                featuredImage {
                  node {
                    alt: altText
                    imageUrl: sourceUrl
                    placeholder: sourceUrl(size: THUMBNAIL)
                  }
                }
                terms {
                  edges {
                    node {
                      taxonomyName
                      slug
                      name
                    }
                  }
                }
              }
            }
          }
        }

        posts(first: 10000) {
          edges {
            node {
              ...PostFields
            }
          }
        }
      }
    `,
    {
      variables: {
        isIndex: true,
      },
    }
  )

  return data
}

/**
 * Query all post slugs
 */
export async function getAllPostSlugs() {
  const data = await fetchAPI(
    gql`
      query AllPostSlugs {
        posts(first: 10000) {
          edges {
            node {
              slug
              uri
            }
          }
        }
      }
    `
  )

  return nodesFromEdges(data?.posts?.edges || [])
}
