import { useMemo, type CSSProperties } from 'react';
import { getViewport } from '../shared/telegram';

export type CombatOverlayKind = 'damage' | 'blocked' | 'evaded' | 'regen' | 'stunned';
export type CombatOverlayTarget = 'hero' | 'enemy';

export interface CombatOverlayEvent {
  id: number;
  kind: CombatOverlayKind;
  target: CombatOverlayTarget;
  value: number;
  isCrit?: boolean;
  createdAt: number;
}

const FLOAT_DURATION_MS = 2600;
const FEEDBACK_DURATION_MS = 4800;
const CRIT_DURATION_MS = 6000;
const FLOAT_RISE_PX = 96;
const FLOAT_DRIFT_PX = 44;

const FLOAT_KEYFRAMES = `
@keyframes autoheroCombatFloat {
  from {
    opacity: 1;
    transform: translate(-50%, -50%) translate(0, 0) scale(var(--ah-s0, 1));
  }
  to {
    opacity: 0;
    transform: translate(-50%, -50%) translate(var(--ah-drift, 0px), calc(-1 * var(--ah-rise, 0px))) scale(1);
  }
}
`;

interface CombatOverlayProps {
  events: CombatOverlayEvent[];
  onExpire?: (id: number) => void;
}

function durationMs(evt: CombatOverlayEvent): number {
  if (evt.kind === 'blocked' || evt.kind === 'evaded' || evt.kind === 'stunned') {
    return FEEDBACK_DURATION_MS;
  }
  if (evt.kind === 'damage' && evt.isCrit) {
    return CRIT_DURATION_MS;
  }
  return FLOAT_DURATION_MS;
}

function overlayText(evt: CombatOverlayEvent): string {
  if (evt.kind === 'damage') {
    const prefix = evt.isCrit ? 'CRIT ' : '';
    return `${prefix}${Math.round(evt.value)}`;
  }
  if (evt.kind === 'regen') {
    return `+${Math.round(evt.value)}`;
  }
  if (evt.kind === 'blocked') return 'BLOCKED';
  if (evt.kind === 'evaded') return 'EVADED';
  return 'STUNNED';
}

function overlayColor(evt: CombatOverlayEvent): string {
  if (evt.kind === 'regen') return '#44dd66';
  if (evt.kind === 'stunned') return '#ffaa44';
  if (evt.kind === 'blocked' || evt.kind === 'evaded') {
    return evt.target === 'hero' ? '#44dd66' : '#ff5566';
  }
  return evt.isCrit ? '#ffdd44' : '#ffffff';
}

function overlayFontSize(evt: CombatOverlayEvent): number {
  if (evt.kind === 'blocked' || evt.kind === 'evaded' || evt.kind === 'stunned') {
    return 16;
  }
  if (evt.kind === 'damage' && evt.isCrit) return 24;
  return 18;
}

export function CombatOverlay({ events, onExpire }: CombatOverlayProps) {
  const viewport = getViewport();

  const anchors = useMemo(() => {
    const xEnemySide = viewport.width / 2 + 88;
    const xHeroSide = viewport.width / 2 - 88;
    const yMid = viewport.height / 2 - 42;
    return {
      hero: { x: xHeroSide, y: yMid, driftDir: -1 },
      enemy: { x: xEnemySide, y: yMid, driftDir: 1 },
    };
  }, [viewport.height, viewport.width]);

  return (
    <div style={{
      position: 'absolute',
      top: 0,
      left: 0,
      width: '100%',
      height: '100%',
      pointerEvents: 'none',
      overflow: 'hidden',
    }}>
      <style dangerouslySetInnerHTML={{ __html: FLOAT_KEYFRAMES }} />
      {events.map((evt) => {
        const anchor = anchors[evt.target];
        const style: CSSProperties = {
          position: 'absolute',
          left: anchor.x,
          top: anchor.y,
          transform: 'translate(-50%, -50%)',
          animation: `autoheroCombatFloat ${durationMs(evt)}ms cubic-bezier(0.2, 0.75, 0.35, 1) forwards`,
          ['--ah-drift' as string]: `${FLOAT_DRIFT_PX * anchor.driftDir}px`,
          ['--ah-rise' as string]: `${FLOAT_RISE_PX}px`,
          ['--ah-s0' as string]: evt.isCrit ? '1.4' : '1',
          color: overlayColor(evt),
          fontSize: overlayFontSize(evt),
          fontWeight: 900,
          textShadow: '0 2px 4px rgba(0,0,0,0.9), 0 0 8px rgba(0,0,0,0.5)',
          pointerEvents: 'none',
        };

        return (
          <div
            key={evt.id}
            style={style}
            onAnimationEnd={() => onExpire?.(evt.id)}
          >
            {overlayText(evt)}
          </div>
        );
      })}
    </div>
  );
}
