// Container.jsx — defines the canvas volume (the single "empty" block).
//
// Direction vocabulary (matches the user-facing iso view):
//
//                       bBack  (gx=0, gy=0)        ← top of screen, farthest
//                       /    \
//             bLeft  (0, D)   bRight (W, 0)        ← screen-left / screen-right
//                       \    /
//                       bFront (W, D)              ← bottom of screen, nearest viewer
//
// Each direction has three z-tier corners:
//   b<Dir>  — at z=0 (floor / cube bottom corner)
//   t<Dir>  — at z=H + CEIL_LIFT (cube top corner, lifted slightly above the
//             tallest block to give visual headroom)
//   p<Dir>  — at z=-PEDESTAL (pedestal underside; the floor is extruded
//             downward into a solid plinth)
//
// "Posts" are the 4 vertical wireframe edges connecting b<Dir> ↔ t<Dir>.
// They're named for the direction they face: BACK / FRONT / LEFT / RIGHT.
// Blocks placed at the corresponding grid corner cluster around each post.
//
// The component is split into:
//   ContainerBack  — drawn BEFORE blocks (floor, pedestal, far walls, all
//                    edges that should be occluded by blocks in front of them)
//   ContainerFront — drawn AFTER blocks (the two top edges at TWD that are
//                    above all block heights and so always frame the volume)
//
// Always Harper teal, always click-through.

// Lift applied to the TOP corners of the cube wireframe so the ceiling
// visibly clears the tallest blocks (which are inset by PAD≈0.08 on each
// axis and so float a bit off floor and ceiling).
const _CEIL_LIFT = 0.16;

// Pedestal: the floor is extruded DOWNWARD by this much so the canvas reads
// as a solid plinth that the contents sit on top of.
const _PEDESTAL = 0.16;

// Build all named corner points in screen space. Naming convention:
//   b = bottom (z=0),  t = top (z=H+lift),  p = pedestal underside (z=-ped)
//   Dir suffix in {Back, Front, Left, Right} — see vocabulary diagram above.
function _containerCorners(W, D, H, accentSlotH = 0) {
  // accentSlotH: extra vertical space (in world units) reserved above the
  // logical cube top for an accent block to float in. The cube wireframe
  // extends up by this amount; blocks still live in [0, H].
  const Ht = H + _CEIL_LIFT + accentSlotH;
  // FRONT_BUFFER pushes the FRONT-side world boundary outward (in +x/+y)
  // so there's visible breathing room between the rendered front frame
  // (FRONT post + the two FRONT floor/ceiling edges) and any block that
  // sits in the front-most row. The back walls already get a visible
  // gap from the per-block PAD inset; this matches that on the front,
  // where there's no filled wall behind the blocks. Block positions are
  // unchanged — only the wireframe boundary moves.
  const FB = 0.12;
  const Wf = W + FB;
  const Df = D + FB;
  return {
    // Bottom (floor) corners
    bBack:  iso(0,  0,  0),
    bRight: iso(Wf, 0,  0),
    bLeft:  iso(0,  Df, 0),
    bFront: iso(Wf, Df, 0),
    // Top (ceiling) corners — lifted slightly above the cube's logical height
    tBack:  iso(0,  0,  Ht),
    tRight: iso(Wf, 0,  Ht),
    tLeft:  iso(0,  Df, Ht),
    tFront: iso(Wf, Df, Ht),
    // Pedestal underside corners — directly below floor corners
    pBack:  iso(0,  0,  -_PEDESTAL),
    pRight: iso(Wf, 0,  -_PEDESTAL),
    pLeft:  iso(0,  Df, -_PEDESTAL),
    pFront: iso(Wf, Df, -_PEDESTAL),
  };
}

const _teal      = '#2dd4a0';
const _tealLight = '#7df0c4';
const _tealDeep  = '#14b88a';
const _polyStr = (...pts) => pts.map(p => `${p.x},${p.y}`).join(' ');

// Which cube faces are camera-facing (visible) vs. camera-away (hidden)?
//   Camera-facing FRONT-LEFT  face: bFront–bLeft–tLeft –tFront
//   Camera-facing FRONT-RIGHT face: bFront–bRight–tRight–tFront
// (These two are NOT drawn — the cube is an open frame.)
//   Camera-away  BACK-LEFT  face: bBack–bLeft –tLeft –tBack   ← drawn as wall
//   Camera-away  BACK-RIGHT face: bBack–bRight–tRight–tBack   ← drawn as wall
// "Walls" below means the 2 BACK faces; visible through the open front.

function ContainerBack({ W, D, H, accentSlotH = 0 }) {
  const C = _containerCorners(W, D, H, accentSlotH);

  return (
    <g style={{ pointerEvents: 'none' }}>
      <defs>
        <linearGradient id="container-wall-left" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%"   stopColor={_tealLight} stopOpacity="0.18" />
          <stop offset="100%" stopColor={_teal}      stopOpacity="0.55" />
        </linearGradient>
        <linearGradient id="container-wall-right" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%"   stopColor={_tealLight} stopOpacity="0.14" />
          <stop offset="100%" stopColor={_teal}      stopOpacity="0.50" />
        </linearGradient>
      </defs>

      {/* Pedestal — a solid plinth below the floor. The two camera-facing
          side faces extrude straight down from the floor's FRONT-LEFT edge
          (bLeft→bFront) and FRONT-RIGHT edge (bRight→bFront). Same fill, no
          seam at the front-vertical edge, so the plinth reads as one shape. */}
      {/* Pedestal FRONT-RIGHT face (between RIGHT and FRONT posts) */}
      <polygon
        points={_polyStr(C.pRight, C.pFront, C.bFront, C.bRight)}
        fill={_tealDeep}
      />
      {/* Pedestal FRONT-LEFT face (between LEFT and FRONT posts) */}
      <polygon
        points={_polyStr(C.pLeft, C.pFront, C.bFront, C.bLeft)}
        fill={_tealDeep}
      />
      {/* Pedestal outer silhouette — bottom + outer verticals only. The top
          edges (bRight→bFront→bLeft) are already drawn by the cube wireframe
          / floor outline below, so we skip them to avoid double-stroke. */}
      <polyline
        points={_polyStr(C.bRight, C.pRight, C.pFront, C.pLeft, C.bLeft)}
        fill="none"
        stroke={_tealDeep}
        strokeOpacity="0.9"
        strokeWidth="1.5"
        strokeLinejoin="round"
      />

      {/* Floor (top face of pedestal) — solid teal, no stroke (the cube
          wireframe outlines this diamond from its 4 floor edges). */}
      <polygon
        points={_polyStr(C.bBack, C.bRight, C.bFront, C.bLeft)}
        fill={_teal}
      />

      {/* BACK-LEFT wall (camera-away face that meets the LEFT and BACK posts) */}
      <polygon
        points={_polyStr(C.bBack, C.bLeft, C.tLeft, C.tBack)}
        fill="url(#container-wall-left)"
        stroke={_teal}
        strokeOpacity="0.55"
        strokeWidth="1.5"
      />
      {/* BACK-RIGHT wall (camera-away face that meets the RIGHT and BACK posts) */}
      <polygon
        points={_polyStr(C.bBack, C.bRight, C.tRight, C.tBack)}
        fill="url(#container-wall-right)"
        stroke={_teal}
        strokeOpacity="0.55"
        strokeWidth="1.5"
      />

      {/* The 4 vertical posts. All four are drawn here (BEFORE blocks) so
          blocks at any corner occlude their nearest post cleanly. The two
          top edges that frame the silhouette above all blocks live in
          ContainerFront. */}
      <line x1={C.bBack.x}  y1={C.bBack.y}  x2={C.tBack.x}  y2={C.tBack.y}  stroke={_teal}      strokeOpacity="0.55" strokeWidth="1.5" />
      <line x1={C.bRight.x} y1={C.bRight.y} x2={C.tRight.x} y2={C.tRight.y} stroke={_teal}      strokeOpacity="0.55" strokeWidth="1.5" />
      <line x1={C.bLeft.x}  y1={C.bLeft.y}  x2={C.tLeft.x}  y2={C.tLeft.y}  stroke={_teal}      strokeOpacity="0.55" strokeWidth="1.5" />
      {/* FRONT post is rendered in ContainerFront so it always sits on top
          of any block — see comment in ContainerFront. */}

      {/* The 2 floor edges that meet at the BACK corner (bBack→bLeft and
          bBack→bRight). The other 2 (bFront→bLeft, bFront→bRight) are the
          near floor edges and are already covered by the floor polygon's
          silhouette + the pedestal outline. */}
      <line x1={C.bBack.x} y1={C.bBack.y} x2={C.bLeft.x}  y2={C.bLeft.y}  stroke={_teal} strokeOpacity="0.7" strokeWidth="1.5" />
      <line x1={C.bBack.x} y1={C.bBack.y} x2={C.bRight.x} y2={C.bRight.y} stroke={_teal} strokeOpacity="0.7" strokeWidth="1.5" />

      {/* The 2 ceiling edges that meet at the BACK corner (tBack→tLeft and
          tBack→tRight). These stay behind blocks (above the BACK wall area).
          The 2 ceiling edges meeting at the FRONT corner are in ContainerFront. */}
      <line x1={C.tBack.x} y1={C.tBack.y} x2={C.tLeft.x}  y2={C.tLeft.y}  stroke={_teal} strokeOpacity="0.6" strokeWidth="1.5" />
      <line x1={C.tBack.x} y1={C.tBack.y} x2={C.tRight.x} y2={C.tRight.y} stroke={_teal} strokeOpacity="0.6" strokeWidth="1.5" />

      {/* Floor interior grid lines REMOVED — blocks still snap to integer
          grid coordinates via the placement logic in App.jsx; the visible
          guide lines were just decoration. The solid teal floor reads
          cleaner without them. */}
    </g>
  );
}

function ContainerFront({ W, D, H, accentSlotH = 0 }) {
  // Three edges of the cube wireframe that always sit in front of every
  // block in screen space, so they're drawn AFTER blocks:
  //   1. The FRONT vertical post (bFront → tFront) — closest to viewer.
  //   2. The 2 ceiling edges meeting at the FRONT corner (tFront → tRight,
  //      tFront → tLeft) — at z = H + CEIL_LIFT, above every block.
  const C = _containerCorners(W, D, H, accentSlotH);

  return (
    <g style={{ pointerEvents: 'none' }}>
      <line x1={C.bFront.x} y1={C.bFront.y} x2={C.tFront.x} y2={C.tFront.y} stroke={_tealLight} strokeOpacity="0.9"  strokeWidth="1.75" />
      <line x1={C.tFront.x} y1={C.tFront.y} x2={C.tRight.x} y2={C.tRight.y} stroke={_tealLight} strokeOpacity="0.85" strokeWidth="1.75" />
      <line x1={C.tFront.x} y1={C.tFront.y} x2={C.tLeft.x}  y2={C.tLeft.y}  stroke={_tealLight} strokeOpacity="0.85" strokeWidth="1.75" />
    </g>
  );
}

window.ContainerBack = ContainerBack;
window.ContainerFront = ContainerFront;
