import truncateHtml from 'truncate-html'
import { convert } from 'html-to-text'

import { parseCountryField } from './countries.js'
import { formatDate, md } from './formatters.js'
import { ICON_MAP } from './icons.js'

const warningBanner = `<div class="banner warning"><p>${ICON_MAP['alertTriangle']}There are probably spoilers after this banner — this is a warning about them.</p></div>`
const generateAssociatedMediaHTML = (data, isGenre = false) => {
  const sections = [
    { key: 'artists', icon: 'headphones', category: 'music', title: 'Related Artist(s)' },
    { key: 'related_artists', icon: 'headphones', category: 'music', title: 'Related Artist(s)' },
    { key: 'genres', icon: 'headphones', category: 'music', title: 'Related Genre(s)' },
    { key: 'movies', icon: 'film', category: 'movies', title: 'Related Movie(s)' },
    { key: 'shows', icon: 'deviceTvOld', category: 'tv', title: 'Related Show(s)' },
    { key: 'related_shows', icon: 'deviceTvOld', category: 'tv', title: 'Related Show(s)' },
    { key: 'posts', icon: 'article', category: 'article', title: 'Related Post(s)' },
    { key: 'related_books', icon: 'books', category: 'books', title: 'Related Book(s)' }
  ]

  return sections
    .filter(({ key }) => !(isGenre && key === 'artists'))
    .map(({ key, category, icon, title }) => {
      const items = data[key]
      if (!items || items.length === 0) return ''

      return `
        <div class="associated-media">
          <p class="${category}">${ICON_MAP[icon]} ${title}</p>
          <ul>
            ${items
              .map(item => {
                const name = item.name || item.title
                const url = item.url
                const year = item.year ? ` (${item.year})` : ''
                const author = item.author ? ` by ${item.author}` : ''
                const totalPlays = item.total_plays
                  ? ` <strong class="highlight-text">${item.total_plays}</strong> ${item.total_plays === 1 ? 'play' : 'plays'}`
                  : ''
                let listItemContent = name

                if (key === 'artists' || key === 'related_artists') {
                  return `<li><a href="${url}">${name}</a>${totalPlays}</li>`
                } else if (key === 'movies' || key === 'shows' || key === 'related_shows') {
                  listItemContent = `${name}${year}`
                } else if (key === 'related_books') {
                  listItemContent = `${name}${author}`
                }

                return `<li><a href="${url}">${listItemContent}</a></li>`
              })
              .join('')}
          </ul>
        </div>`
    })
    .join('')
}
const generateMediaLinks = (data, type, count = 10) => {
  if (!data || !type) return ''

  const dataSlice = data.slice(0, count)
  if (dataSlice.length === 0) return null

  const buildLink = (item) => {
    switch (type) {
      case 'genre':
        return `<a href="${item['genre_url']}">${item['genre_name']}</a>`
      case 'artist':
        return `<a href="${item['url']}">${item['name']}</a>`
      case 'book':
        return `<a href="${item['url']}">${item['title']}</a>`
      default:
        return ''
    }
  }

  if (dataSlice.length === 1) return buildLink(dataSlice[0])

  const links = dataSlice.map(buildLink)
  const allButLast = links.slice(0, -1).join(', ')
  const last = links[links.length - 1]

  return `${allButLast} and ${last}`
}

export const generateArtistHTML = (artist, globals) => {
  const playLabel = artist?.['total_plays'] === 1 ? 'play' : 'plays'
  const concertsList = artist['concerts']?.length
    ? `<hr />
    <p id="concerts" class="concerts">
      ${ICON_MAP['deviceSpeaker']}
      I've seen this artist live!
    </p>
    <ul>${artist['concerts'].map(generateConcertModal).join('')}</ul>`
    : ''
  const albumsTable = artist['albums']?.length
    ? `<table>
        <tr><th>Album</th><th>Plays</th><th>Year</th></tr>
        ${artist['albums'].map(album => `
          <tr>
            <td>${album['name']}</td>
            <td>${album['total_plays'] || 0}</td>
            <td>${album['release_year']}</td>
          </tr>`).join('')}
      </table>
      <p><em>These are the albums by this artist that are in my collection, not necessarily a comprehensive discography.</em></p>
      `
    : ''

  return `
    <a class="icon-link" href="/music">${ICON_MAP.arrowLeft} Back to music</a>
    <article class="artist-focus">
      <div class="artist-display">
        <img
          srcset="
            ${globals['cdn_url']}${artist['image']}?class=w200&type=webp 200w,
            ${globals['cdn_url']}${artist['image']}?class=w600&type=webp 400w,
            ${globals['cdn_url']}${artist['image']}?class=w800&type=webp 800w
          "
          sizes="(max-width: 450px) 200px,
            (max-width: 850px) 400px,
            800px"
          src="${globals['cdn_url']}${artist['image']}?class=w200&type=webp"
          alt="${artist['name']} / ${artist['country']}"
          loading="eager"
          decoding="async"
          width="200"
          height="200"
        />
        <div class="artist-meta">
          <p class="title"><strong>${artist['name']}</strong></p>
          <p class="sub-meta country">${ICON_MAP['mapPin']} ${parseCountryField(artist['country'])}</p>
          ${artist['favorite'] ? `<p class="sub-meta favorite">${ICON_MAP['heart']} This is one of my favorite artists!</p>` : ''}
          ${artist['tattoo'] ? `<p class="sub-meta tattoo">${ICON_MAP['needle']} I have a tattoo inspired by this artist!</p>` : ''}
          ${artist['total_plays'] ? `<p class="sub-meta"><strong class="highlight-text">${artist['total_plays']} ${playLabel}</strong></p>` : ''}
          <p class="sub-meta">${artist['genre'] ? `<a href="${artist['genre']['url']}">${artist['genre']['name']}</a>` : ''}</p>
        </div>
      </div>
      ${generateAssociatedMediaHTML(artist)}
      ${artist['description'] ? `
        <h2>Overview</h2>
        <div data-toggle-content class="text-toggle-hidden">${md.render(artist['description'])}</div>
        <button data-toggle-button>Show more</button>` : ''
      }
      ${concertsList}
      ${albumsTable}
    </article>
  `
}

export const generateBookHTML = (book, globals) => {
  const alt = `${book['title']}${book['author'] ? ` by ${book['author']}` : ''}`
  const percentage = book['progress'] ? `${book['progress']}%` : ''
  const status = book['status'] === 'finished'
    ? `Finished on <strong class="highlight-text">${formatDate(book['date_finished'])}</strong>`
    : percentage
    ? `<div class="progress-bar-wrapper" title="${percentage}">
        <div style="width:${percentage}" class="progress-bar"></div>
      </div>`
    : ''

  return `
    <a class="icon-link" href="/books">${ICON_MAP['arrowLeft']} Back to books</a>
    <article class="book-focus">
      <div class="book-display">
        <img
          srcset="
            ${globals['cdn_url']}${book['image']}?class=verticalsm&type=webp 200w,
            ${globals['cdn_url']}${book['image']}?class=verticalmd&type=webp 400w,
            ${globals['cdn_url']}${book['image']}?class=verticalbase&type=webp 800w
          "
          sizes="(max-width: 450px) 203px, (max-width: 850px) 406px, 812px"
          src="${globals['cdn_url']}${book['image']}?class=verticalsm&type=webp"
          alt="${alt}"
          loading="lazy"
          decoding="async"
          width="200"
          height="307"
        />
        <div class="book-meta">
          <p class="title"><strong>${book['title']}</strong></p>
          ${book['rating'] ? `<p>${book['rating']}</p>` : ''}
          ${book['author'] ? `<p class="sub-meta">By ${book['author']}</p>` : ''}
          ${book['favorite'] ? `<p class="sub-meta favorite">${ICON_MAP['heart']} This is one of my favorite books!</p>` : ''}
          ${book['tattoo'] ? `<p class="sub-meta tattoo">${ICON_MAP['needle']} I have a tattoo inspired by this book!</p>` : ''}
          ${status ? `<p class="sub-meta">${status}</p>` : ''}
        </div>
      </div>
      ${book['review'] ? `${warningBanner}<h2>My thoughts</h2><p>${book['review']}</p>` : ''}
      ${generateAssociatedMediaHTML(book)}
      <h2>Overview</h2>
      <p>${md.render(book['description'])}</p>
    </article>
  `
}

export const generateGenreHTML = (genre) => {
  const artistCount = genre['artists']?.length || 0
  const connectingWords = artistCount > 1 ? 'artists are' : 'artist is'
  const mediaLinks = generateMediaLinks(genre['artists'], 'artist', 5)

  return `
    <a class="icon-link" href="/music">${ICON_MAP['arrowLeft']} Back to music</a>
    <h2>${genre['name']}</h2>
    <article class="genre-focus">
      ${mediaLinks ? `
        <p>My top <strong class="highlight-text">${genre['name']}</strong> ${connectingWords} ${mediaLinks}. I've listened to <strong class="highlight-text">${genre['total_plays']}</strong> tracks from this genre.</p>
        <hr />` : ''}
      ${generateAssociatedMediaHTML(genre, true)}
      ${genre['description'] ? `
        <h3>Overview</h3>
        <div data-toggle-content class="text-toggle-hidden">
          ${md.render(genre['description'])}
          <p><a href="${genre['wiki_link']}">Continue reading at Wikipedia.</a></p>
          <p><em>Wikipedia content provided under the terms of the <a href="https://creativecommons.org/licenses/by-sa/3.0/">Creative Commons BY-SA license</a>.</em></p>
        </div>
        <button data-toggle-button>Show more</button>` : ''}
    </article>
  `
}

export const generateMetadata = (data, type, globals) => {
  let title = globals['site_name']
  let description = data['description'] || globals['site_description']
  const canonicalUrl = data['url'] ? `${globals['url']}${data['url']}` : globals['url']
  const ogImage = `${globals['cdn_url']}${data['image'] || globals['avatar']}?class=w800`

  description = convert(truncateHtml(md.render(description), 100, {
      byWords: true,
      ellipsis: '...'
    }),
    {
      wordwrap: false,
      selectors: [
        { selector: 'a', options: { ignoreHref: true } },
        { selector: 'h1', options: { uppercase: false } },
        { selector: 'h2', options: { uppercase: false } },
        { selector: 'h3', options: { uppercase: false } },
        { selector: '*', format: 'block' }
      ]
    }).replace(/\s+/g, ' ').trim()

  switch (type) {
    case 'artist':
      title = `Artists / ${data['name']} / ${globals['site_name']}`
      break
    case 'genre':
      title = `Genre / ${data['name']} / ${globals['site_name']}`
      break
    case 'book':
      title = `Books / ${data['title']} by ${data.author} / ${globals['site_name']}`
      break
    case 'movie':
      title = `Movies / ${data['title']} (${data.year}) / ${globals['site_name']}`
      break
    case 'show':
      title = `Shows / ${data['title']} / ${globals['site_name']}`
      break
    default:
      title = `${data['title'] || globals['site_name']}`
  }

  return {
    title,
    description,
    'og:title': title,
    'og:description': description,
    'og:image': ogImage,
    'og:url': canonicalUrl,
    'canonical': canonicalUrl
  }
}

export const generateWatchingHTML = (media, globals, type) => {
  const isShow = type === 'show'
  const label = isShow ? 'show' : 'movie'
  const lastWatched = media['last_watched'] || (isShow && media['episode']?.['last_watched_at'])

  return `
    <a class="icon-link" href="/watching">${ICON_MAP.arrowLeft} Back to watching</a>
    <article class="watching focus">
      <img
        srcset="
          ${globals['cdn_url']}${media['backdrop']}?class=bannersm&type=webp 256w,
          ${globals['cdn_url']}${media['backdrop']}?class=bannermd&type=webp 512w,
          ${globals['cdn_url']}${media['backdrop']}?class=bannerbase&type=webp 1024w
        "
        sizes="(max-width: 450px) 256px,
          (max-width: 850px) 512px,
          1024px"
        src="${globals['cdn_url']}${media['backdrop']}?class=bannersm&type=webp"
        alt="${media['title']} / ${media['year']}"
        class="image-banner"
        loading="eager"
        decoding="async"
        width="256"
        height="180"
      />
      <div class="meta">
        <p class="title"><strong>${media['title']}</strong> (${media['year']})</p>
        ${media['favorite'] ? `<p class="sub-meta favorite">${ICON_MAP['heart']} This is one of my favorite ${label}s!</p>` : ''}
        ${media['tattoo'] ? `<p class="sub-meta tattoo">${ICON_MAP['needle']} I have a tattoo inspired by this ${label}!</p>` : ''}
        ${media['collected'] ? `<p class="sub-meta collected">${ICON_MAP['circleCheck']} This ${label} is in my collection!</p>` : ''}
        ${lastWatched ? `<p class="sub-meta">Last watched on <strong class="highlight-text">${formatDate(lastWatched)}</strong></p>` : ''}
      </div>
      ${media['review'] ? `${warningBanner}<h2>My thoughts</h2><p>${md.render(media['review'])}</p>` : ''}
      ${generateAssociatedMediaHTML(media)}
      ${media['description'] ? `<h2>Overview</h2><p>${md.render(media['description'])}</p>` : ''}
    </article>
  `
}

export const generateConcertModal = (concert) => {
  const venue = concert['venue_name']
    ? concert['venue_latitude'] && concert['venue_longitude']
      ? `<a href="https://www.openstreetmap.org/?mlat=${concert['venue_latitude']}&mlon=${concert['venue_longitude']}#map=18/${concert['venue_latitude']}/${concert['venue_longitude']}">${concert['venue_name_short']}</a>`
      : concert['venue_name_short']
    : ''

  const notesModal = concert['notes']
    ? `<input class="modal-input" id="${concert['id']}" type="checkbox" tabindex="0" />
      <label class="modal-toggle" for="${concert['id']}">${ICON_MAP['infoCircle']}</label>
      <div class="modal-wrapper">
        <div class="modal-body">
          <label class="modal-close" for="${concert['id']}">${ICON_MAP['circleX']}</label>
          <div>
            <h3>Notes</h3>
            ${md.render(concert['notes'])}
          </div>
        </div>
      </div>`
    : ''

  return `
    <li>
      <strong class="highlight-text">${formatDate(concert['date'])}</strong> at ${venue}
      ${notesModal}
    </li>
  `
}