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

import { cn } from './utils'

/* ------------------------------------------------------------------ */
/*  Types                                                              */
/* ------------------------------------------------------------------ */

export type CvssSeverity = 'none' | 'low' | 'medium' | 'high' | 'critical'

export type CvssVersion = '3.0' | '3.1' | '4.0'

/* ------------------------------------------------------------------ */
/*  Helpers                                                            */
/* ------------------------------------------------------------------ */

function getSeverity(score: number): CvssSeverity {
  if (score <= 0) return 'none'
  if (score <= 3.9) return 'low'
  if (score <= 6.9) return 'medium'
  if (score <= 8.9) return 'high'
  return 'critical'
}

const SEVERITY_LABELS: Record<CvssSeverity, string> = {
  none: 'None',
  low: 'Low',
  medium: 'Medium',
  high: 'High',
  critical: 'Critical',
}

/* ------------------------------------------------------------------ */
/*  Variants                                                           */
/* ------------------------------------------------------------------ */

const cvssBadgeVariants = cva(
  'inline-flex items-center gap-2 rounded-md border font-semibold tabular-nums transition-all duration-200',
  {
    variants: {
      severity: {
        none: 'border-foreground-muted/25 bg-foreground-muted/[0.12] text-foreground-muted',
        low: 'border-accent-cyan/25 bg-accent-cyan/[0.15] text-accent-cyan',
        medium: 'border-accent-amber/25 bg-accent-amber/[0.15] text-accent-amber',
        high: 'border-accent-rose/25 bg-accent-rose/[0.15] text-accent-rose',
        critical: 'border-accent-rose/35 bg-accent-rose/[0.22] text-accent-rose',
      },
      size: {
        sm: 'px-2 py-0.5 text-[10px]',
        md: 'px-2.5 py-0.5 text-[11px]',
        lg: 'px-3 py-1 text-xs',
      },
    },
    defaultVariants: {
      severity: 'none',
      size: 'md',
    },
  }
)

/* ------------------------------------------------------------------ */
/*  Component                                                          */
/* ------------------------------------------------------------------ */

export interface CvssBadgeProps
  extends
    Omit<React.ComponentProps<'div'>, 'children'>,
    Omit<VariantProps<typeof cvssBadgeVariants>, 'severity'> {
  /** CVSS score from 0 to 10. */
  score: number
  /** CVSS version label (e.g. "3.1", "4.0"). */
  version?: CvssVersion
  /** CVSS vector string. */
  vector?: string
  /** Whether to display the vector string. */
  showVector?: boolean
}

function CvssBadge({
  className,
  score,
  version,
  vector,
  showVector = false,
  size,
  ...props
}: CvssBadgeProps) {
  const clampedScore = Math.max(0, Math.min(10, score))
  const severity = getSeverity(clampedScore)

  return (
    <div
      data-slot="cvss-badge"
      role="status"
      aria-label={`CVSS Score: ${clampedScore.toFixed(1)} - ${SEVERITY_LABELS[severity]}`}
      className={cn(cvssBadgeVariants({ severity, size }), className)}
      {...props}
    >
      <span className="font-bold">{clampedScore.toFixed(1)}</span>
      <span className="opacity-80">{SEVERITY_LABELS[severity]}</span>
      {version && <span className="text-[0.85em] opacity-60">v{version}</span>}
      {showVector && vector && (
        <span className="max-w-[120px] truncate text-[0.85em] opacity-60" title={vector}>
          {vector}
        </span>
      )}
    </div>
  )
}

export { CvssBadge, cvssBadgeVariants }
