import type { LinkType } from '@/components/LinkButton'
import LinkButton from '@/components/LinkButton'
import type { EntityTitleProps } from '@blueprintjs/core'
import { Classes, Icon, Spinner } from '@blueprintjs/core'
import { css } from '@emotion/css'
import type { ActionLogSimple } from '@inject/graphql/fragment-types'
import { useTypedQuery } from '@inject/graphql/graphql'
import { WriteReadReceipt } from '@inject/graphql/mutations.client'
import { GetSingleActionLog } from '@inject/graphql/queries'
import { useClient } from '@inject/graphql/urql/client'
import Message from '@inject/shared/components/Message'
import HeaderItem from '@inject/shared/components/Message/HeaderItem'
import Timestamp from '@inject/shared/components/StyledTag/Timestamp'
import { useEffect, useLayoutEffect, useMemo, useState, type FC } from 'react'
import Content from './Content'
import { getIcon, getTitle } from './utils'

const title = css`
  font-weight: bold;
`

// TODO: ellipsize for too long messages, expand onInspect
interface InjectMessageProps {
  actionLog: ActionLogSimple
  exerciseId: string
  teamId: string
  fullscreenLink?: LinkType
  fill?: boolean
  inInstructor: boolean
}

const InjectMessage: FC<InjectMessageProps> = ({
  actionLog: actionLogSimple,
  exerciseId,
  teamId,
  fullscreenLink,
  fill,
  inInstructor,
}) => {
  const client = useClient()

  const [{ data }] = useTypedQuery({
    query: GetSingleActionLog,
    variables: { logId: actionLogSimple.id },
    context: useMemo(
      () => ({
        suspense: true,
      }),
      []
    ),
  })

  const actionLog = data?.actionLog

  // this ensures the message is rendered as 'not read' the first time it's rendered
  const [initialReadReceipt, setInitialReadReceipt] = useState(false)

  useLayoutEffect(() => {
    if (!actionLogSimple.readReceipt) {
      setInitialReadReceipt(true)
    }
  }, [actionLogSimple.id, actionLogSimple.readReceipt, client])

  useEffect(() => {
    // you can't use URQL calls in layout effects
    if (initialReadReceipt) {
      client
        .mutation(WriteReadReceipt, { actionLogId: actionLogSimple.id })
        .then()
    }
  }, [actionLogSimple.id, client, initialReadReceipt])

  const showOverlay = useMemo(
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    () => inInstructor && actionLog && !!(actionLog.details as any)?.overlay,
    [actionLog, inInstructor]
  )

  const titleProps: EntityTitleProps = useMemo(
    () => ({
      icon: 'applications',
      title: 'Overlay',
      subtitle: 'This inject is shown to trainees as an overlay',
    }),
    []
  )

  if (!actionLog) {
    return <Spinner />
  }

  return (
    <Message
      fill={fill}
      titleProps={showOverlay ? titleProps : undefined}
      warning={showOverlay}
      header={
        <>
          <HeaderItem>
            <Icon
              className={Classes.TEXT_MUTED}
              style={{ paddingLeft: '0.25rem' }}
              icon={getIcon(actionLog.type)}
            />
            <span className={title}>{getTitle(actionLog)}</span>
          </HeaderItem>
          <HeaderItem>
            <Timestamp
              minimal
              datetime={new Date(actionLog.timestamp || 0)}
              isRead={!initialReadReceipt}
            />
            {fullscreenLink && (
              <LinkButton
                button={{
                  minimal: true,
                  icon: 'fullscreen',
                }}
                link={fullscreenLink}
              />
            )}
          </HeaderItem>
        </>
      }
    >
      <Content
        actionLog={actionLog}
        teamId={teamId}
        exerciseId={exerciseId}
        inInstructor={inInstructor}
      />
    </Message>
  )
}

export default InjectMessage
