/**
 * Session-related helpers shared across the CLI/TUI.
 *
 * These are pure functions used by:
 * - the sessions list UI (derive title/summary/preview)
 * - session creation/forking (id generation)
 */

import { stripLeadingFocusFilesBlock } from './focus-files'

function isRecord(value: unknown): value is Record<string, unknown> {
  return value != null && typeof value === 'object' && !Array.isArray(value)
}

function hasRole(
  value: unknown,
  role: string,
): value is Record<string, unknown> & { role: string } {
  return isRecord(value) && String(value.role ?? '') === role
}

export function formatOneLine(text: unknown, maxLen: number): string {
  const s = String(text ?? '')
    .replace(/\s+/g, ' ')
    .trim()
  if (s.length <= maxLen)
    return s
  return `${s.slice(0, Math.max(0, maxLen - 1))}…`
}

function contentToText(content: unknown): string {
  if (typeof content === 'string')
    return content

  if (Array.isArray(content)) {
    const parts = content
      .filter(
        (c): c is Record<string, unknown> =>
          isRecord(c)
          && c.type === 'text'
          && typeof c.text === 'string',
      )
      .map(c => c.text)
    return parts.join(' ')
  }

  if (isRecord(content)) {
    const maybeText = content.text
    if (typeof maybeText === 'string')
      return maybeText
  }

  return ''
}

export function messagePreviewText(message: unknown): string {
  if (!isRecord(message))
    return ''

  const role = String(message.role ?? '')
  if (role === 'user')
    return stripLeadingFocusFilesBlock(contentToText(message.content))
  if (role === 'tool')
    return isRecord(message.result) ? String(message.result.output ?? '') : ''
  if (role === 'assistant') {
    const parts = Array.isArray(message.parts) ? message.parts : []
    const md = parts
      .filter(
        (p): p is Record<string, unknown> =>
          isRecord(p) && p.type === 'markdown',
      )
      .map(p => String(p.markdown ?? ''))
      .join('\n')
    if (md.trim())
      return md
    const status = parts.find(
      (p): p is Record<string, unknown> =>
        isRecord(p) && p.type === 'status',
    )
    return status ? String(status.text ?? '') : ''
  }
  return ''
}

export function deriveSessionTitleFromMessages(
  messages: readonly unknown[],
): string {
  const arr = Array.isArray(messages) ? messages : []
  const firstUser = arr.find(
    m =>
      hasRole(m, 'user')
      && formatOneLine(messagePreviewText(m), 999).length > 0,
  )
  const txt = firstUser ? messagePreviewText(firstUser) : ''
  return formatOneLine(txt || 'New session', 60) || 'New session'
}

export function deriveSessionTitleSuggestionFromMessages(
  messages: readonly unknown[],
): string {
  const base = deriveSessionTitleFromMessages(messages)
  const cleaned = formatOneLine(base, 48)
  if (!cleaned || cleaned.toLowerCase() === 'new session')
    return ''
  return cleaned
}

export function deriveSessionSummaryFromMessages(
  messages: readonly unknown[],
): string {
  const arr = Array.isArray(messages) ? messages : []
  const firstUser = arr.find(
    m =>
      hasRole(m, 'user')
      && formatOneLine(messagePreviewText(m), 999).length > 0,
  )
  const txt = firstUser ? messagePreviewText(firstUser) : ''
  return formatOneLine(txt || 'New session', 120) || 'New session'
}

export function deriveSessionLastUserMessageFromMessages(
  messages: readonly unknown[],
): string {
  const arr = Array.isArray(messages) ? messages : []
  const lastUser = [...arr].reverse().find((m) => {
    if (!hasRole(m, 'user'))
      return false
    return formatOneLine(messagePreviewText(m), 999).length > 0
  })
  return formatOneLine(lastUser ? messagePreviewText(lastUser) : '', 180)
}

export function deriveSessionLastMessagePreviewFromMessages(
  messages: readonly unknown[],
): string {
  const arr = Array.isArray(messages) ? messages : []
  const last = [...arr].reverse().find((m) => {
    if (!isRecord(m))
      return false
    const role = String(m.role ?? '')
    if (
      role !== 'user'
      && role !== 'assistant'
      && role !== 'tool'
      && role !== 'system'
    ) {
      return false
    }
    return formatOneLine(messagePreviewText(m), 999).length > 0
  })
  return formatOneLine(last ? messagePreviewText(last) : '', 180)
}
