type MetadataLike = {
  title?: string
  description?: string
  manifest?: string
  alternates?: {
    canonical?: string
    languages?: Record<string, string>
  }
  icons?: {
    icon?: Array<{ url: string; sizes?: string; type?: string }>
    apple?: Array<{ url: string; sizes?: string }>
  }
  openGraph?: {
    title?: string
    description?: string
    url?: string
    siteName?: string
    type?: string
    images?: Array<{ url: string; alt?: string }>
  }
  twitter?: {
    card?: string
    title?: string
    description?: string
    images?: string[]
  }
  robots?: {
    index?: boolean
    follow?: boolean
    nocache?: boolean
    googleBot?: {
      index?: boolean
      follow?: boolean
      noimageindex?: boolean
    }
  }
}

const pushMeta = (
  meta: Array<Record<string, string>>,
  key: string,
  value?: string
) => {
  if (!value) return
  meta.push({ [key]: value })
}

export function metadataToHead(metadata: MetadataLike) {
  const meta: Array<Record<string, string>> = [
    { charSet: 'utf-8' },
    { name: 'viewport', content: 'width=device-width, initial-scale=1' },
  ]
  const links: Array<Record<string, string>> = []

  if (metadata.title) {
    meta.push({ title: metadata.title })
    meta.push({ property: 'og:title', content: metadata.title })
    meta.push({ name: 'twitter:title', content: metadata.title })
  }

  pushMeta(meta, 'name', metadata.description ? 'description' : undefined)
  if (metadata.description) {
    meta.push({ name: 'description', content: metadata.description })
    meta.push({ property: 'og:description', content: metadata.description })
    meta.push({ name: 'twitter:description', content: metadata.description })
  }

  if (metadata.manifest) {
    links.push({ rel: 'manifest', href: metadata.manifest })
  }

  for (const icon of metadata.icons?.icon ?? []) {
    links.push({
      rel: 'icon',
      href: icon.url,
      ...(icon.sizes ? { sizes: icon.sizes } : {}),
      ...(icon.type ? { type: icon.type } : {}),
    })
  }

  for (const icon of metadata.icons?.apple ?? []) {
    links.push({
      rel: 'apple-touch-icon',
      href: icon.url,
      ...(icon.sizes ? { sizes: icon.sizes } : {}),
    })
  }

  if (metadata.alternates?.canonical) {
    links.push({
      rel: 'canonical',
      href: metadata.alternates.canonical,
    })
  }

  for (const [hreflang, href] of Object.entries(
    metadata.alternates?.languages ?? {}
  )) {
    links.push({
      rel: 'alternate',
      hrefLang: hreflang,
      href,
    })
  }

  if (metadata.openGraph?.url) {
    meta.push({ property: 'og:url', content: metadata.openGraph.url })
  }
  if (metadata.openGraph?.siteName) {
    meta.push({ property: 'og:site_name', content: metadata.openGraph.siteName })
  }
  if (metadata.openGraph?.type) {
    meta.push({ property: 'og:type', content: metadata.openGraph.type })
  }
  for (const image of metadata.openGraph?.images ?? []) {
    meta.push({ property: 'og:image', content: image.url })
    if (image.alt) {
      meta.push({ property: 'og:image:alt', content: image.alt })
    }
  }

  if (metadata.twitter?.card) {
    meta.push({ name: 'twitter:card', content: metadata.twitter.card })
  }
  for (const image of metadata.twitter?.images ?? []) {
    meta.push({ name: 'twitter:image', content: image })
  }

  if (metadata.robots) {
    const robots = [
      metadata.robots.index === false ? 'noindex' : 'index',
      metadata.robots.follow === false ? 'nofollow' : 'follow',
      metadata.robots.nocache ? 'nocache' : undefined,
    ]
      .filter(Boolean)
      .join(', ')

    if (robots) {
      meta.push({ name: 'robots', content: robots })
    }

    if (metadata.robots.googleBot) {
      const googleBot = [
        metadata.robots.googleBot.index === false ? 'noindex' : 'index',
        metadata.robots.googleBot.follow === false ? 'nofollow' : 'follow',
        metadata.robots.googleBot.noimageindex ? 'noimageindex' : undefined,
      ]
        .filter(Boolean)
        .join(', ')

      if (googleBot) {
        meta.push({ name: 'googlebot', content: googleBot })
      }
    }
  }

  return {
    meta,
    links,
  }
}
