/**
 * TYPE-C-31-M-12 USB-C receptacle (JLCPCB C165948).
 *
 * ── Why the geometry below is what it is ──────────────────────────────────
 *
 * Every constant here was measured off the actual model
 * (modelcdn easyeda C165948, 7872 verts) rather than assumed, because the
 * assumed version renders wrong in a way that still passes lint.
 *
 * Raw model bounding box, in model units (mm):
 *     x  -4.470 .. +4.470     8.94 mm wide  (across the connector)
 *     y  -5.300 .. +2.600     7.90 mm deep  (mouth to back)
 *     z  -0.850 .. +3.250     legs below board, shell 3.25 mm proud
 *
 * The `rotationOffset.z: 180` that the registry packages ship is NOT
 * decoration — it is what aligns the model with this footprint. Reconstructing
 * the registry placement shows the model's raw −5.3 face is the BACK (the end
 * the SMT pads protrude from) and the raw +2.6 face is the MOUTH; the 180°
 * flip puts the mouth at −Y in the footprint's frame. The footprint agrees:
 * its mechanical holes sit at y = −1.04, −1.27 and −5.22 relative to the pad
 * row, i.e. on the −Y side, which is only physically possible if the shell —
 * and therefore the mouth — is also on the −Y side. Anchor legs live inside
 * the shell, never behind it.
 *
 * Drop the 180° and keep the native hole positions and you get a board where
 * the body floats forward of its own pads while the anchors trail out the
 * back. `adom-tsci lint` does not catch this: it derives the mouth vector from
 * `cad.rotation.z` using the same +Y assumption, so a 180° error cancels out
 * of the check and reports a healthy `body_fwd`. Look at the 3D view.
 *
 * ── Placement ─────────────────────────────────────────────────────────────
 *
 * Relative to the pad row, the shell spans +0.06 (back, overlapping the pads
 * slightly) to −7.84 (mouth), and the forward anchor pair sits at −5.22, i.e.
 * 2.6 mm behind the mouth. That last number is the real constraint on how far
 * the connector can hang off the board: overhang the mouth by the ~2.5 mm
 * quoted for a pads-only footprint and the forward anchors land ON the board
 * edge. With the anchors included the honest maximum is well under 1 mm —
 * flush-to-slightly-proud, which is all the mechanical spec asks for anyway.
 */

const USB_C_PN = "C165948"
const USB_C_UUID = "2a4bc2358b36497d9ab2a66ab6419ba3"

/** Model origin -> pad row, along the mouth axis. See the derivation above. */
const BODY_FORWARD_MAG = 2.5034

/** Shell front face, measured forward from the pad row. */
export const USB_C_MOUTH_FROM_PADS = 7.84
/** Forward anchor centre, measured forward from the pad row. */
export const USB_C_FRONT_ANCHOR_FROM_PADS = 5.2232
/** Half-length of the forward anchor pill along the mouth axis. */
export const USB_C_FRONT_ANCHOR_HALF = 0.9

/**
 * Where to put `pcbX`/`pcbY` (the pad row) so the mouth ends up `proud` mm
 * past a board edge that sits `edge` mm from the origin.
 */
export const usbCPadRowForEdge = (edge: number, proud = 0.35) =>
  edge + proud - USB_C_MOUTH_FROM_PADS

const pinLabels = {
  pin1: ["GND1", "A1"],
  pin2: ["GND2", "B12"],
  pin3: ["VBUS1", "A4"],
  pin4: ["VBUS2", "B9"],
  pin5: ["SBU2", "B8"],
  pin6: ["CC1", "A5"],
  pin7: ["DM2", "B7"],
  pin8: ["DP1", "A6"],
  pin9: ["DM1", "A7"],
  pin10: ["DP2", "B6"],
  pin11: ["SBU1", "A8"],
  pin12: ["CC2", "B5"],
  pin13: ["VBUS1", "A9"],
  pin14: ["VBUS2", "B4"],
  pin15: ["GND1", "A12"],
  pin16: ["GND2", "B1"],
} as const

// 16 SMT pads, 0.5 mm pitch, pad row pinned to y = 0.
const PADS: Array<{ port: string; x: number }> = [
  { port: "A1", x: -3.35 },
  { port: "B12", x: -3.05 },
  { port: "A4", x: -2.55 },
  { port: "B9", x: -2.25 },
  { port: "B8", x: -1.75 },
  { port: "A5", x: -1.25 },
  { port: "B7", x: -0.75 },
  { port: "A6", x: -0.25 },
  { port: "A7", x: 0.25 },
  { port: "B6", x: 0.75 },
  { port: "A8", x: 1.25 },
  { port: "B5", x: 1.75 },
  { port: "B4", x: 2.25 },
  { port: "A9", x: 2.55 },
  { port: "B1", x: 3.05 },
  { port: "A12", x: 3.35 },
]

// Mechanical holes. y is measured from the pad row, negative = toward the
// mouth, so all of these sit under the shell.
const PLATED_ANCHORS = [
  { port: "alt_0", x: -4.3251, y: -1.0434, outerH: 2.0, innerH: 1.6 },
  { port: "alt_1", x: 4.3251, y: -1.0434, outerH: 2.0, innerH: 1.6 },
  { port: "alt_3", x: -4.3251, y: -5.2232, outerH: 1.8, innerH: 1.4 },
  { port: "alt_2", x: 4.3251, y: -5.2232, outerH: 1.8, innerH: 1.4 },
]
const SUPPORT_HOLES = [
  { x: -2.8999, y: -1.2685 },
  { x: 2.8999, y: -1.2685 },
]

export const UsbCReceptacle = ({
  name,
  pcbX,
  pcbY,
  pcbRotation = 0,
  schX,
  schY,
  schRotation,
}: {
  name: string
  /** Position of the PAD ROW, not the shell. Use `usbCPadRowForEdge`. */
  pcbX: number
  pcbY: number
  /** 0 fires the mouth south, 90 east, 180 north, 270 west. */
  pcbRotation?: 0 | 90 | 180 | 270
  schX?: number
  schY?: number
  schRotation?: number
}) => {
  // Mouth is local −Y. Rotating (0,−1) by pcbRotation CCW gives the world
  // mouth vector; positionOffset is expressed along that same vector so the
  // body tracks the footprint through every rotation instead of drifting
  // (tscircuit applies positionOffset in world coords, not local).
  const rad = (pcbRotation * Math.PI) / 180
  const mouthX = Math.sin(rad)
  const mouthY = -Math.cos(rad)

  return (
    <chip
      name={name}
      pcbX={pcbX}
      pcbY={pcbY}
      pcbRotation={pcbRotation}
      schX={schX}
      schY={schY}
      schRotation={schRotation}
      supplierPartNumbers={{ jlcpcb: [USB_C_PN] }}
      manufacturerPartNumber="TYPE-C-31-M-12"
      pinLabels={pinLabels as any}
      cadModel={{
        objUrl: `https://modelcdn.tscircuit.com/easyeda_models/download?uuid=${USB_C_UUID}&pn=${USB_C_PN}`,
        // 180° is load-bearing: it aligns the model's mouth with the −Y mouth
        // this footprint's hole positions imply. Do not "simplify" it away.
        rotationOffset: { x: 0, y: 0, z: 180 },
        positionOffset: {
          x: BODY_FORWARD_MAG * mouthX,
          y: BODY_FORWARD_MAG * mouthY,
          z: 0,
        },
      }}
      footprint={
        <footprint>
          {PADS.map((p) => (
            <smtpad
              key={p.port}
              portHints={[p.port]}
              shape="rect"
              width="0.3mm"
              height="1.3mm"
              pcbX={`${p.x}mm`}
              pcbY="0mm"
            />
          ))}
          {PLATED_ANCHORS.map((h) => (
            <platedhole
              key={h.port}
              portHints={[h.port]}
              shape="pill"
              pcbX={`${h.x}mm`}
              pcbY={`${h.y}mm`}
              outerWidth="1.2mm"
              outerHeight={`${h.outerH}mm`}
              innerWidth="0.8mm"
              innerHeight={`${h.innerH}mm`}
            />
          ))}
          {SUPPORT_HOLES.map((h, i) => (
            <hole key={i} pcbX={`${h.x}mm`} pcbY={`${h.y}mm`} diameter="0.75mm" />
          ))}
        </footprint>
      }
    />
  )
}
