import {
  Timeline,
  TimelineContent,
  TimelineItem,
  TimelineSeparator,
} from '@mui/lab'
import { Box, SxProps, Typography } from '@mui/material'
import moment from 'moment'
import { useCallback, useRef } from 'react'
import { useInfiniteQuery } from 'react-query'
import { NoDataIllustration } from '..'
import axios from '../../config/axios'
import { useErrorModal } from '../ErrorModalWrapper/ErrorModalWrapper'
import Spinner from '../Spinner'
import Table from '../Tables/BasicTable/Table'
import {
  StyledAvatar,
  StyledCircleIcon,
  StyledSpinnerBox,
  StyledTimeLineDot,
} from './Styles'

interface Props {
  endPoint: string
  tableView: boolean
  enableTitle?: boolean
  params: any
  sx?: SxProps
}

export default function ActivityLog({
  endPoint,
  tableView,
  enableTitle,
  params,
  sx,
}: Props) {
  const errorModal = useErrorModal()
  const fetchActivities = async ({ pageParam = 0 }) => {
    try {
      const response = await axios.get(endPoint, { params: { ...params } })
      return response?.data
    } catch (error) {
      // eslint-disable-next-line no-console
      console.log(error)
      errorModal({ error: error })
    }
  }

  const { data, fetchNextPage, hasNextPage, isFetchingNextPage, isLoading } =
    useInfiniteQuery('activities', fetchActivities, {
      getNextPageParam: (lastPage) => {
        return lastPage?.length ? lastPage[lastPage?.length - 1].id : null
      },
    })

  const activitesData = data ? data?.pages?.flatMap((page) => page) : []

  if (isLoading) return <Spinner />

  if (data?.pages?.length === 0 || !activitesData?.length) {
    return (
      <NoDataIllustration
        imageSrc=""
        message={
          <Typography
            variant="h6"
            style={{ textAlign: 'center', marginTop: '20px' }}
          >
            {'No data found'}
          </Typography>
        }
      />
    )
  }

  return (
    <Box>
      {enableTitle && (
        <Typography
          variant="h1"
          sx={{ fontSize: '18px', fontWeight: 700, margin: '20px' }}
        >
          Activity Log
        </Typography>
      )}

      {!tableView ? (
        <Box
          sx={{
            overflowY: 'scroll',
            '&::-webkit-scrollbar': {
              display: 'none',
            },
            height: '380px',
          }}
        >
          <TimeLineComponent
            activitesData={activitesData}
            fetchNextPage={fetchNextPage}
            isFetchingNextPage={isFetchingNextPage}
            hasNextPage={hasNextPage}
            sx={sx}
          />
        </Box>
      ) : (
        <Box sx={{ margin: '0 25px' }}>
          <Table
            columns={columns}
            dataSource={activitesData}
            loading={isLoading}
          />
        </Box>
      )}
    </Box>
  )
}

const columns = [
  {
    title: 'Date',
    dataIndex: 'timestamp',
    key: 'timestamp',
    render: (timestamp) =>
      moment.utc(timestamp)?.local().format('DD MMM YYYY - hh:mm A'),
  },
  {
    title: 'Action',
    dataIndex: 'action',
    key: 'action',
  },
  {
    title: 'User Name',
    dataIndex: 'userName',
    key: 'userName',
  },
  {
    title: 'Message',
    dataIndex: 'message',
    key: 'message',
    render: (message) => (
      <Typography sx={{ fontSize: '16px' }} variant="subtitle1">
        {message?.split("'")?.map((text: string, index: number) =>
          index % 2 === 0 ? (
            <span key={index}>{text}</span>
          ) : (
            <Typography key={index} sx={{ display: 'inline', fontWeight: 900 }}>
              {text}
            </Typography>
          ),
        )}
      </Typography>
    ),
  },
]

export const TimeLineComponent = ({
  activitesData,
  isFetchingNextPage,
  hasNextPage,
  fetchNextPage,
  sx,
}) => {
  const lastItemRef = useIntersectionObserver<HTMLDivElement>(() => {
    if (!isFetchingNextPage && hasNextPage) fetchNextPage()
  })

  return (
    <Timeline sx={{ padding: 0, margin: 0 }}>
      {activitesData?.map((item, index, items) => (
        <Box
          key={index}
          ref={items.length - 1 === index ? lastItemRef : null}
          sx={{ maxWidth: '550px', ...sx }}
        >
          <TimelineItem
            sx={{
              margin: 2,
              padding: 0,
              '&:before': { display: 'none' },
            }}
          >
            <TimelineSeparator>
              <StyledTimeLineDot>
                <StyledCircleIcon />
              </StyledTimeLineDot>
              {index < activitesData?.length - 1 && (
                <Box
                  sx={{
                    width: '1px',
                    height: '115%',
                    bgcolor: '#12121233',
                    position: 'absolute',
                    top: '25px',
                  }}
                />
              )}
            </TimelineSeparator>
            <TimelineContent sx={{ padding: '6px 8px' }}>
              <Box>
                <Typography variant="subtitle2" sx={{ fontSize: '14px' }}>
                  {moment
                    .utc(item?.timestamp)
                    .local()
                    .format('DD MMM YYYY - hh:mm A')}
                </Typography>
                <Typography sx={{ fontSize: '16px' }} variant="subtitle1">
                  {item?.message
                    ?.split("'")
                    ?.map((text: string, index: number) =>
                      index % 2 === 0 ? (
                        <span key={index}>{text}</span>
                      ) : (
                        <Typography
                          key={index}
                          sx={{ display: 'inline', fontWeight: 900 }}
                        >
                          {text}
                        </Typography>
                      ),
                    )}
                </Typography>
                <Typography
                  style={{
                    display: 'flex',
                    alignItems: 'center',
                    marginTop: '8px',
                  }}
                >
                  <StyledAvatar>
                    {item?.userName?.charAt(0)?.toUpperCase()}
                  </StyledAvatar>
                  <Typography sx={{ fontSize: '13px', fontWeight: 900 }}>
                    {item?.userName}
                  </Typography>
                </Typography>
              </Box>
            </TimelineContent>
          </TimelineItem>
          {isFetchingNextPage && index === items?.length - 1 && hasNextPage && (
            <StyledSpinnerBox>
              <Spinner />
            </StyledSpinnerBox>
          )}
        </Box>
      ))}
    </Timeline>
  )
}

function useIntersectionObserver<T extends HTMLDivElement>(
  callback: () => void,
) {
  const observer = useRef<IntersectionObserver | null>(null)

  const handleObserver = useCallback(
    (node: T) => {
      if (observer?.current) observer?.current?.disconnect()
      observer.current = new IntersectionObserver((entries) => {
        if (entries[0]?.isIntersecting) callback()
      })
      if (node) observer?.current?.observe(node)
    },
    [callback],
  )

  return handleObserver
}
