import { memo } from "react";
import { shade, type PawnAppearance } from "@/lib/appearance";

export type PawnPose = "stand" | "sit" | "walk";
export type PawnMotion = "none" | "typing" | "talking" | "shaking";

const OUTLINE = "rgba(28, 18, 8, 0.32)";

interface PawnProps {
  appearance: PawnAppearance;
  pose: PawnPose;
  motion?: PawnMotion;
  ghost?: boolean;
}

/**
 * Chibi office worker. Anchor (0,0) at the hips; feet ≈ y+16, hair top ≈ y-30.
 */
export const Pawn = memo(function Pawn({ appearance, pose, motion = "none", ghost = false }: PawnProps) {
  const isWalking = pose === "walk";
  const isTyping = motion === "typing" && pose !== "walk";
  const isTalking = motion === "talking";
  const isShaking = motion === "shaking";

  const skin = ghost ? "#9ca3af" : appearance.skinColor;
  const hair = ghost ? "#6b7280" : appearance.hairColor;
  const shirt = ghost ? "#9ca3af" : appearance.shirtColor;
  const pants = ghost ? "#6b7280" : appearance.pantsColor;
  const shoes = ghost ? "#4b5563" : appearance.shoeColor;
  const sleeve = shade(shirt, 0.8);

  return (
    <g>
      <ellipse cx={0} cy={17.5} rx={11.5} ry={3} fill="rgba(0,0,0,0.16)" />

      <g
        style={
          isShaking
            ? { animation: "pawn-shake 0.45s linear infinite", transformBox: "fill-box", transformOrigin: "center" }
            : undefined
        }
      >
        {/* legs */}
        <Leg side={-1} pose={pose} walking={isWalking} pants={pants} shoes={shoes} />
        <Leg side={1} pose={pose} walking={isWalking} pants={pants} shoes={shoes} />

        {/* torso — breathes when idle */}
        <g
          style={
            !isWalking && !isShaking
              ? { animation: "pawn-breathe 3.4s ease-in-out infinite", transformBox: "fill-box", transformOrigin: "center bottom" }
              : undefined
          }
        >
          <rect x={-8} y={-11.5} width={16} height={16} rx={6.5} fill={shirt} stroke={OUTLINE} strokeWidth={1} />
          <path
            d="M -3 -11 L 0 -8.2 L 3 -11"
            fill="none"
            stroke={shade(shirt, 0.66)}
            strokeWidth={1.2}
            strokeLinecap="round"
          />
        </g>

        {/* arms */}
        <Arm side={-1} walking={isWalking} typing={isTyping} sleeve={sleeve} skin={skin} />
        <Arm side={1} walking={isWalking} typing={isTyping} sleeve={sleeve} skin={skin} />

        {/* head */}
        <g>
          <circle cx={0} cy={-19.5} r={8.6} fill={skin} stroke={OUTLINE} strokeWidth={1} />
          <Hair style={appearance.hairStyle} color={hair} />
          <g style={{ animation: "pawn-blink 4.6s ease-in-out infinite", transformBox: "fill-box", transformOrigin: "center" }}>
            <Eyes style={appearance.eyeStyle} />
          </g>
          {isTalking ? (
            <ellipse
              cx={0}
              cy={-15}
              rx={1.8}
              ry={1.6}
              fill="#6b2812"
              style={{ animation: "pawn-mouth 0.35s ease-in-out infinite", transformBox: "fill-box", transformOrigin: "center" }}
            />
          ) : (
            <path d="M -1.8 -15 Q 0 -13.6 1.8 -15" fill="none" stroke="#6b2812" strokeWidth={1} strokeLinecap="round" />
          )}
        </g>
      </g>
    </g>
  );
});

function Leg({ side, pose, walking, pants, shoes }: { side: -1 | 1; pose: PawnPose; walking: boolean; pants: string; shoes: string }) {
  const legH = pose === "sit" ? 7 : 11;
  const shoeY = pose === "sit" ? 5 : 8.5;
  return (
    <g transform={`translate(${side * 3.5}, 3)`}>
      <g
        style={
          walking
            ? {
                animation: "pawn-swing 0.5s ease-in-out infinite alternate",
                animationDelay: side === 1 ? "-0.5s" : "0s",
                transformBox: "fill-box",
                transformOrigin: "center top",
              }
            : undefined
        }
      >
        <rect x={-2.5} y={-1} width={5} height={legH} rx={2.4} fill={pants} stroke={OUTLINE} strokeWidth={0.8} />
        <rect x={-3} y={shoeY} width={6} height={4.5} rx={2} fill={shoes} />
      </g>
    </g>
  );
}

function Arm({ side, walking, typing, sleeve, skin }: { side: -1 | 1; walking: boolean; typing: boolean; sleeve: string; skin: string }) {
  const baseRotate = typing ? side * -30 : 0;
  let animStyle: React.CSSProperties | undefined;
  if (walking) {
    animStyle = {
      animation: "pawn-swing 0.5s ease-in-out infinite alternate",
      animationDelay: side === 1 ? "0s" : "-0.5s",
      transformBox: "fill-box",
      transformOrigin: "center top",
    };
  } else if (typing) {
    animStyle = {
      animation: "pawn-type 0.26s ease-in-out infinite",
      animationDelay: side === 1 ? "-0.13s" : "0s",
      transformBox: "fill-box",
      transformOrigin: "center top",
    };
  }
  return (
    <g transform={`translate(${side * 8.5}, -8.5) rotate(${baseRotate})`}>
      <g style={animStyle}>
        <rect x={-2} y={-1} width={4} height={8.8} rx={2} fill={sleeve} stroke={OUTLINE} strokeWidth={0.8} />
        <circle cx={0} cy={8.8} r={2.4} fill={skin} stroke={OUTLINE} strokeWidth={0.7} />
      </g>
    </g>
  );
}

function Hair({ style, color }: { style: PawnAppearance["hairStyle"]; color: string }) {
  switch (style) {
    case "short":
      return (
        <path
          d="M -8.4 -20.5 Q -8.4 -29 0 -29 Q 8.4 -29 8.4 -20.5 Q 4 -24 0 -24 Q -4 -24 -8.4 -20.5 Z"
          fill={color}
        />
      );
    case "spiky":
      return (
        <g fill={color}>
          <path d="M -8.4 -20.5 Q -8.4 -28 0 -28 Q 8.4 -28 8.4 -20.5 Q 4 -23.5 0 -23.5 Q -4 -23.5 -8.4 -20.5 Z" />
          <polygon points="-6,-26 -5,-31 -3,-27" />
          <polygon points="-1.5,-27 0,-32 1.5,-27" />
          <polygon points="3,-27 5,-31 6,-26" />
        </g>
      );
    case "side-part":
      return (
        <g fill={color}>
          <path d="M -8.4 -20 Q -8.6 -29 -1 -29 Q 8.4 -29 8.4 -20 Q 6.5 -25 2 -25.5 Q -3 -26 -8.4 -20 Z" />
          <path d="M 4 -28 Q 8.9 -26.5 8.6 -21.5 L 6.3 -24 Z" />
        </g>
      );
    case "curly":
      return (
        <g fill={color}>
          <circle cx={-5.5} cy={-24.5} r={3.4} />
          <circle cx={0} cy={-27} r={3.6} />
          <circle cx={5.5} cy={-24.5} r={3.4} />
          <circle cx={-7.8} cy={-20.5} r={2.6} />
          <circle cx={7.8} cy={-20.5} r={2.6} />
        </g>
      );
    case "buzz":
      return (
        <path
          d="M -8 -21.5 Q -8 -28 0 -28 Q 8 -28 8 -21.5 Q 4 -24.5 0 -24.5 Q -4 -24.5 -8 -21.5 Z"
          fill={color}
          opacity={0.72}
        />
      );
    case "bob":
      return (
        <path
          d="M -8.8 -14 Q -9.4 -29.5 0 -29.5 Q 9.4 -29.5 8.8 -14 L 6 -14 Q 7 -24 0 -24.5 Q -7 -24 -6 -14 Z"
          fill={color}
        />
      );
    default:
      return null;
  }
}

function Eyes({ style }: { style: PawnAppearance["eyeStyle"] }) {
  const ey = -20;
  const gap = 3.2;
  switch (style) {
    case "dot":
      return (
        <g>
          <circle cx={-gap} cy={ey} r={1.3} fill="#241a12" />
          <circle cx={gap} cy={ey} r={1.3} fill="#241a12" />
        </g>
      );
    case "line":
      return (
        <g stroke="#241a12" strokeWidth={1.1} strokeLinecap="round">
          <line x1={-gap - 1.6} y1={ey} x2={-gap + 1.6} y2={ey} />
          <line x1={gap - 1.6} y1={ey} x2={gap + 1.6} y2={ey} />
        </g>
      );
    case "wide":
      return (
        <g>
          <ellipse cx={-gap} cy={ey} rx={1.9} ry={2.2} fill="#fff" stroke="#241a12" strokeWidth={0.6} />
          <circle cx={-gap} cy={ey + 0.3} r={1} fill="#241a12" />
          <ellipse cx={gap} cy={ey} rx={1.9} ry={2.2} fill="#fff" stroke="#241a12" strokeWidth={0.6} />
          <circle cx={gap} cy={ey + 0.3} r={1} fill="#241a12" />
        </g>
      );
    default:
      return null;
  }
}
