import * as React from 'react'
import { cva, type VariantProps } from 'class-variance-authority'
import { XIcon } from 'lucide-react'

import { cn } from './utils'

const alertVariants = cva(
  'relative flex gap-3 rounded-xl border p-4 text-sm transition-all duration-200 [&>svg]:size-5 [&>svg]:shrink-0',
  {
    variants: {
      variant: {
        info: 'border-accent-cyan/30 bg-accent-cyan/5 text-accent-cyan [&>svg]:text-accent-cyan',
        success:
          'border-accent-emerald/30 bg-accent-emerald/5 text-accent-emerald [&>svg]:text-accent-emerald',
        warning:
          'border-accent-amber/30 bg-accent-amber/5 text-accent-amber [&>svg]:text-accent-amber',
        error: 'border-accent-rose/30 bg-accent-rose/5 text-accent-rose [&>svg]:text-accent-rose',
      },
    },
    defaultVariants: {
      variant: 'info',
    },
  }
)

/**
 * Variants emitted by the alert today. The `AlertProps['variant']` shape
 * is widened below to also accept the legacy `'destructive' | 'default'`
 * names from the v0.2.0 cva map; those values are auto-mapped at runtime
 * to `'error'` / `'info'` and trigger a one-time dev-mode console.warn.
 */
type AlertVariant = 'info' | 'success' | 'warning' | 'error'

/** Legacy v0.2.0 variants kept as accepted aliases. */
type LegacyAlertVariant = 'default' | 'destructive'

const LEGACY_VARIANT_MAP: Record<LegacyAlertVariant, AlertVariant> = {
  destructive: 'error',
  default: 'info',
}

// Track which legacy values we've already warned about so a noisy
// re-render loop doesn't spam the console.
const warnedLegacyVariants = new Set<LegacyAlertVariant>()

function resolveVariant(
  variant: AlertVariant | LegacyAlertVariant | null | undefined
): AlertVariant {
  if (variant === 'destructive' || variant === 'default') {
    if (process.env.NODE_ENV !== 'production' && !warnedLegacyVariants.has(variant)) {
      warnedLegacyVariants.add(variant)
      const target = LEGACY_VARIANT_MAP[variant]

      console.warn(
        `[@countermeasure-platform/web-components] <Alert variant="${variant}"> is deprecated and ` +
          `will be removed in a future release. Auto-mapping to variant="${target}". ` +
          `Run: find src -type f \\( -name '*.tsx' -o -name '*.ts' \\) -exec sed -i ` +
          `'s/variant="${variant}"/variant="${target}"/g' {} +`
      )
    }
    return LEGACY_VARIANT_MAP[variant]
  }
  return variant ?? 'info'
}

/** @internal — exported for tests only. Resets the dev-mode warn cache. */
export function _resetAlertLegacyWarnings(): void {
  warnedLegacyVariants.clear()
}

export type AlertProps = Omit<React.ComponentProps<'div'>, 'children'> &
  Omit<VariantProps<typeof alertVariants>, 'variant'> & {
    /**
     * Style variant. Accepts the current `'info' | 'success' | 'warning'
     * | 'error'` set plus the legacy `'destructive' | 'default'` aliases
     * from v0.2.0 (auto-mapped to 'error' / 'info' with a dev warning).
     */
    variant?: AlertVariant | LegacyAlertVariant
    icon?: React.ReactNode
    dismissible?: boolean
    onDismiss?: () => void
    children?: React.ReactNode
  }

function Alert({
  className,
  variant,
  icon,
  dismissible = false,
  onDismiss,
  children,
  ...props
}: AlertProps) {
  const [dismissed, setDismissed] = React.useState(false)
  const resolved = resolveVariant(variant)

  if (dismissed) {
    return null
  }

  return (
    <div
      data-slot="alert"
      data-variant={resolved}
      role="alert"
      className={cn(alertVariants({ variant: resolved }), className)}
      {...props}
    >
      {icon && <span className="mt-0.5 shrink-0">{icon}</span>}
      <div className="flex-1">{children}</div>
      {dismissible && (
        <button
          type="button"
          aria-label="Dismiss"
          onClick={() => {
            setDismissed(true)
            onDismiss?.()
          }}
          className="shrink-0 rounded-lg p-0.5 opacity-70 transition-opacity hover:opacity-100"
        >
          <XIcon className="size-4" />
        </button>
      )}
    </div>
  )
}

function AlertTitle({ className, ...props }: React.ComponentProps<'h5'>) {
  return (
    <h5
      data-slot="alert-title"
      className={cn('mb-1 font-semibold leading-none tracking-tight', className)}
      {...props}
    />
  )
}

function AlertDescription({ className, ...props }: React.ComponentProps<'div'>) {
  return (
    <div
      data-slot="alert-description"
      className={cn('text-sm opacity-90 [&_p]:leading-relaxed', className)}
      {...props}
    />
  )
}

export { Alert, AlertTitle, AlertDescription, alertVariants, type AlertVariant }
