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

import { cn } from './utils'

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

export type AttackStepType =
  | 'initial_access'
  | 'execution'
  | 'persistence'
  | 'privilege_escalation'
  | 'defense_evasion'
  | 'credential_access'
  | 'discovery'
  | 'lateral_movement'
  | 'collection'
  | 'exfiltration'
  | 'impact'
  | 'command_and_control'

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

export interface AttackStep {
  id: string
  label: string
  type: AttackStepType
  description?: string
  severity?: AttackStepSeverity
  mitigated?: boolean
  techniques?: string[]
}

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

const TYPE_LABELS: Record<AttackStepType, string> = {
  initial_access: 'Initial Access',
  execution: 'Execution',
  persistence: 'Persistence',
  privilege_escalation: 'Privilege Escalation',
  defense_evasion: 'Defense Evasion',
  credential_access: 'Credential Access',
  discovery: 'Discovery',
  lateral_movement: 'Lateral Movement',
  collection: 'Collection',
  exfiltration: 'Exfiltration',
  impact: 'Impact',
  command_and_control: 'Command & Control',
}

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

const stepVariants = cva(
  'group relative flex flex-col items-center gap-1 rounded-xl border px-4 py-3 text-center backdrop-blur-[20px] transition-all duration-200',
  {
    variants: {
      severity: {
        critical: 'border-accent-rose/40 bg-accent-rose/10 hover:bg-accent-rose/15',
        high: 'border-accent-rose/30 bg-accent-rose/5 hover:bg-accent-rose/10',
        medium: 'border-accent-amber/30 bg-accent-amber/5 hover:bg-accent-amber/10',
        low: 'border-accent-cyan/30 bg-accent-cyan/5 hover:bg-accent-cyan/10',
      },
      mitigated: {
        true: 'opacity-60',
        false: '',
      },
    },
    defaultVariants: {
      mitigated: false,
    },
  }
)

const defaultStepClass = 'border-border-glass bg-glass hover:bg-glass-hover'

/* ------------------------------------------------------------------ */
/*  Arrow connector                                                    */
/* ------------------------------------------------------------------ */

function StepArrow() {
  return (
    <div aria-hidden="true" className="flex shrink-0 items-center px-1 text-foreground-muted">
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        strokeWidth={2}
        strokeLinecap="round"
        strokeLinejoin="round"
        className="size-4"
      >
        <path d="M5 12h14" />
        <path d="m12 5 7 7-7 7" />
      </svg>
    </div>
  )
}

/* ------------------------------------------------------------------ */
/*  AttackPathStep                                                     */
/* ------------------------------------------------------------------ */

export interface AttackPathStepProps extends Omit<React.ComponentProps<'div'>, 'onClick'> {
  step: AttackStep
  showTechniques?: boolean
  onClick?: ((step: AttackStep) => void) | undefined
}

function AttackPathStep({
  className,
  step,
  showTechniques = false,
  onClick,
  ...props
}: AttackPathStepProps) {
  const hasTip =
    step.description || (showTechniques && step.techniques && step.techniques.length > 0)

  return (
    <div
      data-slot="attack-path-step"
      role="listitem"
      className={cn(
        step.severity
          ? stepVariants({ severity: step.severity, mitigated: step.mitigated ?? false })
          : cn(stepVariants({ mitigated: step.mitigated ?? false }), defaultStepClass),
        onClick && 'cursor-pointer',
        className
      )}
      onClick={onClick ? () => onClick(step) : undefined}
      {...props}
    >
      {/* Type label */}
      <span className="text-[10px] font-bold uppercase tracking-wider text-foreground-muted">
        {TYPE_LABELS[step.type]}
      </span>

      {/* Step label */}
      <span className="text-xs font-medium text-foreground">{step.label}</span>

      {/* Mitigated indicator */}
      {step.mitigated && (
        <span
          aria-label="Mitigated"
          className="absolute -right-1 -top-1 flex size-5 items-center justify-center rounded-full bg-accent-emerald text-[10px] text-white"
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth={3}
            strokeLinecap="round"
            strokeLinejoin="round"
            className="size-3"
          >
            <path d="M20 6 9 17l-5-5" />
          </svg>
        </span>
      )}

      {/* Tooltip popup */}
      {hasTip && (
        <div className="pointer-events-none absolute left-1/2 top-full z-10 mt-2 hidden w-48 -translate-x-1/2 rounded-lg border border-border-glass bg-surface-secondary/95 p-3 text-left shadow-lg backdrop-blur-xl group-hover:block">
          {step.description && (
            <p className="text-xs text-foreground-secondary">{step.description}</p>
          )}
          {showTechniques && step.techniques && step.techniques.length > 0 && (
            <ul className="mt-2 flex flex-col gap-1">
              {step.techniques.map(t => (
                <li key={t} className="text-[11px] font-mono text-foreground-muted">
                  {t}
                </li>
              ))}
            </ul>
          )}
        </div>
      )}
    </div>
  )
}

/* ------------------------------------------------------------------ */
/*  AttackPath                                                         */
/* ------------------------------------------------------------------ */

export interface AttackPathProps extends React.ComponentProps<'div'> {
  steps: AttackStep[]
  /** Optional title above the path. */
  title?: string
  /** Show MITRE technique IDs in the tooltip. */
  showTechniques?: boolean
  /** Callback when a step node is clicked. */
  onStepClick?: (step: AttackStep) => void
}

function AttackPath({
  className,
  steps,
  title,
  showTechniques = false,
  onStepClick,
  ...props
}: AttackPathProps) {
  return (
    <div
      data-slot="attack-path"
      role="list"
      aria-label={title ?? 'Attack Path'}
      className={cn('flex flex-col gap-3', className)}
      {...props}
    >
      {title && <div className="text-sm font-semibold text-foreground">{title}</div>}

      <div className="flex items-center gap-1 overflow-x-auto pb-2">
        {steps.map((step, i) => (
          <React.Fragment key={step.id}>
            <AttackPathStep
              step={step}
              showTechniques={showTechniques}
              onClick={onStepClick ?? undefined}
            />
            {i < steps.length - 1 && <StepArrow />}
          </React.Fragment>
        ))}
      </div>
    </div>
  )
}

export { AttackPath, AttackPathStep, stepVariants }
