'use client'

import { useState } from 'react'
import type { AnnotateResponse, AnnotationEntry } from '@/lib/api'
import type { Settings } from '@/types'

interface Sentence {
  text: string
  annotations: AnnotationEntry[]
  startAnnotIdx: number
}

const CHARS_PER_PAGE = 2000

interface Props {
  result: AnnotateResponse
  settings: Settings
}

export default function AnnotationResult({ result, settings }: Props) {
  const [copied, setCopied] = useState<'annotated' | 'replaced' | null>(null)
  const [toggled, setToggled] = useState<Set<number>>(new Set())
  const [page, setPage] = useState(0)

  if (!result.valid || !result.annotation) {
    return (
      <div className="bg-red-50 border border-red-200 rounded-2xl p-5 text-sm text-red-700">
        <span className="font-semibold">Annotation failed: </span>
        {result.reason ?? 'Unknown error.'}
      </div>
    )
  }

  const { marked, annotations } = result.annotation
  const sentences = parseSentences(marked, annotations)
  const pages = groupByChars(sentences, CHARS_PER_PAGE)
  const totalPages = Math.max(1, pages.length)
  const safePage = Math.min(page, totalPages - 1)
  const pageSentences = pages[safePage] ?? []

  const lineHeight =
    settings.displayMode === 'top'
      ? `${settings.emojiSize + 44}px`
      : `${Math.max(32, settings.emojiSize * 1.4)}px`

  function handleCopy(type: 'annotated' | 'replaced') {
    const text =
      type === 'annotated'
        ? buildAnnotatedText(marked, annotations)
        : buildReplacedText(marked, annotations)
    navigator.clipboard.writeText(text).then(() => {
      setCopied(type)
      setTimeout(() => setCopied(null), 2000)
    })
  }

  function handleToggle(globalIdx: number) {
    setToggled((prev) => {
      const next = new Set(prev)
      if (next.has(globalIdx)) next.delete(globalIdx)
      else next.add(globalIdx)
      return next
    })
  }

  return (
    <div className="bg-white/80 dark:bg-black/40 backdrop-blur-md dark:backdrop-blur-xl border border-gray-300 dark:border-white/10 rounded-2xl shadow-md p-6">
      {/* Header */}
      <div className="flex items-center justify-between pb-4 border-b border-gray-300 dark:border-gray-600">
        <p className="text-sm font-bold text-gray-600 dark:text-white uppercase tracking-widest">
          Result
        </p>
        <div className="flex items-center gap-3">
          <CopyButton label="Copy annotated" done={copied === 'annotated'} onClick={() => handleCopy('annotated')} />
          <CopyButton label="Copy replaced" done={copied === 'replaced'} onClick={() => handleCopy('replaced')} />
        </div>
      </div>

      {/* Text */}
      <p className="text-[16px] mt-4" style={{ lineHeight }}>
        {pageSentences.map((sentence, si) => (
          <span key={si}>
            {settings.displayMode === 'top'
              ? renderTop(sentence, settings.emojiSize, si)
              : renderToggle(sentence, settings.emojiSize, toggled, handleToggle, si)}
            {si < pageSentences.length - 1 ? ' ' : ''}
          </span>
        ))}
      </p>

      {/* Pagination — always visible */}
      <div className="flex items-center justify-end gap-4 mt-5 pt-4 border-t border-gray-300 dark:border-gray-600">
        <button
          onClick={() => setPage((p) => Math.max(0, p - 1))}
          disabled={safePage === 0}
          className="px-3 py-1.5 text-[15px] font-semibold text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
        >
          ← Prev
        </button>
        <span className="text-[15px] font-semibold text-gray-600 dark:text-gray-400 tabular-nums">
          {safePage + 1} / {totalPages}
        </span>
        <button
          onClick={() => setPage((p) => Math.min(totalPages - 1, p + 1))}
          disabled={safePage === totalPages - 1}
          className="px-3 py-1.5 text-[15px] font-semibold text-gray-600 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
        >
          Next →
        </button>
      </div>
    </div>
  )
}


function groupByChars(sentences: Sentence[], maxChars: number): Sentence[][] {
  const pages: Sentence[][] = []
  let current: Sentence[] = []
  let count = 0
  for (const s of sentences) {
    const len = s.text.replace(/<\/?span>/g, '').length
    if (current.length > 0 && count + len > maxChars) {
      pages.push(current)
      current = [s]
      count = len
    } else {
      current.push(s)
      count += len
    }
  }
  if (current.length > 0) pages.push(current)
  return pages
}

function parseSentences(marked: string, annotations: AnnotationEntry[]): Sentence[] {
  const parts = marked.split(/(?<=[.!?])\s+/)
  let globalAnnotIdx = 0
  return parts.map((text) => {
    const spanCount = (text.match(/<span>/g) ?? []).length
    const sentence: Sentence = {
      text: text.trim(),
      annotations: annotations.slice(globalAnnotIdx, globalAnnotIdx + spanCount),
      startAnnotIdx: globalAnnotIdx,
    }
    globalAnnotIdx += spanCount
    return sentence
  })
}

function renderTop(
  sentence: Sentence,
  emojiSize: number,
  prefix: number
): React.ReactNode[] {
  const parts = sentence.text.split(/(<span>.*?<\/span>)/g)
  let localIdx = 0
  return parts.map((part, i) => {
    const match = part.match(/^<span>(.*?)<\/span>$/)
    if (match) {
      const word = match[1]
      const emoji = sentence.annotations[localIdx++]?.emojis?.trim() ?? ''
      // Empty emoji → render as plain, unmarked text (no highlight, no emoji slot)
      if (!emoji) return <span key={`${prefix}-${i}`}>{word}</span>
      return (
        <span
          key={`${prefix}-${i}`}
          className="inline-block mx-0.5 text-center"
          style={{ verticalAlign: 'bottom' }}
        >
          <span className="block" style={{ fontSize: emojiSize, lineHeight: 1, marginBottom: -14 }}>
            {emoji}
          </span>
          <span className="bg-yellow-100 dark:bg-yellow-700/50 rounded-sm px-0.5">
            {word}
          </span>
        </span>
      )
    }
    return <span key={`${prefix}-${i}`}>{part}</span>
  })
}

function renderToggle(
  sentence: Sentence,
  emojiSize: number,
  toggled: Set<number>,
  onToggle: (globalIdx: number) => void,
  prefix: number
): React.ReactNode[] {
  const parts = sentence.text.split(/(<span>.*?<\/span>)/g)
  let localIdx = 0
  return parts.map((part, i) => {
    const match = part.match(/^<span>(.*?)<\/span>$/)
    if (match) {
      const word = match[1]
      const globalIdx = sentence.startAnnotIdx + localIdx
      const emoji = sentence.annotations[localIdx++]?.emojis?.trim() ?? ''
      // Empty emoji → render as plain, unmarked text (no highlight, no toggle)
      if (!emoji) return <span key={`${prefix}-${i}`}>{word}</span>
      const isToggled = toggled.has(globalIdx)
      return (
        <button
          key={`${prefix}-${i}`}
          onClick={() => onToggle(globalIdx)}
          title={isToggled ? word : emoji}
          className="inline-block mx-0.5 bg-yellow-100 dark:bg-yellow-700/50 rounded-sm px-0.5 cursor-pointer align-baseline hover:opacity-70 transition-opacity"
        >
          {isToggled ? (
            <span style={{ fontSize: emojiSize }}>{emoji}</span>
          ) : (
            word
          )}
        </button>
      )
    }
    return <span key={`${prefix}-${i}`}>{part}</span>
  })
}

function buildAnnotatedText(marked: string, annotations: AnnotationEntry[]): string {
  const parts = marked.split(/(<span>.*?<\/span>)/g)
  let i = 0
  return parts
    .map((part) => {
      const match = part.match(/^<span>(.*?)<\/span>$/)
      if (match) {
        const emoji = annotations[i++]?.emojis.trim() ?? ''
        // Empty emoji → plain word, no empty [](...) brackets
        return emoji ? `[${match[1]}](${emoji})` : match[1]
      }
      return part
    })
    .join('')
}

function buildReplacedText(marked: string, annotations: AnnotationEntry[]): string {
  const parts = marked.split(/(<span>.*?<\/span>)/g)
  let i = 0
  return parts
    .map((part) => {
      const match = part.match(/^<span>(.*?)<\/span>$/)
      if (match) {
        const emoji = annotations[i++]?.emojis.trim() ?? ''
        // Empty emoji → keep the original word (nothing to replace it with)
        return emoji ? emoji : match[1]
      }
      return part
    })
    .join('')
}

function CopyButton({ label, done, onClick }: { label: string; done: boolean; onClick: () => void }) {
  return (
    <button
      onClick={onClick}
      title={label}
      className="flex items-center gap-1.5 text-[13px] font-semibold text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 transition-colors"
    >
      {done ? <CheckIcon /> : <CopyIcon />}
      <span>{done ? 'Copied!' : label}</span>
    </button>
  )
}

function CopyIcon() {
  return (
    <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24"
      fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <rect width="14" height="14" x="8" y="8" rx="2" ry="2" />
      <path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2" />
    </svg>
  )
}

function CheckIcon() {
  return (
    <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24"
      fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
      <polyline points="20 6 9 17 4 12" />
    </svg>
  )
}
