import { useMemo } from 'react'
import {
  Dialog,
  DialogTitle,
  DialogContent,
  IconButton,
  Box,
} from '@mui/material'
import { Close } from '@mui/icons-material'
import { CopyButton } from '../../components/copy-button/copy-button'
import type { ChatToolFullViewDialogProps } from '../types'
import { styles } from './styles'

interface Token {
  type: 'key' | 'string' | 'number' | 'boolean' | 'null' | 'punctuation'
  value: string
}

const NUMBER_START_REGEX = /^-?\d/

function tokenizeLine(line: string): (Token | string)[] {
  const tokens: (Token | string)[] = []
  let lastIndex = 0
  let match: RegExpExecArray | null

  // First, find all key positions by looking for "...": patterns
  const keyPositions = new Set<number>()
  const keyRegex = /("(?:[^"\\]|\\.)*")\s*:/g
  let keyMatch: RegExpExecArray | null
  while ((keyMatch = keyRegex.exec(line)) !== null) {
    keyPositions.add(keyMatch.index)
  }

  const tokenRegex = // eslint-disable-next-line no-useless-escape
    /"(?:[^"\\]|\\.)*"|\b(?:true|false)\b|\bnull\b|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?|[{}\[\]:,]/g

  while ((match = tokenRegex.exec(line)) !== null) {
    if (match.index > lastIndex) {
      tokens.push(line.slice(lastIndex, match.index))
    }
    const value = match[0]
    if (value.startsWith('"')) {
      if (keyPositions.has(match.index)) {
        tokens.push({ type: 'key', value })
      } else {
        tokens.push({ type: 'string', value })
      }
    } else if (NUMBER_START_REGEX.test(value)) {
      tokens.push({ type: 'number', value })
    } else if (value === 'true' || value === 'false') {
      tokens.push({ type: 'boolean', value })
    } else if (value === 'null') {
      tokens.push({ type: 'null', value })
    } else {
      tokens.push({ type: 'punctuation', value })
    }
    lastIndex = match.index + value.length
  }

  if (lastIndex < line.length) {
    tokens.push(line.slice(lastIndex))
  }

  return tokens
}

export function ChatToolFullViewDialog({
  open,
  onClose,
  title,
  content,
}: ChatToolFullViewDialogProps) {
  const tokenizedLines = useMemo(
    () => content.split('\n').map((line) => tokenizeLine(line)),
    [content],
  )

  return (
    <Dialog
      open={open}
      onClose={onClose}
      sx={styles.fullViewDialog}
      PaperProps={{ sx: styles.fullViewPaper }}
      fullScreen
    >
      <DialogTitle sx={styles.fullViewTitle}>
        {title}
        <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}>
          <CopyButton copyText={content} aria-label='Copy content' />
          <IconButton onClick={onClose} aria-label='close'>
            <Close />
          </IconButton>
        </Box>
      </DialogTitle>
      <DialogContent sx={styles.fullViewDialogContent}>
        <Box component='pre' sx={styles.fullViewPre}>
          {tokenizedLines.map((tokens, i) => (
            <Box component='span' key={i} sx={styles.fullViewLine}>
              {tokens.map((token, j) =>
                typeof token === 'string' ? (
                  token
                ) : (
                  <Box
                    component='span'
                    key={j}
                    sx={
                      styles[`syntaxToken_${token.type}` as keyof typeof styles]
                    }
                  >
                    {token.value}
                  </Box>
                ),
              )}
              {'\n'}
            </Box>
          ))}
        </Box>
      </DialogContent>
    </Dialog>
  )
}
