import { gql } from 'graphql-request'
import useSWR from 'swr'
import { makePublicGqlFetcher, RequestContext, ssrFetcher } from '../networkHelpers'
import { Highlight } from '../fragments/highlightFragment'

type PublicArticleQueryInput = {
  username: string
  slug: string
  selectedHighlightId?: string
}

export type PublicArticleQueryOutput = {
  publicArticle?: PublicArticleAttributes
  fetchError: unknown
  isLoading: boolean
  isValidating: boolean
}

type PublicArticleData = {
  sharedArticle: NestedPublicArticleData
}

type NestedPublicArticleData = {
  article: PublicArticleAttributes
}

export type PublicArticleAttributes = {
  id: string
  title: string
  slug: string
  url: string
  author?: string
  image?: string
  description?: string
  hasContent?: boolean
  highlights: Highlight[]
}

export const PublicArticleGQLFragment = gql`
  fragment PublicArticle on Article {
    id
    title
    slug
    url
    author
    image
    description
    savedByViewer
    postedByViewer
    hasContent
    highlights {
      id
      shortId
      quote
      prefix
      suffix
      patch
      annotation
      sharedAt
      user {
        id
        name
        profile {
          id
          username
          pictureUrl
        }
      }
    }
  }
`

const query = gql`
  query GetPublicArticle(
    $username: String!
    $slug: String!
    $selectedHighlightId: String
  ) {
    sharedArticle(
      username: $username
      slug: $slug
      selectedHighlightId: $selectedHighlightId
    ) {
      ... on SharedArticleSuccess {
        article {
          ...PublicArticle
        }
      }

      ... on SharedArticleError {
        errorCodes
      }
    }
  }
  ${PublicArticleGQLFragment}
`

export function useGetPublicArticleQuery({
  username,
  slug,
  selectedHighlightId,
}: PublicArticleQueryInput): PublicArticleQueryOutput {
  const variables = {
    username,
    slug,
    selectedHighlightId,
  }

  const { data, error, isValidating } = useSWR(
    // Only make request if username is defined
    !!username ? [query, username, slug, selectedHighlightId] : null,
    makePublicGqlFetcher(variables)
  )
  const publicArticle = (data as PublicArticleData)?.sharedArticle?.article

  return {
    publicArticle,
    fetchError: error as unknown,
    isLoading: !error && !publicArticle,
    isValidating,
  }
}

export async function publicArticleQuery(
  context: RequestContext,
  input: PublicArticleQueryInput
): Promise<PublicArticleAttributes> {
  const result = (await ssrFetcher(context, query, input, false)) as PublicArticleData
  if (result.sharedArticle.article) {
    return result.sharedArticle.article
  }

  return Promise.reject()
}
