import React, { useEffect, useMemo, useState } from 'react'
import LevelBadge from '../xp/LevelBadge'

const IMAGE_FALLBACK = 'https://files.skinbase.org/default/missing_md.webp'
const AVATAR_FALLBACK = 'https://files.skinbase.org/default/avatar_default.webp'
const numberFormatter = new Intl.NumberFormat(undefined, {
  notation: 'compact',
  maximumFractionDigits: 1,
})

function cx(...parts) {
  return parts.filter(Boolean).join(' ')
}

function formatCount(value) {
  const numeric = Number(value ?? 0)
  if (!Number.isFinite(numeric)) return '0'
  return numberFormatter.format(numeric)
}

function formatRelativeTime(value) {
  if (!value) return ''

  const date = value instanceof Date ? value : new Date(value)
  if (Number.isNaN(date.getTime())) return ''

  const now = new Date()
  const diffMs = date.getTime() - now.getTime()
  const diffSeconds = Math.round(diffMs / 1000)
  const absSeconds = Math.abs(diffSeconds)
  const rtf = new Intl.RelativeTimeFormat(undefined, { numeric: 'auto' })

  if (absSeconds < 60) return rtf.format(diffSeconds, 'second')

  const diffMinutes = Math.round(diffSeconds / 60)
  if (Math.abs(diffMinutes) < 60) return rtf.format(diffMinutes, 'minute')

  const diffHours = Math.round(diffSeconds / 3600)
  if (Math.abs(diffHours) < 24) return rtf.format(diffHours, 'hour')

  const diffDays = Math.round(diffSeconds / 86400)
  if (Math.abs(diffDays) < 7) return rtf.format(diffDays, 'day')

  const diffWeeks = Math.round(diffSeconds / 604800)
  if (Math.abs(diffWeeks) < 5) return rtf.format(diffWeeks, 'week')

  const diffMonths = Math.round(diffSeconds / 2629800)
  if (Math.abs(diffMonths) < 12) return rtf.format(diffMonths, 'month')

  const diffYears = Math.round(diffSeconds / 31557600)
  return rtf.format(diffYears, 'year')
}

function slugify(value) {
  return String(value ?? '')
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-|-$/g, '')
}

function decodeHtml(value) {
  const text = String(value ?? '')
  if (!text.includes('&')) return text

  let decoded = text

  for (let index = 0; index < 3; index += 1) {
    decoded = decoded
      .replace(/&amp;/gi, '&')
      .replace(/&(apos|#39);/gi, "'")
      .replace(/&(acute|#180|#x00B4);/gi, "'")
      .replace(/&(quot|#34);/gi, '"')
      .replace(/&(nbsp|#160);/gi, ' ')

    if (typeof document === 'undefined') {
      break
    }

    const textarea = document.createElement('textarea')
    textarea.innerHTML = decoded
    const nextValue = textarea.value
    if (nextValue === decoded) break
    decoded = nextValue
  }

  return decoded
}

function normalizeContentTypeLabel(value) {
  const raw = decodeHtml(value).trim()
  if (!raw) return ''

  const normalized = raw.toLowerCase()
  const knownLabels = {
    artworks: 'Artwork',
    artwork: 'Artwork',
    wallpapers: 'Wallpaper',
    wallpaper: 'Wallpaper',
    skins: 'Skin',
    skin: 'Skin',
    photography: 'Photography',
    photo: 'Photography',
    photos: 'Photography',
    other: 'Other',
  }

  if (knownLabels[normalized]) {
    return knownLabels[normalized]
  }

  return raw
    .replace(/[-_]+/g, ' ')
    .replace(/\b\w/g, (char) => char.toUpperCase())
}

function getCsrfToken() {
  if (typeof document === 'undefined') return ''
  return document.querySelector('meta[name="csrf-token"]')?.getAttribute('content') || ''
}

function HeartIcon(props) {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" aria-hidden="true" {...props}>
      <path strokeLinecap="round" strokeLinejoin="round" d="M12 20.25c-4.97-3.12-8.25-6.16-8.25-10.03A4.72 4.72 0 0 1 8.5 5.5c1.5 0 2.93.7 3.84 1.92A4.8 4.8 0 0 1 16.18 5.5a4.72 4.72 0 0 1 4.82 4.72c0 3.87-3.28 6.91-8.25 10.03Z" />
    </svg>
  )
}

function DownloadIcon(props) {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" aria-hidden="true" {...props}>
      <path strokeLinecap="round" strokeLinejoin="round" d="M12 3.75v10.5" />
      <path strokeLinecap="round" strokeLinejoin="round" d="m8.25 10.5 3.75 3.75 3.75-3.75" />
      <path strokeLinecap="round" strokeLinejoin="round" d="M4.5 18.75h15" />
    </svg>
  )
}

function ViewIcon(props) {
  return (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" aria-hidden="true" {...props}>
      <path strokeLinecap="round" strokeLinejoin="round" d="M2.25 12s3.75-6.75 9.75-6.75S21.75 12 21.75 12 18 18.75 12 18.75 2.25 12 2.25 12Z" />
      <path strokeLinecap="round" strokeLinejoin="round" d="M12 14.75A2.75 2.75 0 1 0 12 9.25a2.75 2.75 0 0 0 0 5.5Z" />
    </svg>
  )
}

function ActionLink({ href, label, children, onClick }) {
  return (
    <a
      href={href || '#'}
      aria-label={label}
      onClick={onClick}
      className="inline-flex h-10 w-10 items-center justify-center rounded-lg border border-white/10 bg-white/10 text-white/90 shadow-[0_14px_36px_rgba(2,6,23,0.38)] backdrop-blur-md transition duration-200 hover:bg-white/20 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-300/80"
    >
      {children}
    </a>
  )
}

function ActionButton({ label, children, onClick }) {
  return (
    <button
      type="button"
      aria-label={label}
      onClick={onClick}
      className="inline-flex h-10 w-10 items-center justify-center rounded-lg border border-white/10 bg-white/10 text-white/90 shadow-[0_14px_36px_rgba(2,6,23,0.38)] backdrop-blur-md transition duration-200 hover:bg-white/20 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-300/80"
    >
      {children}
    </button>
  )
}

function BadgePill({ className = '', iconClass = '', children }) {
  return (
    <span
      className={cx(
        'inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-[10px] font-semibold uppercase tracking-[0.14em] backdrop-blur-sm ring-1 shadow-[0_8px_24px_rgba(2,6,23,0.28)]',
        className
      )}
    >
      {iconClass ? <i className={iconClass} aria-hidden="true" /> : null}
      {children}
    </span>
  )
}

export default function ArtworkCard({
  artwork,
  variant = 'default',
  compact = false,
  showStats = true,
  showAuthor = true,
  className = '',
  articleClassName = '',
  frameClassName = '',
  mediaClassName = '',
  mediaStyle,
  articleStyle,
  imageClassName = '',
  imageSizes,
  imageSrcSet,
  imageWidth,
  imageHeight,
  loading = 'lazy',
  decoding = 'async',
  fetchPriority,
  onLike,
  showActions = true,
  metricBadge = null,
}) {
  const item = artwork || {}
  const rawAuthor = item.author || item.creator
  const title = decodeHtml(item.title || item.name || 'Untitled artwork')
  const author = decodeHtml(
    (typeof rawAuthor === 'string' ? rawAuthor : rawAuthor?.name)
      || item.author_name
      || item.uname
      || 'Skinbase Artist'
  )
  const username = rawAuthor?.username || item.author_username || item.username || null
  const authorLevel = Number(rawAuthor?.level ?? item.author_level ?? item.creator?.level ?? 0)
  const authorRank = rawAuthor?.rank || item.author_rank || item.creator?.rank || ''
  const image = item.image || item.thumb || item.thumb_url || item.thumbnail_url || IMAGE_FALLBACK
  const avatar = rawAuthor?.avatar_url || rawAuthor?.avatar || item.avatar || item.author_avatar || item.avatar_url || AVATAR_FALLBACK
  const likes = item.likes ?? item.favourites ?? 0
  const views = item.views ?? item.views_count ?? item.view_count ?? 0
  const downloads = item.downloads ?? item.downloads_count ?? item.download_count ?? 0
  const contentType = normalizeContentTypeLabel(
    item.content_type
      || item.content_type_name
      || item.contentType
      || item.contentTypeName
      || item.content_type_slug
      || ''
  )
  const category = decodeHtml(item.category || item.category_name || '')
  const width = Number(item.width ?? 0)
  const height = Number(item.height ?? 0)
  const resolution = decodeHtml(item.resolution || ((width > 0 && height > 0) ? `${width}x${height}` : ''))
  const href = item.url || item.href || (item.id ? `/art/${item.id}/${slugify(title)}` : '#')
  const downloadHref = item.download_url || item.downloadHref || (item.id ? `/download/artwork/${item.id}` : href)
  const cardLabel = `${title} by ${author}`
  const aspectClass = compact ? 'aspect-square' : 'aspect-[4/5]'
  const titleClass = compact ? 'text-[0.96rem]' : 'text-[1rem] sm:text-[1.08rem]'
  const metadataLine = [contentType, category, resolution].filter(Boolean).join(' • ')
  const authorHref = username ? `/@${username}` : null
  const resolvedMetricBadge = metricBadge || item.metric_badge || null
  const relativePublishedAt = useMemo(
    () => formatRelativeTime(item.published_at || item.publishedAt || null),
    [item.published_at, item.publishedAt]
  )
  const initialLiked = Boolean(item.viewer?.is_liked)
  const [liked, setLiked] = useState(initialLiked)
  const [likeCount, setLikeCount] = useState(Number(likes ?? 0) || 0)
  const [likeBusy, setLikeBusy] = useState(false)
  const [downloadBusy, setDownloadBusy] = useState(false)

  useEffect(() => {
    setLiked(Boolean(item.viewer?.is_liked))
    setLikeCount(Number(item.likes ?? item.favourites ?? 0) || 0)
  }, [item.id, item.likes, item.favourites, item.viewer?.is_liked])

  const articleData = useMemo(() => ({
    'data-art-id': item.id ?? undefined,
    'data-art-url': href !== '#' ? href : undefined,
    'data-art-title': title,
    'data-art-img': image,
  }), [href, image, item.id, title])

  const handleLike = async () => {
    if (!item.id || likeBusy) {
      onLike?.(item)
      return
    }

    const nextState = !liked
    setLikeBusy(true)
    setLiked(nextState)
    setLikeCount((current) => Math.max(0, current + (nextState ? 1 : -1)))

    try {
      const response = await fetch(`/api/artworks/${item.id}/like`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'X-CSRF-TOKEN': getCsrfToken(),
        },
        credentials: 'same-origin',
        body: JSON.stringify({ state: nextState }),
      })

      if (!response.ok) {
        throw new Error('like_request_failed')
      }

      onLike?.(item)
    } catch {
      setLiked(!nextState)
      setLikeCount((current) => Math.max(0, current + (nextState ? -1 : 1)))
    } finally {
      setLikeBusy(false)
    }
  }

  const handleDownload = async (event) => {
    event.preventDefault()
    if (!item.id || downloadBusy) return

    setDownloadBusy(true)
    try {
      const link = document.createElement('a')
      link.href = downloadHref
      link.rel = 'noopener noreferrer'
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    } catch {
      window.open(downloadHref, '_blank', 'noopener,noreferrer')
    } finally {
      setDownloadBusy(false)
    }
  }

  if (variant === 'embed') {
    return (
      <article
        className={cx('group overflow-hidden rounded-xl border border-white/[0.08] bg-black/30 transition-colors hover:border-sky-500/30', articleClassName, className)}
        style={articleStyle}
        {...articleData}
      >
        <a
          href={href}
          className="flex gap-3 p-3 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-300/80"
          aria-label={`Open artwork: ${cardLabel}`}
        >
          <div className="h-16 w-20 shrink-0 overflow-hidden rounded-lg bg-white/5">
            <img
              src={image}
              alt={title}
              loading={loading}
              decoding={decoding}
              className="h-full w-full object-cover transition-transform duration-300 group-hover:scale-105"
              onError={(event) => {
                event.currentTarget.src = IMAGE_FALLBACK
              }}
            />
          </div>

          <div className="min-w-0 flex-1">
            <p className="truncate text-sm font-medium text-white/90">{title}</p>
            {showAuthor && (
              <div className="mt-0.5 flex items-center gap-2 text-xs text-slate-400">
                {authorHref ? (
                  <span>
                    by {author} <span className="text-slate-500">@{username}</span>
                  </span>
                ) : (
                  <span>by {author}</span>
                )}
                {authorLevel > 0 ? <LevelBadge level={authorLevel} rank={authorRank} compact /> : null}
              </div>
            )}
            <p className="mt-1 truncate text-[10px] uppercase tracking-wider text-slate-600">
              {contentType || 'Artwork'}
            </p>
          </div>
        </a>
      </article>
    )
  }

  return (
    <article
      className={cx('group relative', articleClassName, className)}
      style={articleStyle}
      {...articleData}
    >
      <div className={cx('relative overflow-hidden rounded-[1.6rem] border border-white/8 bg-slate-950/80 shadow-[0_18px_60px_rgba(2,6,23,0.45)] transition duration-300 ease-out group-hover:-translate-y-1 group-hover:scale-[1.02] group-hover:border-white/14 group-hover:shadow-[0_24px_80px_rgba(8,47,73,0.5)] group-focus-within:-translate-y-1 group-focus-within:scale-[1.02] group-focus-within:border-sky-200/40', frameClassName)}>
        <a
          href={href}
          aria-label={`Open artwork: ${cardLabel}`}
          className="absolute inset-0 z-10 rounded-[inherit] cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-300/80"
        >
          <span className="sr-only">{cardLabel}</span>
        </a>

        <div className={cx('relative overflow-hidden bg-slate-900', aspectClass, mediaClassName)} style={mediaStyle}>
          <div className="absolute inset-0 bg-[radial-gradient(circle_at_top,_rgba(148,163,184,0.28),_transparent_52%),linear-gradient(180deg,rgba(15,23,42,0.08),rgba(15,23,42,0.42))]" />

          <img
            src={image}
            srcSet={imageSrcSet || undefined}
            sizes={imageSizes || undefined}
            alt={title}
            width={imageWidth || undefined}
            height={imageHeight || undefined}
            loading={loading}
            decoding={decoding}
            fetchPriority={fetchPriority || undefined}
            className={cx('h-full w-full object-cover transition duration-500 group-hover:scale-110 group-focus-within:scale-110', imageClassName)}
            onError={(event) => {
              event.currentTarget.src = IMAGE_FALLBACK
            }}
          />

          <div className="pointer-events-none absolute inset-0 bg-gradient-to-t from-black/85 via-black/38 to-transparent opacity-90 transition duration-300 md:opacity-45 md:group-hover:opacity-100 md:group-focus-within:opacity-100" />

          {(resolvedMetricBadge?.label || relativePublishedAt) ? (
            <div className="pointer-events-none absolute inset-x-0 top-0 z-20 flex items-start justify-between gap-3 p-3">
              <div>
                {resolvedMetricBadge?.label ? (
                  <BadgePill className={resolvedMetricBadge.className || 'bg-emerald-500/14 text-emerald-200 ring-emerald-400/30'} iconClass={resolvedMetricBadge.iconClass}>
                    {resolvedMetricBadge.label}
                  </BadgePill>
                ) : null}
              </div>

              {relativePublishedAt ? (
                <BadgePill className="bg-black/45 text-white/75 ring-white/12" iconClass="fa-regular fa-clock text-[10px]">
                  {relativePublishedAt}
                </BadgePill>
              ) : null}
            </div>
          ) : null}

          {showActions && (
            <div className={cx(
              'absolute right-3 z-20 flex translate-y-2 gap-2 opacity-100 transition duration-200 md:opacity-0 md:group-hover:translate-y-0 md:group-hover:opacity-100 md:group-focus-within:translate-y-0 md:group-focus-within:opacity-100',
              relativePublishedAt ? 'top-12' : 'top-3'
            )}>
              <ActionButton label={liked ? 'Unlike artwork' : 'Like artwork'} onClick={handleLike}>
                <HeartIcon className={cx('h-4 w-4 transition-transform duration-200', liked ? 'fill-current text-rose-300' : '', likeBusy ? 'scale-90' : '')} />
              </ActionButton>

              <ActionLink href={downloadHref} label={downloadBusy ? 'Downloading artwork' : 'Download artwork'} onClick={handleDownload}>
                <DownloadIcon className={cx('h-4 w-4', downloadBusy ? 'animate-pulse text-emerald-300' : '')} />
              </ActionLink>

              <ActionLink href={href} label="View artwork">
                <ViewIcon className="h-4 w-4" />
              </ActionLink>
            </div>
          )}

          <div className="pointer-events-none absolute inset-x-0 bottom-0 z-20 bg-gradient-to-t from-black/80 via-black/40 to-transparent p-3 backdrop-blur-[2px] opacity-100 transition-opacity duration-200 md:opacity-0 md:group-hover:opacity-100 md:group-focus-within:opacity-100">
              <h3 className={cx('truncate font-semibold text-white', titleClass)}>
                {title}
              </h3>

              {showAuthor ? (
                <div className="mt-1 flex items-start justify-between gap-3 text-xs text-white/80">
                  <span className="flex min-w-0 items-start gap-3">
                    <img
                      src={avatar}
                      alt={`Avatar of ${author}`}
                      loading="lazy"
                      decoding="async"
                      className="h-9 w-9 shrink-0 rounded-full object-cover"
                      onError={(event) => {
                        event.currentTarget.src = AVATAR_FALLBACK
                      }}
                    />
                    <span className="min-w-0 flex-1">
                      <span className="flex items-center gap-2">
                        <span className="block min-w-0 truncate text-sm font-medium text-white/90">
                          {author}
                          {username && <span className="text-[11px] text-white/60"> @{username}</span>}
                        </span>
                        {authorLevel > 0 ? <LevelBadge level={authorLevel} rank={authorRank} compact className="shrink-0" /> : null}
                      </span>
                      {showStats && metadataLine && (
                        <span className="mt-0.5 block truncate text-[11px] text-white/70">
                          {metadataLine}
                        </span>
                      )}
                    </span>
                  </span>
                </div>
              ) : showStats && metadataLine ? (
                <div className="mt-1 text-[11px] text-white/70">
                  {metadataLine}
                </div>
              ) : null}
          </div>
        </div>
      </div>
    </article>
  )
}
