import { memo, useState } from "react";
import type { VisualAgent } from "@/lib/types";
import { generateAppearance } from "@/lib/appearance";
import { STATUS_COLORS, STATUS_LABELS } from "@/lib/constants";
import { interpolatePath } from "@/lib/movement";
import { useOfficeStore } from "@/store/office-store";
import { Pawn, type PawnMotion, type PawnPose } from "./Pawn";
import { ErrorEmote, SparkleEmote, SpeechEmote, ThoughtEmote, ToolEmote, ZzzEmote } from "./Emotes";

const WALK_BOB_AMPLITUDE = 1.2;
const WALK_BOB_FREQ = 7;
const EMOTE_Y = -34;

interface AgentAvatarProps {
  agent: VisualAgent;
}

export const AgentAvatar = memo(function AgentAvatar({ agent }: AgentAvatarProps) {
  const selectedAgentId = useOfficeStore((s) => s.selectedAgentId);
  const selectAgent = useOfficeStore((s) => s.selectAgent);
  const isDark = useOfficeStore((s) => s.theme) === "dark";
  const [hovered, setHovered] = useState(false);

  const isSelected = selectedAgentId === agent.id;
  const isWalking = agent.movement !== null;
  const statusColor = STATUS_COLORS[agent.status];
  const appearance = generateAppearance(agent.id);

  const pose: PawnPose = isWalking
    ? "walk"
    : agent.zone === "desk" || agent.zone === "hotDesk" || agent.zone === "meeting"
      ? "sit"
      : "stand";

  let motion: PawnMotion = "none";
  if (!isWalking) {
    if (agent.status === "error") motion = "shaking";
    else if (agent.status === "speaking") motion = "talking";
    else if (agent.status === "tool_calling" || agent.status === "thinking") motion = "typing";
  }

  // Walk bob + facing derived from movement progress (declarative — no rAF here).
  let bobY = 0;
  let facingLeft = false;
  if (agent.movement) {
    bobY = Math.sin(agent.movement.elapsed * WALK_BOB_FREQ * Math.PI * 2) * WALK_BOB_AMPLITUDE;
    const p = agent.movement.elapsed / agent.movement.duration;
    const ahead = interpolatePath(agent.movement.path, Math.min(p + 0.02, 1));
    facingLeft = ahead.x < agent.position.x - 0.01;
  }

  const displayName = agent.name.length > 12 ? `${agent.name.slice(0, 12)}…` : agent.name;

  return (
    <g
      data-agent-id={agent.id}
      transform={`translate(${agent.position.x}, ${agent.position.y + bobY})`}
      style={{ cursor: "pointer" }}
      onClick={(e) => {
        e.stopPropagation();
        selectAgent(agent.id);
      }}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
    >
      {isSelected && (
        <g style={{ animation: "selection-ring 1.4s ease-in-out infinite", transformBox: "fill-box", transformOrigin: "center" }}>
          <ellipse cy={17.5} rx={16} ry={5} fill={statusColor} opacity={0.22} style={{ filter: `drop-shadow(0 0 6px ${statusColor})` }} />
          <ellipse cy={17.5} rx={16} ry={5} fill="none" stroke={statusColor} strokeWidth={1.6} />
        </g>
      )}
      {hovered && !isSelected && (
        <ellipse cy={17.5} rx={14.5} ry={4.5} fill="none" stroke={statusColor} strokeWidth={1} opacity={0.5} />
      )}

      <g style={agent.status === "spawning" && !isWalking ? spawnStyle : undefined}>
        <g transform={facingLeft ? "scale(-1, 1)" : undefined}>
          <Pawn appearance={appearance} pose={pose} motion={motion} />
        </g>
      </g>

      {!isWalking && (
        <g transform={`translate(0, ${EMOTE_Y})`}>
          {agent.status === "thinking" && <ThoughtEmote isDark={isDark} />}
          {agent.status === "speaking" && <SpeechEmote text={agent.speech ?? ""} isDark={isDark} />}
          {agent.status === "tool_calling" && agent.currentTool && (
            <ToolEmote toolName={agent.currentTool.name} isDark={isDark} />
          )}
          {agent.status === "error" && <ErrorEmote />}
          {agent.status === "offline" && <ZzzEmote isDark={isDark} />}
          {agent.status === "spawning" && <SparkleEmote />}
        </g>
      )}

      {/* name tag */}
      <foreignObject x={-60} y={21} width={120} height={22} style={{ pointerEvents: "none" }}>
        <div style={{ display: "flex", justifyContent: "center" }}>
          <span
            style={{
              display: "inline-flex",
              alignItems: "center",
              gap: "4px",
              fontSize: "10px",
              fontWeight: 600,
              fontFamily: "'Instrument Sans', system-ui, sans-serif",
              color: isDark ? "#e8e4da" : "#3d3830",
              backgroundColor: isDark ? "rgba(23,19,16,0.8)" : "rgba(255,252,245,0.88)",
              backdropFilter: "blur(6px)",
              borderRadius: "7px",
              padding: "1px 7px",
              whiteSpace: "nowrap",
              border: `1px solid ${isDark ? "rgba(255,255,255,0.08)" : "rgba(120,90,60,0.18)"}`,
              boxShadow: "0 1px 3px rgba(0,0,0,0.1)",
            }}
          >
            <span
              style={{
                width: "5px",
                height: "5px",
                borderRadius: "50%",
                backgroundColor: statusColor,
                flexShrink: 0,
                boxShadow: `0 0 3px ${statusColor}`,
              }}
            />
            {agent.role === "lead" && <span style={{ color: "#d97757", fontSize: "9px" }}>✳</span>}
            {displayName}
            {agent.role === "subagent" && (
              <span
                style={{
                  fontSize: "8px",
                  fontWeight: 700,
                  color: "#fff",
                  backgroundColor: statusColor,
                  borderRadius: "4px",
                  padding: "0 3px",
                  lineHeight: "10px",
                }}
              >
                S
              </span>
            )}
          </span>
        </div>
      </foreignObject>

      {hovered && (
        <foreignObject x={-80} y={-70} width={160} height={30} style={{ pointerEvents: "none" }}>
          <div style={{ display: "flex", justifyContent: "center" }}>
            <span
              style={{
                fontSize: "11px",
                fontWeight: 500,
                fontFamily: "'Instrument Sans', system-ui, sans-serif",
                color: isDark ? "#e8e4da" : "#3d3830",
                backgroundColor: isDark ? "rgba(23,19,16,0.92)" : "rgba(255,255,255,0.94)",
                borderRadius: "8px",
                padding: "4px 10px",
                whiteSpace: "nowrap",
                boxShadow: "0 4px 8px rgba(0,0,0,0.15)",
                border: `1px solid ${isDark ? "rgba(255,255,255,0.08)" : "rgba(0,0,0,0.06)"}`,
              }}
            >
              {agent.name} · {STATUS_LABELS[agent.status]}
            </span>
          </div>
        </foreignObject>
      )}
    </g>
  );
});

const spawnStyle: React.CSSProperties = {
  animation: "agent-spawn 0.5s ease-out forwards",
  transformBox: "fill-box",
  transformOrigin: "center bottom",
};
