import { useMemo } from "react";
import {
  DARK,
  ENTRANCE,
  LIGHT,
  MEETING_CENTER,
  OFFICE,
  SVG_HEIGHT,
  SVG_WIDTH,
  ZONES,
  ZONE_LABELS,
  type OfficeColors,
} from "@/lib/constants";
import { DESK_SLOTS, HOT_DESK_SLOTS, meetingSeats } from "@/lib/positions";
import { useOfficeStore } from "@/store/office-store";
import type { VisualAgent } from "@/lib/types";
import { AgentAvatar } from "./AgentAvatar";
import { ConnectionLine } from "./ConnectionLine";
import { Chair, CoffeeMachine, CoffeeTable, Desk, MeetingTable, Plant, Sofa } from "./furniture";

export function FloorPlan() {
  const agents = useOfficeStore((s) => s.agents);
  const links = useOfficeStore((s) => s.links);
  const meetings = useOfficeStore((s) => s.meetings);
  const selectAgent = useOfficeStore((s) => s.selectAgent);
  const isDark = useOfficeStore((s) => s.theme) === "dark";
  const C = isDark ? DARK : LIGHT;

  const agentList = useMemo(
    () => [...agents.values()].sort((a, b) => a.position.y - b.position.y),
    [agents],
  );

  const agentById = (id: string): VisualAgent | undefined => agents.get(id);

  return (
    <div className="floorplan-wrap">
      <svg
        viewBox={`0 0 ${SVG_WIDTH} ${SVG_HEIGHT}`}
        className="floorplan-svg"
        preserveAspectRatio="xMidYMid meet"
        onClick={() => selectAgent(null)}
      >
        <defs>
          <filter id="building-shadow" x="-3%" y="-3%" width="106%" height="106%">
            <feDropShadow dx="0" dy="3" stdDeviation="6" floodOpacity={isDark ? 0.5 : 0.15} />
          </filter>
          <pattern id="corridor-tiles" width="28" height="28" patternUnits="userSpaceOnUse">
            <rect width="28" height="28" fill={C.corridor} />
            <rect x="0.5" y="0.5" width="27" height="27" rx="2" fill="none" stroke={C.tile} strokeWidth="0.6" />
          </pattern>
          <pattern id="wood-floor" width="160" height="26" patternUnits="userSpaceOnUse">
            <rect width="160" height="26" fill={C.woodA} />
            <g stroke={C.woodLine} strokeWidth="0.8">
              <line x1="0" y1="0.4" x2="160" y2="0.4" />
              <line x1="0" y1="13.4" x2="160" y2="13.4" />
            </g>
            <g stroke={C.woodLine} strokeWidth="0.6" opacity="0.7">
              <line x1="56" y1="0" x2="56" y2="13" />
              <line x1="128" y1="13" x2="128" y2="26" />
            </g>
          </pattern>
          <pattern id="lounge-carpet" width="10" height="10" patternUnits="userSpaceOnUse">
            <rect width="10" height="10" fill={C.carpet} />
            <circle cx="2.5" cy="2.5" r="0.7" fill={C.carpetDot} opacity="0.6" />
            <circle cx="7.5" cy="7.5" r="0.7" fill={C.carpetDot} opacity="0.6" />
          </pattern>
        </defs>

        {/* building shell */}
        <rect
          x={OFFICE.x}
          y={OFFICE.y}
          width={OFFICE.width}
          height={OFFICE.height}
          rx={OFFICE.cornerRadius}
          fill={C.corridor}
          stroke={C.wall}
          strokeWidth={OFFICE.wallThickness}
          filter="url(#building-shadow)"
        />

        <CorridorFloor colors={C} />

        {/* zone floors */}
        {(Object.keys(ZONES) as Array<keyof typeof ZONES>).map((key) => (
          <rect
            key={`floor-${key}`}
            x={ZONES[key].x}
            y={ZONES[key].y}
            width={ZONES[key].width}
            height={ZONES[key].height}
            fill={key === "lounge" ? "url(#lounge-carpet)" : "url(#wood-floor)"}
          />
        ))}

        <PartitionWalls colors={C} />
        <DoorOpenings colors={C} />

        {/* zone labels */}
        {(Object.keys(ZONES) as Array<keyof typeof ZONES>).map((key) => (
          <text
            key={`label-${key}`}
            x={ZONES[key].x + 16}
            y={ZONES[key].y + 26}
            fontSize={12}
            fontWeight={700}
            letterSpacing="0.1em"
            fill={C.labelText}
            fontFamily="'Instrument Sans', system-ui, sans-serif"
          >
            {ZONE_LABELS[key].zh} · {ZONE_LABELS[key].en}
          </text>
        ))}

        {/* desk zone: 6 fixed workstations */}
        {DESK_SLOTS.map((slot, i) => (
          <DeskUnit key={`desk-${i}`} x={slot.x} y={slot.y} isDark={isDark} agents={agents} zone="desk" slot={i} />
        ))}

        {/* hot desk zone: 8 subagent desks */}
        {HOT_DESK_SLOTS.map((slot, i) => (
          <DeskUnit key={`hot-${i}`} x={slot.x} y={slot.y} isDark={isDark} agents={agents} zone="hotDesk" slot={i} />
        ))}

        {/* meeting zone */}
        <MeetingArea meetingsCount={meetings.length} attendeeCount={meetings[0]?.agentIds.length ?? 0} colors={C} isDark={isDark} />

        {/* lounge */}
        <LoungeDecor colors={C} isDark={isDark} />
        <EntranceDoor colors={C} />

        {/* collaboration links */}
        {links.map((link) => {
          const source = agentById(link.sourceId);
          const target = agentById(link.targetId);
          if (!source || !target) return null;
          return (
            <ConnectionLine
              key={`${link.sourceId}-${link.targetId}`}
              x1={source.position.x}
              y1={source.position.y}
              x2={target.position.x}
              y2={target.position.y}
              strength={link.strength}
              kind={link.kind}
            />
          );
        })}

        {/* agents, painter's order */}
        {agentList.map((agent) => (
          <AgentAvatar key={agent.id} agent={agent} />
        ))}
      </svg>
    </div>
  );
}

/* ── pieces ── */

function DeskUnit({
  x,
  y,
  isDark,
  agents,
  zone,
  slot,
}: {
  x: number;
  y: number;
  isDark: boolean;
  agents: Map<string, VisualAgent>;
  zone: "desk" | "hotDesk";
  slot: number;
}) {
  // The seat point (agent.homePosition) is 18px above the unit centre.
  let active = false;
  for (const a of agents.values()) {
    if (a.homeZone === zone && a.homeSlot === slot && !a.movement && a.zone === zone) {
      active = a.status === "thinking" || a.status === "tool_calling" || a.status === "speaking";
      break;
    }
  }
  return (
    <g transform={`translate(${x}, ${y})`}>
      <Chair x={0} y={-14} isDark={isDark} />
      <Desk x={0} y={26} isDark={isDark} active={active} />
    </g>
  );
}

function MeetingArea({
  meetingsCount,
  attendeeCount,
  colors,
  isDark,
}: {
  meetingsCount: number;
  attendeeCount: number;
  colors: OfficeColors;
  isDark: boolean;
}) {
  const center = MEETING_CENTER;
  const hasMeeting = meetingsCount > 0 && attendeeCount > 0;
  const seatR = hasMeeting ? Math.min(74 + attendeeCount * 6, 108) : 88;
  const tableR = hasMeeting ? seatR - 28 : 54;
  const chairPts = hasMeeting
    ? meetingSeats(attendeeCount, center)
    : Array.from({ length: 6 }, (_, i) => {
        const angle = (2 * Math.PI * i) / 6 - Math.PI / 2;
        return { x: center.x + Math.cos(angle) * seatR, y: center.y + Math.sin(angle) * seatR };
      });

  return (
    <g>
      {/* rug */}
      <g transform={`translate(${center.x}, ${center.y})`} opacity={0.85}>
        <circle r={seatR + 34} fill={colors.rug} />
        <circle r={seatR + 28} fill="none" stroke={colors.rugBorder} strokeWidth={2} strokeDasharray="10 6" />
      </g>
      {chairPts.map((p, i) => (
        <Chair key={`mchair-${i}`} x={Math.round(p.x)} y={Math.round(p.y)} isDark={isDark} />
      ))}
      <MeetingTable x={center.x} y={center.y} radius={tableR} isDark={isDark} />
    </g>
  );
}

function CorridorFloor({ colors }: { colors: OfficeColors }) {
  const cw = OFFICE.corridorWidth;
  const hy = OFFICE.y + (OFFICE.height - cw) / 2;
  const vx = OFFICE.x + (OFFICE.width - cw) / 2;
  return (
    <g>
      <rect x={OFFICE.x} y={hy} width={OFFICE.width} height={cw} fill="url(#corridor-tiles)" />
      <rect x={vx} y={OFFICE.y} width={cw} height={OFFICE.height} fill="url(#corridor-tiles)" />
      <line
        x1={OFFICE.x}
        y1={hy + cw / 2}
        x2={OFFICE.x + OFFICE.width}
        y2={hy + cw / 2}
        stroke={colors.corridorLine}
        strokeWidth={0.5}
        strokeDasharray="8 6"
        opacity={0.6}
      />
      <line
        x1={vx + cw / 2}
        y1={OFFICE.y}
        x2={vx + cw / 2}
        y2={OFFICE.y + OFFICE.height}
        stroke={colors.corridorLine}
        strokeWidth={0.5}
        strokeDasharray="8 6"
        opacity={0.6}
      />
    </g>
  );
}

function PartitionWalls({ colors }: { colors: OfficeColors }) {
  const wallW = 4;
  const cw = OFFICE.corridorWidth;
  const midX = OFFICE.x + (OFFICE.width - cw) / 2;
  const midY = OFFICE.y + (OFFICE.height - cw) / 2;

  const walls = [
    { x: midX - wallW / 2, y: OFFICE.y, w: wallW, h: midY - OFFICE.y },
    { x: midX - wallW / 2, y: midY + cw, w: wallW, h: OFFICE.y + OFFICE.height - midY - cw },
    { x: midX + cw - wallW / 2, y: OFFICE.y, w: wallW, h: midY - OFFICE.y },
    { x: midX + cw - wallW / 2, y: midY + cw, w: wallW, h: OFFICE.y + OFFICE.height - midY - cw },
    { x: OFFICE.x, y: midY - wallW / 2, w: midX - OFFICE.x, h: wallW },
    { x: midX + cw, y: midY - wallW / 2, w: OFFICE.x + OFFICE.width - midX - cw, h: wallW },
    { x: OFFICE.x, y: midY + cw - wallW / 2, w: midX - OFFICE.x, h: wallW },
    { x: midX + cw, y: midY + cw - wallW / 2, w: OFFICE.x + OFFICE.width - midX - cw, h: wallW },
  ];

  return (
    <g>
      {walls.map((w, i) => (
        <rect key={i} x={w.x} y={w.y} width={w.w} height={w.h} fill={colors.wallFill} stroke={colors.wall} strokeWidth={0.5} />
      ))}
    </g>
  );
}

/** Door gaps aligned with the walk paths: south doors for the top rooms, north doors for the bottom rooms. */
function DoorOpenings({ colors }: { colors: OfficeColors }) {
  const cw = OFFICE.corridorWidth;
  const midY = OFFICE.y + (OFFICE.height - cw) / 2;
  const doorWidth = 44;

  const doors = [
    { cx: ZONES.desk.x + ZONES.desk.width / 2, cy: midY },
    { cx: ZONES.meeting.x + ZONES.meeting.width / 2, cy: midY },
    { cx: ZONES.hotDesk.x + ZONES.hotDesk.width / 2, cy: midY + cw },
    { cx: ZONES.lounge.x + ZONES.lounge.width / 2, cy: midY + cw },
  ];

  return (
    <g>
      {doors.map((d, i) => {
        const half = doorWidth / 2;
        return (
          <g key={i}>
            <rect x={d.cx - half} y={d.cy - 3} width={doorWidth} height={6} fill={colors.corridor} />
            <path
              d={`M ${d.cx - half} ${d.cy} A ${half} ${half} 0 0 1 ${d.cx + half} ${d.cy}`}
              fill="none"
              stroke={colors.doorArc}
              strokeWidth={0.8}
              strokeDasharray="3 2"
              opacity={0.5}
            />
          </g>
        );
      })}
    </g>
  );
}

function LoungeDecor({ colors, isDark }: { colors: OfficeColors; isDark: boolean }) {
  const lz = ZONES.lounge;
  // Reception + logo wall sit right-of-centre so the entrance aisle stays clear.
  const rx = lz.x + lz.width * 0.72;
  const wallW = 176;
  const wallH = 34;
  const wallY = lz.y + lz.height * 0.56;

  return (
    <g>
      <Sofa x={lz.x + 118} y={lz.y + 66} rotation={0} isDark={isDark} />
      <Sofa x={lz.x + 118} y={lz.y + 202} rotation={180} isDark={isDark} />
      <CoffeeTable x={lz.x + 118} y={lz.y + 134} isDark={isDark} />
      <CoffeeMachine x={lz.x + 388} y={lz.y + 64} isDark={isDark} />

      {/* logo wall */}
      <rect x={rx - wallW / 2} y={wallY} width={wallW} height={wallH} rx={5} fill={colors.logoBg} />
      <rect x={rx - wallW / 2} y={wallY} width={wallW} height={3} rx={1.5} fill="#d97757" />
      <text
        x={rx}
        y={wallY + wallH / 2 + 6}
        textAnchor="middle"
        fill={colors.logoText}
        fontSize={16}
        fontWeight={600}
        fontFamily="'Fraunces', Georgia, serif"
        letterSpacing="0.06em"
      >
        <tspan fill="#d97757">✳</tspan> Claude Office
      </text>

      {/* reception desk */}
      <rect
        x={rx - 70}
        y={wallY + wallH + 14}
        width={140}
        height={24}
        rx={12}
        fill={isDark ? "#54432e" : "#d9b98a"}
        stroke={isDark ? "#3d3021" : "#bd9c6c"}
        strokeWidth={1.2}
      />

      <Plant x={rx - wallW / 2 - 26} y={wallY + wallH / 2} />
      <Plant x={rx + wallW / 2 + 26} y={wallY + wallH / 2} />
      <Plant x={lz.x + 34} y={lz.y + lz.height - 44} />
      <Plant x={ZONES.desk.x + 30} y={ZONES.desk.y + 44} />
      <Plant x={ZONES.meeting.x + ZONES.meeting.width - 34} y={ZONES.meeting.y + 44} />
    </g>
  );
}

function EntranceDoor({ colors }: { colors: OfficeColors }) {
  const doorCX = ENTRANCE.x;
  const doorY = OFFICE.y + OFFICE.height;
  const half = 36;

  return (
    <g>
      <rect x={doorCX - half - 2} y={doorY - OFFICE.wallThickness - 1} width={half * 2 + 4} height={OFFICE.wallThickness + 4} fill={colors.carpet} />
      <rect x={doorCX - half - 3} y={doorY - 10} width={3} height={12} rx={1} fill={colors.doorArc} />
      <rect x={doorCX + half} y={doorY - 10} width={3} height={12} rx={1} fill={colors.doorArc} />
      <path
        d={`M ${doorCX - half} ${doorY} A ${half} ${half} 0 0 0 ${doorCX} ${doorY - half}`}
        fill="none"
        stroke={colors.doorArc}
        strokeWidth={0.8}
        strokeDasharray="4 3"
        opacity={0.5}
      />
      <path
        d={`M ${doorCX + half} ${doorY} A ${half} ${half} 0 0 1 ${doorCX} ${doorY - half}`}
        fill="none"
        stroke={colors.doorArc}
        strokeWidth={0.8}
        strokeDasharray="4 3"
        opacity={0.5}
      />
      <rect x={doorCX - 30} y={doorY - 18} width={60} height={12} rx={3} fill="#c0714c" opacity={0.45} />
      <text
        x={doorCX}
        y={doorY + 15}
        textAnchor="middle"
        fill={colors.doorArc}
        fontSize={9}
        fontWeight={600}
        letterSpacing="0.15em"
        fontFamily="'Instrument Sans', system-ui, sans-serif"
      >
        ENTRANCE
      </text>
    </g>
  );
}
