import type { KeyboardEvent, ReactNode } from 'react'
import { Inbox, Maximize2, RefreshCw } from 'lucide-react'
import { cn } from '@/lib/cn'

// WidgetCard — dashboard widget container (PURO HomePage widget). A header
// (brand gradient, or an accent-tinted bar) carries the title + optional refresh
// / expand icon-buttons; an optional clickable stat-chip row sits under it; the
// body is `children`, or a muted EmptyState when `empty`. The whole card is
// wrapped with .card-accent so it gets the colored left rail.
//
// Visual idiom from pages/hrm/EmployeesListPage.tsx + index.css: .card-accent
// (rail via --accent), .app-gradient-brand (gradient surface), .icon-chip, and
// the stat-chip treatment. Accent palettes ship stops 50/100/500/600/700 only
// (no -800).
//
// gotcha 66: index.css declares `h1,h2,h3,h4 { color:#0b1220 }` OUTSIDE any
// @layer, so in Tailwind v4 it beats `text-white`. The brand-gradient header
// uses an <h3>, therefore its title MUST be `text-white!` (with the important
// bang) — plain `text-white` would render dark ink on the gradient. Accent
// (non-brand) headers sit on a light tinted bar and use the accent ink instead.
export type Accent = 'brand' | 'teal' | 'violet' | 'amberx' | 'greenx'

export type WidgetStat = {
  label: string
  value: number | string
  onClick?: () => void
}

type AccentTokens = {
  rail: string
  chipBg: string
  chipFg: string
  head: string
  headBar: string
  statValue: string
}

// rail = value for --accent on .card-accent; headBar = light tinted header bg
// used for non-brand accents (brand uses the gradient instead).
const ACCENT: Record<Accent, AccentTokens> = {
  brand: { rail: 'var(--color-brand-500)', chipBg: 'var(--color-brand-50)', chipFg: 'var(--color-brand-600)', head: 'text-brand-800', headBar: 'bg-brand-50', statValue: 'text-brand-800' },
  teal: { rail: 'var(--color-teal-500)', chipBg: 'var(--color-teal-50)', chipFg: 'var(--color-teal-700)', head: 'text-teal-700', headBar: 'bg-teal-50', statValue: 'text-teal-700' },
  violet: { rail: 'var(--color-violet-500)', chipBg: 'var(--color-violet-50)', chipFg: 'var(--color-violet-700)', head: 'text-violet-700', headBar: 'bg-violet-50', statValue: 'text-violet-700' },
  amberx: { rail: 'var(--color-amberx-500)', chipBg: 'var(--color-amberx-50)', chipFg: 'var(--color-amberx-700)', head: 'text-amberx-700', headBar: 'bg-amberx-50', statValue: 'text-amberx-700' },
  greenx: { rail: 'var(--color-greenx-500)', chipBg: 'var(--color-greenx-50)', chipFg: 'var(--color-greenx-700)', head: 'text-greenx-700', headBar: 'bg-greenx-50', statValue: 'text-greenx-700' },
}

export function WidgetCard({
  title,
  icon,
  accent = 'brand',
  stats,
  onExpand,
  onRefresh,
  children,
  empty = false,
  emptyText = 'Chưa có dữ liệu.',
  className,
}: {
  /** Widget title (rendered in the header). */
  title: string
  /** Optional lucide icon node shown before the title. */
  icon?: ReactNode
  /** Accent colour — brand uses the gradient header, others a tinted bar. */
  accent?: Accent
  /** Optional clickable stat chips rendered under the header. */
  stats?: WidgetStat[]
  /** When set, shows an expand icon-button in the header. */
  onExpand?: () => void
  /** When set, shows a refresh icon-button in the header. */
  onRefresh?: () => void
  /** Widget body. Ignored when `empty` is true. */
  children?: ReactNode
  /** Render the empty state instead of children. */
  empty?: boolean
  /** Message for the empty state. */
  emptyText?: string
  className?: string
}) {
  const a = ACCENT[accent]
  const isBrand = accent === 'brand'

  return (
    <section
      className={cn('card-accent flex min-w-0 flex-col overflow-hidden', className)}
      style={{ ['--accent' as string]: a.rail }}
    >
      {/* ===== Header ===== brand = gradient (white text, gotcha 66), else tinted bar */}
      <header
        className={cn(
          'flex items-center justify-between gap-2 px-4 py-2.5',
          isBrand ? 'app-gradient-brand text-white' : cn(a.headBar, 'border-b border-slate-100'),
        )}
      >
        <div className="flex min-w-0 items-center gap-2">
          {icon && (
            <span
              className={cn(
                'inline-flex h-7 w-7 shrink-0 items-center justify-center rounded-lg',
                isBrand ? 'bg-white/15 text-white ring-1 ring-white/25' : 'icon-chip',
              )}
              style={isBrand ? undefined : { ['--chip-bg' as string]: a.chipBg, ['--chip-fg' as string]: a.chipFg }}
              aria-hidden
            >
              {icon}
            </span>
          )}
          {/* gotcha 66: gradient header → text-white! (important) so the
              unlayered h1-h4 dark rule does not win. */}
          <h3 className={cn('truncate text-sm font-semibold tracking-tight', isBrand ? 'text-white!' : a.head)}>
            {title}
          </h3>
        </div>
        {(onRefresh || onExpand) && (
          <div className="flex shrink-0 items-center gap-0.5">
            {onRefresh && (
              <IconButton onClick={onRefresh} label={`Làm mới ${title}`} onGradient={isBrand}>
                <RefreshCw className="h-3.5 w-3.5" />
              </IconButton>
            )}
            {onExpand && (
              <IconButton onClick={onExpand} label={`Mở rộng ${title}`} onGradient={isBrand}>
                <Maximize2 className="h-3.5 w-3.5" />
              </IconButton>
            )}
          </div>
        )}
      </header>

      {/* ===== Stat-chip row ===== */}
      {stats && stats.length > 0 && (
        <div className="flex flex-wrap gap-2 border-b border-slate-100 bg-slate-50/50 px-4 py-3">
          {stats.map((s, i) => (
            <StatChip key={i} stat={s} valueClass={a.statValue} />
          ))}
        </div>
      )}

      {/* ===== Body / EmptyState ===== */}
      <div className="min-h-0 flex-1 p-4">
        {empty ? (
          <div className="flex flex-col items-center justify-center gap-2 py-8 text-center">
            <span
              className="icon-chip"
              style={{ ['--chip-bg' as string]: '#f1f5f9', ['--chip-fg' as string]: '#94a3b8' }}
              aria-hidden
            >
              <Inbox className="h-4 w-4" />
            </span>
            <p className="text-xs text-slate-500">{emptyText}</p>
          </div>
        ) : (
          children
        )}
      </div>
    </section>
  )
}

// Small clickable stat — value + label. Falls back to an inert div when no
// onClick (no button affordance, no focus ring).
function StatChip({ stat, valueClass }: { stat: WidgetStat; valueClass: string }) {
  const clickable = !!stat.onClick

  function handleKeyDown(e: KeyboardEvent<HTMLDivElement>) {
    if (!stat.onClick) return
    if (e.key === 'Enter' || e.key === ' ') {
      e.preventDefault()
      stat.onClick()
    }
  }

  return (
    <div
      role={clickable ? 'button' : undefined}
      tabIndex={clickable ? 0 : undefined}
      onClick={stat.onClick}
      onKeyDown={handleKeyDown}
      className={cn(
        'min-w-[5rem] rounded-lg border border-slate-200 bg-white px-2.5 py-1.5 text-left transition',
        clickable &&
          'cursor-pointer hover:border-brand-300 hover:bg-brand-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand-500 focus-visible:ring-offset-1 focus-visible:ring-offset-white',
      )}
    >
      <div className={cn('stat-value text-lg', valueClass)}>{stat.value}</div>
      <div className="label-eyebrow mt-0.5 truncate">{stat.label}</div>
    </div>
  )
}

// Header icon-button — adapts contrast to the gradient vs tinted header.
function IconButton({
  onClick,
  label,
  onGradient,
  children,
}: {
  onClick: () => void
  label: string
  onGradient: boolean
  children: ReactNode
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      aria-label={label}
      title={label}
      className={cn(
        'inline-flex h-7 w-7 items-center justify-center rounded-lg transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1',
        onGradient
          ? 'text-white/80 hover:bg-white/15 hover:text-white focus-visible:ring-white/70 focus-visible:ring-offset-transparent'
          : 'text-slate-400 hover:bg-slate-100 hover:text-slate-700 focus-visible:ring-brand-500 focus-visible:ring-offset-white',
      )}
    >
      {children}
    </button>
  )
}
