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

import { cn } from './utils'

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

export type MitreSeverity = 'critical' | 'high' | 'medium' | 'low'

export interface MitreTechnique {
  id: string
  name: string
  tactic: string
  detected?: boolean
  count?: number
  severity?: MitreSeverity
}

/* ------------------------------------------------------------------ */
/*  Constants                                                          */
/* ------------------------------------------------------------------ */

const DEFAULT_TACTICS: readonly string[] = [
  'Initial Access',
  'Execution',
  'Persistence',
  'Privilege Escalation',
  'Defense Evasion',
  'Credential Access',
  'Discovery',
  'Lateral Movement',
  'Collection',
  'Command and Control',
  'Exfiltration',
  'Impact',
]

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

const techniqueVariants = cva(
  'group relative flex flex-col gap-0.5 rounded-lg border px-2.5 py-2 text-left transition-all duration-200',
  {
    variants: {
      severity: {
        critical: 'border-accent-rose/30 hover:border-accent-rose/50',
        high: 'border-accent-rose/20 hover:border-accent-rose/40',
        medium: 'border-accent-amber/20 hover:border-accent-amber/40',
        low: 'border-accent-cyan/20 hover:border-accent-cyan/40',
      },
      detected: {
        true: 'bg-accent-emerald/10 border-accent-emerald/30 hover:bg-accent-emerald/15',
        false: 'bg-glass border-border-glass hover:bg-glass-hover',
      },
    },
    defaultVariants: {
      detected: false,
    },
  }
)

/* ------------------------------------------------------------------ */
/*  TechniqueCell                                                      */
/* ------------------------------------------------------------------ */

interface TechniqueCellProps {
  technique: MitreTechnique
  showCounts?: boolean
  highlightDetected?: boolean
  onClick?: ((technique: MitreTechnique) => void) | undefined
}

function TechniqueCell({
  technique,
  showCounts = false,
  highlightDetected = true,
  onClick,
}: TechniqueCellProps) {
  const detected = highlightDetected && technique.detected === true

  return (
    <div
      className={cn(
        detected
          ? techniqueVariants({ detected: true })
          : technique.severity
            ? techniqueVariants({ severity: technique.severity, detected: false })
            : techniqueVariants({ detected: false }),
        onClick && 'cursor-pointer'
      )}
      title={`${technique.id}: ${technique.name}`}
      onClick={onClick ? () => onClick(technique) : undefined}
    >
      {/* Name */}
      <span className="truncate text-[11px] font-medium leading-tight text-foreground">
        {technique.name}
      </span>

      {/* ID + optional count */}
      <div className="flex items-center justify-between gap-1">
        <span className="text-[10px] font-mono text-foreground-muted">{technique.id}</span>
        {showCounts && technique.count !== undefined && technique.count > 0 && (
          <span className="rounded-full bg-accent-violet/15 px-1.5 py-0.5 text-[9px] font-bold tabular-nums text-accent-violet">
            {technique.count}
          </span>
        )}
      </div>

      {/* Hover tooltip */}
      <div className="pointer-events-none absolute left-1/2 top-full z-20 mt-1 hidden w-44 -translate-x-1/2 rounded-lg border border-border-glass bg-surface-secondary/95 p-2 shadow-lg backdrop-blur-xl group-hover:block">
        <div className="text-[10px] font-mono text-foreground-muted">{technique.id}</div>
        <div className="text-xs font-medium text-foreground">{technique.name}</div>
        {detected && <div className="mt-1 text-[10px] font-bold text-accent-emerald">Detected</div>}
        {technique.count !== undefined && technique.count > 0 && (
          <div className="text-[10px] text-foreground-secondary">Detections: {technique.count}</div>
        )}
      </div>
    </div>
  )
}

/* ------------------------------------------------------------------ */
/*  MitreMatrix                                                        */
/* ------------------------------------------------------------------ */

export interface MitreMatrixProps extends React.ComponentProps<'div'> {
  techniques: MitreTechnique[]
  /** Tactic column headers. Defaults to the standard 12 ATT&CK tactics. */
  tactics?: string[]
  /** Show detection count badges on technique cells. */
  showCounts?: boolean
  /** Highlight detected techniques with green accent. Defaults to true. */
  highlightDetected?: boolean
  /** Callback when a technique cell is clicked. */
  onTechniqueClick?: (technique: MitreTechnique) => void
}

function MitreMatrix({
  className,
  techniques,
  tactics = DEFAULT_TACTICS as string[],
  showCounts = false,
  highlightDetected = true,
  onTechniqueClick,
  ...props
}: MitreMatrixProps) {
  /* Group techniques by tactic */
  const tacticMap = React.useMemo(() => {
    const map = new Map<string, MitreTechnique[]>()
    for (const tactic of tactics) {
      map.set(tactic, [])
    }
    for (const tech of techniques) {
      const list = map.get(tech.tactic)
      if (list) {
        list.push(tech)
      }
    }
    return map
  }, [tactics, techniques])

  return (
    <div
      data-slot="mitre-matrix"
      role="grid"
      aria-label="MITRE ATT&CK Matrix"
      className={cn('overflow-x-auto', className)}
      {...props}
    >
      <div className="inline-flex min-w-full gap-2">
        {tactics.map(tactic => {
          const techs = tacticMap.get(tactic) ?? []
          return (
            <div key={tactic} role="gridcell" className="flex w-36 shrink-0 flex-col gap-1.5">
              {/* Tactic header */}
              <div className="rounded-lg border border-border-glass bg-surface-secondary px-2.5 py-2 text-center">
                <span className="text-[11px] font-bold uppercase tracking-wider text-foreground-secondary">
                  {tactic}
                </span>
              </div>

              {/* Technique cells */}
              {techs.map(tech => (
                <TechniqueCell
                  key={tech.id}
                  technique={tech}
                  showCounts={showCounts}
                  highlightDetected={highlightDetected}
                  onClick={onTechniqueClick}
                />
              ))}
            </div>
          )
        })}
      </div>
    </div>
  )
}

export { MitreMatrix, techniqueVariants }
