import { styled, Box } from '@mui/material'
import type { ReactNode } from 'react'

import type { SearchState } from '@/components/base'

const Item = styled(Box)(({ theme: { palette, typography } }) => ({
  padding: '8px 0',
  margin: '0 12px',
  lineHeight: 1.35,
  borderBottom: `1px solid ${palette.divider}`,
  fontSize: '0.875rem',
  fontFamily: typography.fontFamily,
  userSelect: 'text',
  '& .time': {
    color: palette.text.secondary,
  },
  '& .type': {
    display: 'inline-block',
    marginLeft: 8,
    textAlign: 'center',
    borderRadius: 2,
    textTransform: 'uppercase',
    fontWeight: '600',
  },
  '& .type[data-type="error"], & .type[data-type="err"]': {
    color: palette.error.main,
  },
  '& .type[data-type="warning"], & .type[data-type="warn"]': {
    color: palette.warning.main,
  },
  '& .type[data-type="info"], & .type[data-type="inf"]': {
    color: palette.info.main,
  },
  '& .data': {
    color: palette.text.primary,
    overflowWrap: 'anywhere',
  },
  '& .highlight': {
    backgroundColor: palette.mode === 'dark' ? '#ffeb3b40' : '#ffeb3b90',
    borderRadius: 2,
    padding: '0 2px',
  },
}))

interface Props {
  value: ILogItem
  searchState?: SearchState
}

const LogItem = ({ value, searchState }: Props) => {
  const renderHighlightText = (text: string) => {
    if (!searchState?.text.trim()) return text

    try {
      const searchText = searchState.text
      let pattern: string

      if (searchState.useRegularExpression) {
        try {
          new RegExp(searchText)
          pattern = searchText
        } catch {
          pattern = searchText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
        }
      } else {
        const escaped = searchText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
        pattern = searchState.matchWholeWord ? `\\b${escaped}\\b` : escaped
      }

      const flags = searchState.matchCase ? 'g' : 'gi'
      const regex = new RegExp(pattern, flags)
      const elements: ReactNode[] = []
      let lastIndex = 0
      let match: RegExpExecArray | null

      while ((match = regex.exec(text)) !== null) {
        const start = match.index
        const matchText = match[0]

        if (matchText === '') {
          regex.lastIndex += 1
          continue
        }

        if (start > lastIndex) {
          elements.push(text.slice(lastIndex, start))
        }

        elements.push(
          <span key={`highlight-${start}`} className="highlight">
            {matchText}
          </span>,
        )

        lastIndex = start + matchText.length
      }

      if (lastIndex < text.length) {
        elements.push(text.slice(lastIndex))
      }

      return elements.length ? elements : text
    } catch {
      return text
    }
  }

  return (
    <Item>
      <div>
        <span className="time">{renderHighlightText(value.time || '')}</span>
        <span className="type" data-type={value.type.toLowerCase()}>
          {renderHighlightText(value.type)}
        </span>
      </div>
      <div>
        <span className="data">{renderHighlightText(value.payload)}</span>
      </div>
    </Item>
  )
}

export default LogItem
