import { getSectionType, type PageSection } from '@actuate-media/cms-core/page-sections'
import { analyzeContent } from '@actuate-media/cms-core/seo/analysis'

const HTML_LIKE = /<\/?[a-z][\s\S]*>/i

/** Build an HTML-ish string from editor sections (+ optional post body) for SEO analysis. */
export function buildEditorContentHtml(sections: PageSection[], body = ''): string {
  const parts: string[] = []
  if (body.trim()) parts.push(body)
  for (const section of sections) {
    if (section.visible === false) continue
    const chunk = extractSectionContentHtml(section)
    if (chunk) parts.push(chunk)
  }
  return parts.join('\n')
}

/** Live 0–100 SEO score from the current in-editor document state. */
export function computeLiveSeoScore(input: {
  title: string
  slug: string
  seoTitle: string
  seoDescription: string
  focusKeyword?: string
  sections: PageSection[]
  bodyHtml?: string
}): number {
  const content = buildEditorContentHtml(input.sections, input.bodyHtml ?? '')
  return analyzeContent({
    title: input.title,
    slug: input.slug,
    content,
    metaTitle: input.seoTitle,
    metaDescription: input.seoDescription,
    focusKeyphrase: input.focusKeyword,
  }).score
}

function extractSectionContentHtml(section: PageSection): string {
  const content = section.content
  if (!content || typeof content !== 'object') return ''
  const def = getSectionType(section.sectionType)
  const chunks: string[] = []

  if (def) {
    for (const field of def.fields) {
      const val = content[field.key]
      if (typeof val !== 'string' || !val.trim()) continue
      if (field.type === 'richText' || HTML_LIKE.test(val)) {
        chunks.push(val)
      } else if (/heading|title|subtitle|eyebrow/i.test(field.key)) {
        chunks.push(`<h2>${escapeHtml(val.trim())}</h2>`)
      } else if (/body|content|text|copy|description|excerpt|quote|answer/i.test(field.key)) {
        chunks.push(`<p>${escapeHtml(val.trim())}</p>`)
      }
    }
  } else {
    collectStringValues(content, chunks, 0)
  }

  return chunks.join('\n')
}

function collectStringValues(obj: Record<string, unknown>, chunks: string[], depth: number): void {
  if (depth > 6) return
  for (const value of Object.values(obj)) {
    if (typeof value === 'string' && value.trim()) {
      chunks.push(HTML_LIKE.test(value) ? value : `<p>${escapeHtml(value.trim())}</p>`)
    } else if (Array.isArray(value)) {
      for (const item of value) {
        if (item && typeof item === 'object') {
          collectStringValues(item as Record<string, unknown>, chunks, depth + 1)
        }
      }
    } else if (value && typeof value === 'object') {
      collectStringValues(value as Record<string, unknown>, chunks, depth + 1)
    }
  }
}

function escapeHtml(text: string): string {
  return text
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
}

const STOP_WORDS = new Set([
  'about',
  'after',
  'also',
  'been',
  'before',
  'being',
  'between',
  'both',
  'could',
  'each',
  'from',
  'have',
  'into',
  'more',
  'most',
  'other',
  'over',
  'some',
  'such',
  'than',
  'that',
  'their',
  'them',
  'then',
  'there',
  'these',
  'they',
  'this',
  'through',
  'under',
  'very',
  'were',
  'what',
  'when',
  'where',
  'which',
  'while',
  'with',
  'would',
  'your',
])

/** Top content words for the Insights accordion (excluding common stop words). */
export function prominentWordsFromText(plainText: string, limit = 8): string[] {
  const counts = new Map<string, number>()
  for (const raw of plainText.toLowerCase().split(/\s+/)) {
    const word = raw.replace(/[^a-z0-9'-]/g, '')
    if (word.length < 4 || STOP_WORDS.has(word)) continue
    counts.set(word, (counts.get(word) ?? 0) + 1)
  }
  return [...counts.entries()]
    .sort((a, b) => b[1] - a[1])
    .slice(0, limit)
    .map(([word]) => word)
}
