import { isNarrow } from '../state'
import {
  LogApp,
  LogEntry,
  LogsBody,
  LogsHeader,
  LogsSection,
  LogsTab,
  LogsTabs,
  LogsTitle,
  LogText,
  LogTimestamp,
} from '../styles'
import { update } from '../update'

export interface UnifiedLogLine {
  time: number
  app: string
  text: string
}

type LogFilter = 'all' | 'toes'

const MAX_LOGS = 200

let _filter: LogFilter = 'all'
let _logs: UnifiedLogLine[] = []
let _source: EventSource | undefined

const formatTime = (timestamp: number): string => {
  const d = new Date(timestamp)
  const pad = (n: number) => String(n).padStart(2, '0')
  return `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`
}

const getStatusColor = (status?: number): string | undefined => {
  if (!status) return undefined
  if (status >= 200 && status < 300) return '#22c55e'
  if (status >= 400 && status < 500) return '#f59e0b'
  if (status >= 500) return '#ef4444'
  return undefined
}

function parseLogText(text: string): { method?: string, path?: string, status?: number, rest: string } {
  // Match patterns like "GET /api/time 200" or "200 GET http://... (0ms)"
  const httpMatch = text.match(/^(\d{3})\s+(GET|POST|PUT|DELETE|PATCH)\s+\S+/)
    || text.match(/^(GET|POST|PUT|DELETE|PATCH)\s+(\S+)\s+(\d{3})/)

  if (httpMatch) {
    if (httpMatch[1]?.match(/^\d{3}$/)) {
      return { method: httpMatch[2], status: parseInt(httpMatch[1], 10), rest: text }
    } else {
      return { method: httpMatch[1], path: httpMatch[2], status: parseInt(httpMatch[3]!, 10), rest: text }
    }
  }

  return { rest: text }
}

function LogLineEntry({ log }: { log: UnifiedLogLine }) {
  const parsed = parseLogText(log.text)
  const statusColor = getStatusColor(parsed.status)
  const narrow = isNarrow || undefined
  return (
    <LogEntry narrow={narrow}>
      <LogTimestamp narrow={narrow}>{formatTime(log.time)}</LogTimestamp>
      <LogApp narrow={narrow}>{log.app}</LogApp>
      <LogText style={statusColor ? { color: statusColor } : undefined}>
        {log.text}
      </LogText>
    </LogEntry>
  )
}

const filteredLogs = (): UnifiedLogLine[] =>
  _filter === 'toes' ? _logs.filter(l => l.app === 'toes') : _logs

function setFilter(filter: LogFilter) {
  _filter = filter
  renderLogs()
}

function LogsBodyContent() {
  const logs = filteredLogs()
  return (
    <>
      {logs.length === 0 ? (
        <LogEntry>
          <LogText style={{ color: 'var(--colors-textFaint)' }}>No activity yet</LogText>
        </LogEntry>
      ) : (
        logs.map((log, i) => <LogLineEntry key={i} log={log} />)
      )}
    </>
  )
}

function renderLogs() {
  update('#unified-logs-tabs', <LogsTabsBar />)
  update('#unified-logs-body', <LogsBodyContent />)
  // Auto-scroll after render
  requestAnimationFrame(() => {
    const el = document.getElementById('unified-logs-body')
    if (el) el.scrollTop = el.scrollHeight
  })
}

export function scrollLogsToBottom() {
  requestAnimationFrame(() => {
    const el = document.getElementById('unified-logs-body')
    if (el) el.scrollTop = el.scrollHeight
  })
}

export function initUnifiedLogs() {
  if (_source) return
  _source = new EventSource('/api/system/logs/stream')
  _source.onmessage = e => {
    try {
      const line = JSON.parse(e.data) as UnifiedLogLine
      _logs = [..._logs.slice(-(MAX_LOGS - 1)), line]
      renderLogs()
    } catch {}
  }
}

function LogsTabsBar() {
  return (
    <LogsTabs>
      <LogsTab variant={_filter === 'all' ? 'active' : undefined} onClick={() => setFilter('all')}>All</LogsTab>
      <LogsTab variant={_filter === 'toes' ? 'active' : undefined} onClick={() => setFilter('toes')}>Toes</LogsTab>
    </LogsTabs>
  )
}

export function UnifiedLogs() {
  return (
    <LogsSection>
      <LogsHeader>
        <LogsTitle>Logs</LogsTitle>
        <div id="unified-logs-tabs"><LogsTabsBar /></div>
      </LogsHeader>
      <LogsBody id="unified-logs-body">
        <LogsBodyContent />
      </LogsBody>
    </LogsSection>
  )
}
