'use client'

import { Check, FileImage, ImageIcon, SquarePen, TriangleAlert, X } from 'lucide-react'
import { useMemo, useState } from 'react'
import type { KeyboardEvent } from 'react'
import { FilterPill } from '../components/ui/FilterPill.js'

/**
 * The subset of the `GET /media` item shape the audit needs. `seoScore` is
 * derived server-side by `calculateMediaSeoScore()` in cms-core — the audit
 * never re-scores client-side, so this table can't drift from the SEO drawer
 * or the MCP `validateMediaSEO` tool.
 */
export interface MediaSeoAuditItem {
  id: number | string
  name: string
  type: string
  size: string
  url: string
  format?: string
  altTag?: string
  title?: string
  description?: string
  seoScore?: number
}

export interface MediaSeoAuditProps {
  items: MediaSeoAuditItem[]
  /** Fired when a row / Edit button is activated — opens the item in the Library tab. */
  onEdit: (item: MediaSeoAuditItem) => void
  /** Media fetch error — renders a retryable error state instead of an empty audit. */
  error?: string | null
  onRetry?: () => void
}

type AuditFilter = 'all' | 'alt' | 'title' | 'poor'

const FILTERS: Array<[AuditFilter, string]> = [
  ['all', 'All items'],
  ['alt', 'Missing Alt'],
  ['title', 'Missing Title'],
  ['poor', 'Poor score'],
]

const hasValue = (value?: string): boolean => Boolean(value?.trim())

const itemScore = (item: MediaSeoAuditItem): number => item.seoScore ?? 0

/** Presentational buckets for the score bar/number — score itself comes from cms-core. */
function scoreToneClass(score: number): string {
  if (score >= 80) return 'text-[var(--suc)]'
  if (score >= 30) return 'text-[var(--warn)]'
  return 'text-[var(--err)]'
}

function scoreBarClass(score: number): string {
  if (score >= 80) return 'bg-[var(--suc)]'
  if (score >= 30) return 'bg-[var(--warn)]'
  return 'bg-[var(--err)]'
}

function scoreLabel(score: number): string {
  if (score >= 80) return 'Good'
  if (score >= 55) return 'Fair'
  if (score >= 30) return 'Needs work'
  return 'Poor'
}

function isImageItem(item: MediaSeoAuditItem): boolean {
  return (
    Boolean(item.url) &&
    (item.type?.startsWith('image/') || /\.(avif|gif|jpe?g|png|webp|svg)$/i.test(item.url))
  )
}

function typeLabel(item: MediaSeoAuditItem): string {
  return (item.format ?? item.type ?? '').replace(/^.*\//, '').toUpperCase()
}

function ScoreBar({ score }: { score: number }) {
  return (
    <div className="flex items-center gap-[7px]">
      <div
        role="meter"
        aria-label="SEO score"
        aria-valuenow={score}
        aria-valuemin={0}
        aria-valuemax={100}
        className="h-[5px] w-[60px] overflow-hidden rounded-full bg-[var(--bdr)]"
      >
        <div
          className={`h-full rounded-full motion-safe:transition-[width] motion-safe:duration-300 ${scoreBarClass(score)}`}
          style={{ width: `${score}%` }}
        />
      </div>
      <span
        className={`w-7 text-right text-xs font-semibold tabular-nums ${scoreToneClass(score)}`}
      >
        {score}
      </span>
    </div>
  )
}

function SeoCheck({ set, missTone }: { set: boolean; missTone: 'err' | 'warn' }) {
  if (set) {
    return (
      <span className="inline-flex items-center gap-[3px] rounded-[4px] bg-[var(--suc-l)] px-[7px] py-[2px] text-[11px] font-medium text-[var(--suc)]">
        <Check size={10} aria-hidden />
        Set
      </span>
    )
  }
  const Icon = missTone === 'err' ? X : TriangleAlert
  const tone =
    missTone === 'err'
      ? 'bg-[var(--err-l)] text-[var(--err)]'
      : 'bg-[var(--warn-l)] text-[var(--warn)]'
  return (
    <span
      className={`inline-flex items-center gap-[3px] rounded-[4px] px-[7px] py-[2px] text-[11px] font-medium ${tone}`}
    >
      <Icon size={10} aria-hidden />
      Missing
    </span>
  )
}

function StatCard({
  value,
  label,
  sub,
  toneClass,
}: {
  value: string
  label: string
  sub: string
  toneClass: string
}) {
  return (
    <div className="rounded-[10px] border border-[var(--bdr)] bg-[var(--card)] px-4 py-3.5">
      <div className={`text-[26px] leading-none font-bold tracking-[-0.8px] ${toneClass}`}>
        {value}
      </div>
      <div className="mt-1 text-xs text-[var(--sub)]">{label}</div>
      <div className={`mt-[3px] text-[11px] font-medium ${toneClass}`}>{sub}</div>
    </div>
  )
}

export function MediaSeoAudit({ items, onEdit, error, onRetry }: MediaSeoAuditProps) {
  const [filter, setFilter] = useState<AuditFilter>('all')

  const stats = useMemo(() => {
    const total = items.length
    const missingAlt = items.filter((it) => !hasValue(it.altTag)).length
    const missingTitle = items.filter((it) => !hasValue(it.title)).length
    const missingDesc = items.filter((it) => !hasValue(it.description)).length
    const avgScore =
      total === 0 ? 0 : Math.round(items.reduce((sum, it) => sum + itemScore(it), 0) / total)
    return { total, missingAlt, missingTitle, missingDesc, avgScore }
  }, [items])

  const filtered = useMemo(() => {
    switch (filter) {
      case 'all':
        return items
      case 'alt':
        return items.filter((it) => !hasValue(it.altTag))
      case 'title':
        return items.filter((it) => !hasValue(it.title))
      case 'poor':
        return items.filter((it) => itemScore(it) < 40)
      default: {
        const exhaustive: never = filter
        return exhaustive
      }
    }
  }, [items, filter])

  if (error && items.length === 0) {
    return (
      <div className="min-h-0 flex-1 overflow-y-auto">
        <div
          role="alert"
          className="flex flex-col items-center justify-center rounded-[10px] border border-[var(--bdr)] bg-[var(--card)] px-4 py-14 text-center"
        >
          <TriangleAlert size={24} className="mb-3 text-[var(--err)]" aria-hidden />
          <p className="text-sm font-medium text-[var(--txt)]">Couldn&apos;t load media</p>
          <p className="mt-1 max-w-sm text-xs text-[var(--sub)]">{error}</p>
          {onRetry && (
            <button
              type="button"
              onClick={onRetry}
              className="mt-4 rounded-[7px] border border-[var(--bdr)] bg-[var(--card)] px-3.5 py-1.5 text-[12.5px] font-medium text-[var(--txt)] transition-colors hover:border-[var(--acc)] hover:text-[var(--acc)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none"
            >
              Retry
            </button>
          )}
        </div>
      </div>
    )
  }

  return (
    <div className="min-h-0 flex-1 overflow-y-auto">
      <div className="mb-[18px] grid grid-cols-2 gap-2.5 lg:grid-cols-4">
        <StatCard
          value={`${stats.avgScore}/100`}
          label="Avg SEO Score"
          sub={scoreLabel(stats.avgScore)}
          toneClass={scoreToneClass(stats.avgScore)}
        />
        <StatCard
          value={String(stats.missingAlt)}
          label="Missing Alt Text"
          sub={`${stats.total - stats.missingAlt} have alt text`}
          toneClass={stats.missingAlt > 0 ? 'text-[var(--err)]' : 'text-[var(--suc)]'}
        />
        <StatCard
          value={String(stats.missingTitle)}
          label="Missing Titles"
          sub={`${stats.total - stats.missingTitle} have titles`}
          toneClass={stats.missingTitle > 0 ? 'text-[var(--warn)]' : 'text-[var(--suc)]'}
        />
        <StatCard
          value={String(stats.missingDesc)}
          label="Missing Descriptions"
          sub={`${stats.total - stats.missingDesc} have descriptions`}
          toneClass={stats.missingDesc > 5 ? 'text-[var(--warn)]' : 'text-[var(--sub)]'}
        />
      </div>

      <div className="mb-3 flex flex-wrap items-center gap-2">
        <span className="text-[12.5px] font-medium text-[var(--sub)]">Show:</span>
        {FILTERS.map(([value, label]) => (
          <FilterPill key={value} active={filter === value} onClick={() => setFilter(value)}>
            {label}
          </FilterPill>
        ))}
        <span className="ml-auto text-xs text-[var(--muted)]">
          {filtered.length} item{filtered.length !== 1 ? 's' : ''}
        </span>
      </div>

      <div className="overflow-x-auto rounded-[10px] border border-[var(--bdr)] bg-[var(--card)]">
        {filtered.length === 0 ? (
          <div className="flex flex-col items-center justify-center px-4 py-14 text-center">
            <ImageIcon size={24} className="mb-3 text-[var(--muted)]" aria-hidden />
            <p className="text-sm font-medium text-[var(--txt)]">
              {items.length === 0 ? 'No media to audit' : 'No items match this filter'}
            </p>
            <p className="mt-1 text-xs text-[var(--muted)]">
              {items.length === 0
                ? 'Upload files to the library to see their SEO health here.'
                : 'Try a different filter to see more items.'}
            </p>
          </div>
        ) : (
          // min-w keeps the 7 columns readable; narrow viewports scroll sideways.
          <table className="w-full min-w-[820px] border-collapse" aria-label="Media SEO audit">
            <thead>
              <tr>
                {['File', 'Type', 'Alt Text', 'Title', 'Description', 'SEO Score', 'Action'].map(
                  (heading) => (
                    <th
                      key={heading}
                      scope="col"
                      className={`border-b border-[var(--bdr)] bg-[var(--bg)] px-3 py-2 text-[11px] font-semibold tracking-[0.5px] whitespace-nowrap text-[var(--muted)] uppercase ${
                        heading === 'Action' ? 'text-right' : 'text-left'
                      }`}
                    >
                      {heading}
                    </th>
                  ),
                )}
              </tr>
            </thead>
            <tbody>
              {filtered.map((item) => {
                const score = itemScore(item)
                return (
                  <tr
                    key={item.id}
                    tabIndex={0}
                    onClick={() => onEdit(item)}
                    onKeyDown={(e: KeyboardEvent<HTMLTableRowElement>) => {
                      if (e.target !== e.currentTarget) return
                      if (e.key === 'Enter' || e.key === ' ') {
                        e.preventDefault()
                        onEdit(item)
                      }
                    }}
                    aria-label={`Edit SEO metadata for ${item.name}`}
                    className="cursor-pointer border-b border-[var(--bdr)] transition-colors last:border-b-0 hover:bg-[var(--acc-l)] focus-visible:bg-[var(--acc-l)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none focus-visible:ring-inset"
                  >
                    <td className="px-3 py-[9px] align-middle">
                      <div className="flex items-center gap-2.5">
                        <div className="flex h-[30px] w-[38px] shrink-0 items-center justify-center overflow-hidden rounded-[5px] border border-[var(--bdr)] bg-[var(--bg)]">
                          {isImageItem(item) ? (
                            <img
                              src={item.url}
                              alt=""
                              className="h-full w-full object-cover"
                              loading="lazy"
                            />
                          ) : (
                            <FileImage size={14} className="text-[var(--muted)]" aria-hidden />
                          )}
                        </div>
                        <div className="min-w-0">
                          <div className="max-w-[160px] truncate text-[12.5px] font-medium text-[var(--txt)]">
                            {item.name}
                          </div>
                          <div className="text-[11px] text-[var(--muted)]">{item.size}</div>
                        </div>
                      </div>
                    </td>
                    <td className="px-3 py-[9px] align-middle">
                      <span className="text-[11.5px] font-semibold tracking-[0.3px] text-[var(--sub)] uppercase">
                        {typeLabel(item)}
                      </span>
                    </td>
                    <td className="px-3 py-[9px] align-middle">
                      <SeoCheck set={hasValue(item.altTag)} missTone="err" />
                    </td>
                    <td className="px-3 py-[9px] align-middle">
                      <SeoCheck set={hasValue(item.title)} missTone="warn" />
                    </td>
                    <td className="px-3 py-[9px] align-middle">
                      <SeoCheck set={hasValue(item.description)} missTone="warn" />
                    </td>
                    <td className="px-3 py-[9px] align-middle">
                      <ScoreBar score={score} />
                    </td>
                    <td className="px-3 py-[9px] text-right align-middle">
                      <button
                        type="button"
                        onClick={(e) => {
                          e.stopPropagation()
                          onEdit(item)
                        }}
                        className="inline-flex items-center gap-[5px] rounded-[7px] px-2 py-1 text-[11.5px] text-[var(--sub)] transition-colors hover:bg-[var(--acc-l)] hover:text-[var(--acc)] focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:outline-none"
                      >
                        <SquarePen size={11} aria-hidden />
                        Edit
                      </button>
                    </td>
                  </tr>
                )
              })}
            </tbody>
          </table>
        )}
      </div>
    </div>
  )
}
