import i18next from 'i18next'
import { formatDate, formatDuration, formatItemDuration } from '../utils/dateFormatter.js'
import { useSaveFilePrompt } from './useSaveFilePrompt.js'

function escHtml(str) {
  return String(str ?? '')
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
}

function enrichItemsWithTiming(log) {
  const items = log.items || []
  return items.map((item, i) => {
    const curr = item.timestamp ? new Date(item.timestamp).getTime() : null
    const prev =
      i === 0
        ? log.started_at
          ? new Date(log.started_at).getTime()
          : null
        : items[i - 1].timestamp
          ? new Date(items[i - 1].timestamp).getTime()
          : null
    return { ...item, duration_ms: curr && prev ? curr - prev : null }
  })
}

function groupItems(items) {
  if (!items || items.length === 0) return []
  const result = []
  const comboMap = {}
  for (const item of items) {
    if (!item.combo_id) {
      result.push({ type: 'exercise', item })
    } else {
      if (!comboMap[item.combo_id]) {
        comboMap[item.combo_id] = {
          type: 'combo',
          combo_id: item.combo_id,
          combo_title: item.combo_title,
          exercises: [],
        }
        result.push(comboMap[item.combo_id])
      }
      comboMap[item.combo_id].exercises.push(item)
    }
  }
  return result
}

function comboRounds(group) {
  const hasRounds = group.exercises.some((ex) => ex.round_number != null)
  if (!hasRounds) return [group.exercises]
  const map = {}
  for (const ex of group.exercises) {
    const rn = ex.round_number ?? 0
    if (!map[rn]) map[rn] = []
    map[rn].push(ex)
  }
  return Object.entries(map)
    .sort(([a], [b]) => Number(a) - Number(b))
    .map(([, exes]) => exes)
}

function itemParens(item) {
  const parts = [item.reps_done, item.weight_used]
  const dur = formatItemDuration(item.duration_ms)
  if (dur) parts.push(dur)
  return `(${parts.join(',')})`
}

function renderSessionItemsHtml(log) {
  const groups = groupItems(enrichItemsWithTiming(log))
  if (!groups.length) return ''
  return groups
    .map((group, gi) => {
      const sep = gi > 0 ? ', ' : ''
      if (group.type === 'exercise') {
        return `${sep}${escHtml(group.item.exercise_title)} ${escHtml(itemParens(group.item))}`
      }
      const rounds = comboRounds(group)
      const roundsHtml = rounds
        .map((round, ri) => {
          const exsHtml = round
            .map((ex, ei) => {
              const sep2 = ri > 0 || ei > 0 ? ', ' : ''
              return `${sep2}${escHtml(ex.exercise_title)} ${escHtml(itemParens(ex))}`
            })
            .join('')
          return ri > 0 ? ` // ${exsHtml}` : exsHtml
        })
        .join('')
      return `${sep}${escHtml(group.combo_title)} ×${rounds.length} : <em>{${roundsHtml}}</em>`
    })
    .join('')
}

async function fetchIconAsBase64() {
  try {
    // Resolve against BASE_URL so subdirectory deploys (base: './') still find the icon
    const res = await fetch(import.meta.env.BASE_URL + 'icon.svg')
    if (!res.ok) return null
    const text = await res.text()
    const bytes = new TextEncoder().encode(text)
    const binStr = Array.from(bytes, (b) => String.fromCharCode(b)).join('')
    return `data:image/svg+xml;base64,${btoa(binStr)}`
  } catch {
    return null
  }
}

async function downloadHtml(defaultFilename, html) {
  const { promptFilename } = useSaveFilePrompt()
  const filename = await promptFilename(defaultFilename)
  if (!filename) return

  const blob = new Blob([html], { type: 'text/html' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = filename
  a.click()
  URL.revokeObjectURL(url)
}

export function useHtmlExport() {
  async function exportHomeAsHtml({
    count7Days,
    count30Days,
    recentSessions,
    historyByDay,
    historyFrom,
    historyTo,
  }) {
    const lang = i18next.language || 'en'
    const t = i18next.t.bind(i18next)
    const iconDataUrl = await fetchIconAsBase64()
    const exportDate = formatDate(new Date(), lang)

    const iconHtml = iconDataUrl
      ? `<img src="${iconDataUrl}" alt="TrainUs" class="app-icon" />`
      : ''

    const recentHtml = recentSessions
      .map((log) => {
        const duration = formatDuration(log.started_at, log.finished_at)
        const date = formatDate(log.started_at, lang)
        const itemsLine = renderSessionItemsHtml(log)
        return `
        <div class="card">
          <div class="session-header">
            <span class="session-title">${escHtml(log.session_title)}</span>
            <span class="session-meta">
              <span class="session-date">${escHtml(date)}</span>
              ${duration ? `<span class="session-duration">&#x23F1; ${escHtml(duration)}</span>` : ''}
            </span>
          </div>
          ${itemsLine ? `<div class="session-items">${itemsLine}</div>` : ''}
        </div>`
      })
      .join('')

    const historyHtml = historyByDay
      .map(({ day, logs }) => {
        const dayLabel = formatDate(day, lang)
        const logsHtml = logs
          .map((log) => {
            const duration = formatDuration(log.started_at, log.finished_at)
            const itemsLine = renderSessionItemsHtml(log)
            return `
            <div class="card card--sm">
              <div class="session-header session-header--sm">
                <span class="history-title">${escHtml(log.session_title)}</span>
                ${duration ? `<span class="session-duration">&#x23F1; ${escHtml(duration)}</span>` : ''}
              </div>
              ${itemsLine ? `<div class="session-items session-items--sm">${itemsLine}</div>` : ''}
            </div>`
          })
          .join('')
        return `<div class="history-day"><h4 class="history-day-label">${escHtml(dayLabel)}</h4>${logsHtml}</div>`
      })
      .join('')

    const html = `<!DOCTYPE html>
<html lang="${escHtml(lang)}">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>TrainUs</title>
  <style>
    *, *::before, *::after { box-sizing: border-box; }
    body { margin: 0 auto; padding: 24px 16px; font-family: Helvetica, sans-serif; color: #1a1a1a; background: #fff; max-width: 800px; }
    h1, h2, h3, h4 { margin: 0; padding: 0; }
    .app-header { display: flex; align-items: center; gap: 12px; margin-bottom: 4px; }
    .app-icon { width: 36px; height: 36px; }
    .app-name { font-size: 22px; font-weight: 700; }
    .export-meta { font-size: 12px; color: #555; margin-bottom: 24px; }
    .stats-cards { display: flex; gap: 16px; margin-bottom: 24px; }
    .stat-card { flex: 1; display: flex; flex-direction: column; align-items: center; padding: 16px; border-radius: 8px; background: #f5f5f5; border: 1px solid #ddd; }
    .stat-value { font-size: 32px; font-weight: 700; color: #2563eb; }
    .stat-label { font-size: 13px; color: #555; text-align: center; margin-top: 4px; }
    .section-title { font-size: 16px; font-weight: 600; margin-bottom: 10px; }
    .recent-section { margin-bottom: 28px; }
    .history-section { margin-bottom: 20px; }
    .history-header { display: flex; align-items: baseline; gap: 10px; margin-bottom: 10px; }
    .history-range { font-size: 12px; color: #555; }
    .card { background: #f5f5f5; border: 1px solid #ddd; border-radius: 8px; padding: 16px; margin-bottom: 8px; }
    .card--sm { padding: 10px 16px; }
    .session-header { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
    .session-header--sm { margin-bottom: 4px; }
    .session-title { flex: 1; font-size: 15px; font-weight: 600; }
    .history-title { flex: 1; font-size: 14px; font-weight: 600; }
    .session-meta { display: flex; align-items: center; gap: 8px; flex-shrink: 0; }
    .session-date { font-size: 13px; color: #555; white-space: nowrap; }
    .session-duration { font-size: 12px; color: #555; white-space: nowrap; }
    .session-items { font-size: 13px; color: #1a1a1a; line-height: 1.6; }
    .session-items--sm { font-size: 12px; }
    .history-day { margin-bottom: 16px; }
    .history-day-label { font-size: 13px; font-weight: 600; color: #555; margin-bottom: 6px; text-transform: uppercase; letter-spacing: 0.04em; }
  </style>
</head>
<body>
  <div class="app-header">
    ${iconHtml}
    <span class="app-name">TrainUs</span>
  </div>
  <p class="export-meta">${escHtml(t('home.exportedOn', { date: exportDate }))}</p>

  <div class="stats-cards">
    <div class="stat-card">
      <span class="stat-value">${count7Days}</span>
      <span class="stat-label">${escHtml(t('home.sessionsLast7Days'))}</span>
    </div>
    <div class="stat-card">
      <span class="stat-value">${count30Days}</span>
      <span class="stat-label">${escHtml(t('home.sessionsLast30Days'))}</span>
    </div>
  </div>

  ${
    recentSessions.length > 0
      ? `<div class="recent-section">
    <h3 class="section-title">${escHtml(t('home.recentSessions'))}</h3>
    ${recentHtml}
  </div>`
      : ''
  }

  ${
    historyByDay.length > 0
      ? `<div class="history-section">
    <div class="history-header">
      <h3 class="section-title">${escHtml(t('home.history'))}</h3>
      <span class="history-range">${escHtml(historyFrom)} – ${escHtml(historyTo)}</span>
    </div>
    ${historyHtml}
  </div>`
      : ''
  }
</body>
</html>`

    const date = new Date().toISOString().slice(0, 10)
    await downloadHtml(`trainus-home-${date}.html`, html)
  }

  return { exportHomeAsHtml }
}
