import { define } from 'forge'
import { theme } from './theme'

// Code block container
const CodeBlock = define('CodeBlock', {
  fontFamily: 'monospace',
  fontSize: '13px',
  lineHeight: 1.5,
  color: theme('syntax-text'),
})

// Syntax token spans
const TagToken = define('TagToken', {
  base: 'span',
  color: theme('syntax-tag'),
  fontWeight: 600,
})

const AttrToken = define('AttrToken', {
  base: 'span',
  color: theme('syntax-attr'),
})

const StringToken = define('StringToken', {
  base: 'span',
  color: theme('syntax-string'),
})

const NumberToken = define('NumberToken', {
  base: 'span',
  color: theme('syntax-number'),
})

const BraceToken = define('BraceToken', {
  base: 'span',
  color: theme('syntax-brace'),
  fontWeight: 600,
})

const TextToken = define('TextToken', {
  base: 'span',
  color: theme('syntax-text'),
})

// Code examples container
const CodeExamplesBox = define('CodeExamplesBox', {
  background: theme('colors-bgElevated'),
  padding: theme('spacing-4'),
  borderRadius: theme('radius-lg'),
  border: `1px solid ${theme('colors-border')}`,
  display: 'flex',
  flexDirection: 'column',
  gap: theme('spacing-2'),
})

type CodeProps = {
  children: string
}

// Lightweight JSX syntax highlighter
export const Code = ({ children }: CodeProps) => {
  const tokens = tokenizeJSX(children)

  return (
    <CodeBlock>
      {tokens.map((token, i) => {
        if (token.type === 'tag') {
          return <TagToken key={i}>{token.value}</TagToken>
        }
        if (token.type === 'attr') {
          return <AttrToken key={i}>{token.value}</AttrToken>
        }
        if (token.type === 'string') {
          return <StringToken key={i}>{token.value}</StringToken>
        }
        if (token.type === 'number') {
          return <NumberToken key={i}>{token.value}</NumberToken>
        }
        if (token.type === 'brace') {
          return <BraceToken key={i}>{token.value}</BraceToken>
        }
        return <TextToken key={i}>{token.value}</TextToken>
      })}
    </CodeBlock>
  )
}

type CodeExamplesProps = {
  examples: string[]
}

// Container for multiple code examples
export const CodeExamples = ({ examples }: CodeExamplesProps) => {
  return (
    <CodeExamplesBox class="code-examples-container">
      {examples.map((example, i) => (
        <Code key={i}>{example}</Code>
      ))}
    </CodeExamplesBox>
  )
}

type Token = {
  type: 'tag' | 'attr' | 'string' | 'number' | 'brace' | 'text'
  value: string
}

function tokenizeJSX(code: string): Token[] {
  const tokens: Token[] = []
  let i = 0

  while (i < code.length) {
    // Match opening/closing tags: < or </
    if (code[i] === '<') {
      i++

      // Check for closing tag
      if (code[i] === '/') {
        tokens.push({ type: 'tag', value: '</' })
        i++
      } else {
        tokens.push({ type: 'tag', value: '<' })
      }

      // Get tag name
      let tagName = ''
      while (i < code.length && /[A-Za-z0-9.]/.test(code[i]!)) {
        tagName += code[i]
        i++
      }
      if (tagName) {
        tokens.push({ type: 'tag', value: tagName })
      }

      // Parse attributes inside the tag
      while (i < code.length && code[i] !== '>') {
        // Skip whitespace
        if (/\s/.test(code[i]!)) {
          tokens.push({ type: 'text', value: code[i]! })
          i++
          continue
        }

        // Check for self-closing /
        if (code[i] === '/' && code[i + 1] === '>') {
          tokens.push({ type: 'tag', value: ' />' })
          i += 2
          break
        }

        // Parse attribute name
        let attrName = ''
        while (i < code.length && /[a-zA-Z0-9-]/.test(code[i]!)) {
          attrName += code[i]
          i++
        }
        if (attrName) {
          tokens.push({ type: 'attr', value: attrName })
        }

        // Check for =
        if (code[i] === '=') {
          tokens.push({ type: 'text', value: '=' })
          i++

          // Parse attribute value
          if (code[i] === '"') {
            // String value
            let str = '"'
            i++
            while (i < code.length && code[i] !== '"') {
              str += code[i]
              i++
            }
            if (code[i] === '"') {
              str += '"'
              i++
            }
            tokens.push({ type: 'string', value: str })
          } else if (code[i] === '{') {
            // Brace value
            tokens.push({ type: 'brace', value: '{' })
            i++

            // Get content inside braces
            let content = ''
            let depth = 1
            while (i < code.length && depth > 0) {
              if (code[i] === '{') depth++
              if (code[i] === '}') {
                depth--
                if (depth === 0) break
              }
              content += code[i]
              i++
            }

            // Check if content is a number
            if (/^\d+$/.test(content)) {
              tokens.push({ type: 'number', value: content })
            } else {
              tokens.push({ type: 'text', value: content })
            }

            if (code[i] === '}') {
              tokens.push({ type: 'brace', value: '}' })
              i++
            }
          }
        }
      }

      // Closing >
      if (code[i] === '>') {
        tokens.push({ type: 'tag', value: '>' })
        i++
      }
    } else {
      // Regular text
      let text = ''
      while (i < code.length && code[i] !== '<') {
        text += code[i]
        i++
      }
      if (text) {
        tokens.push({ type: 'text', value: text })
      }
    }
  }

  return tokens
}
