import { MeshBuilder, StandardMaterial, Color3, DynamicTexture, Vector3 } from '@babylonjs/core';

/**
 * SHiRE logo branding layer — fixed orientation.
 *
 * The logo is a single thin plane placed on the outer-lateral face of the
 * conceptual cover.  Its front face normal points OUTWARD (away from the cover
 * centre) so that a camera positioned outside the cover always sees the
 * correctly-oriented texture.  backFaceCulling is enabled so the mirrored
 * back face is never rendered — the logo can never appear backwards from any
 * viewing angle.
 *
 * Placement, size and colour are configurable so the Custom Design system can
 * reposition the logo without re-introducing the mirror.
 */

const SIZE_SCALE = { small: 0.7, medium: 1.0, large: 1.3 };

// Each placement maps to an outward-facing position + rotation around Y.
// rotationY is computed so the default +Z plane normal points outward.
const PLACEMENT_MAP = {
  front:          { pos: [0.0,  4.50, 0.84], rotY: 0,            lat: 0 },
  'front-lateral':{ pos: [0.60, 4.50, 0.66], rotY: 0.74,         lat: 0.6 },
  'outer-lateral':{ pos: [0.92, 4.50, 0.0],  rotY: Math.PI / 2,  lat: 1.0 },
  'rear-lateral': { pos: [0.60, 4.50, -0.66],rotY: Math.PI - 0.74,lat: 0.6 },
  rear:           { pos: [0.0,  4.50, -0.84],rotY: Math.PI,       lat: 0 },
};

function resolveColour(value, fallback) {
  const map = { black: '#1A1A22', graphite: '#3B465A', purple: '#7E3FF2', green: '#22D37D', red: '#FF4D62', silver: '#C0C8D4', white: '#F5F7FB' };
  if (!value) return fallback;
  if (map[value]) return map[value];
  if (/^#[0-9A-Fa-f]{6}$/.test(value)) return value;
  return fallback;
}

function makeTexture(scene, colour) {
  const tex = new DynamicTexture('shireLogoTex', { width: 512, height: 200 }, scene, false);
  const ctx = tex.getContext();
  ctx.clearRect(0, 0, 512, 200);
  ctx.fillStyle = colour;
  ctx.font = 'bold 110px sans-serif';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  ctx.fillText('SHiRE', 256, 100);
  tex.update();
  tex.hasAlpha = true;
  return tex;
}

export function buildBranding(scene, options = {}) {
  const placement = options.logo_placement || 'outer-lateral';
  const sizeKey = options.logo_size || 'medium';
  const colour = resolveColour(options.logo_colour, '#C9A6FF');
  const scale = SIZE_SCALE[sizeKey] || 1.0;

  const pm = PLACEMENT_MAP[placement] || PLACEMENT_MAP['outer-lateral'];

  let texture = null;
  try { texture = makeTexture(scene, colour); } catch (_) { texture = null; }

  const mat = new StandardMaterial('shireLogoMat', scene);
  mat.specularColor = new Color3(0.1, 0.1, 0.1);
  mat.backFaceCulling = true; // Only the outward front face renders — never mirrored
  if (texture) {
    mat.diffuseTexture = texture;
    mat.emissiveTexture = texture;
    mat.emissiveColor = Color3.FromHexString(colour).scale(0.7);
    mat.opacityTexture = texture;
  } else {
    mat.diffuseColor = Color3.FromHexString(colour);
    mat.emissiveColor = Color3.FromHexString(colour).scale(0.5);
  }

  const w = 0.82 * scale;
  const h = 0.32 * scale;
  const plane = MeshBuilder.CreatePlane('shire-logo-plane', { width: w, height: h }, scene);
  plane.position = new Vector3(pm.pos[0], pm.pos[1], pm.pos[2]);
  plane.rotation.y = pm.rotY;
  plane.material = mat;
  // Nudge slightly outward so it sits on the surface, not inside
  plane.position.x += Math.sin(pm.rotY) * 0.03;
  plane.position.z += Math.cos(pm.rotY) * 0.03;
  plane.metadata = { type: 'branding', partId: 'logo', label: 'SHiRE Logo' };
  plane.isPickable = true;

  return {
    mesh: plane,
    label: { id: 'logo-label', position: [plane.position.x, plane.position.y + h / 2 + 0.12, plane.position.z], text: 'SHiRE', kind: 'warning', tone: 'purple' },
    setPlacement(newPlacement) {
      const np = PLACEMENT_MAP[newPlacement] || PLACEMENT_MAP['outer-lateral'];
      plane.position.x = np.pos[0] + Math.sin(np.rotY) * 0.03;
      plane.position.y = np.pos[1];
      plane.position.z = np.pos[2] + Math.cos(np.rotY) * 0.03;
      plane.rotation.y = np.rotY;
    },
    update(next = {}) {
      if (next.logo_placement) this.setPlacement(next.logo_placement);
      if (next.logo_size) {
        const ns = SIZE_SCALE[next.logo_size] || 1.0;
        plane.scaling.x = ns / scale;
        plane.scaling.y = ns / scale;
      }
      if (next.logo_colour && next.logo_colour !== options.logo_colour) {
        try { if (texture) texture.dispose(); } catch (_) {}
        try {
          texture = makeTexture(scene, resolveColour(next.logo_colour, colour));
          mat.diffuseTexture = texture;
          mat.emissiveTexture = texture;
          mat.opacityTexture = texture;
          mat.emissiveColor = Color3.FromHexString(resolveColour(next.logo_colour, colour)).scale(0.7);
        } catch (_) {}
        options.logo_colour = next.logo_colour;
      }
    },
    setVisible: (v) => { try { plane.setEnabled(v ? 1 : 0); } catch (_) {} },
    dispose: () => {
      try { plane.dispose(); } catch (_) {}
      try { mat.dispose(); } catch (_) {}
      try { if (texture) texture.dispose(); } catch (_) {}
    },
  };
}