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

/**
 * Design preview layer — renders conceptual custom design elements on top of
 * the cover shell: custom text plates, accent bands and surface notes overlays.
 *
 * Everything here is a lightweight plane or tube — no booleans, no shaders,
 * no post-processing.  The layer is disposable and updateable without recreating
 * the engine.
 */

const COVER_RINGS = [
  { y: 1.60, rx: 0.40, rz: 0.36 },
  { y: 2.00, rx: 0.44, rz: 0.39 },
  { y: 2.40, rx: 0.52, rz: 0.45 },
  { y: 2.78, rx: 0.60, rz: 0.50 },
  { y: 3.20, rx: 0.72, rz: 0.60 },
  { y: 3.70, rx: 0.86, rz: 0.70 },
  { y: 4.10, rx: 0.94, rz: 0.76 },
  { y: 4.50, rx: 0.98, rz: 0.80, fullBack: 0.14, sideBias: 0.03 },
  { y: 4.85, rx: 0.94, rz: 0.76 },
  { y: 5.15, rx: 0.84, rz: 0.68 },
  { y: 5.40, rx: 0.74, rz: 0.60 },
];

const TEXT_SIZE = { small: 0.22, medium: 0.34, large: 0.48 };

// angular placement -> { theta (around cover), rotY (plane facing outward) }
const ANGULAR = {
  front:           { theta: Math.PI / 2,     rotY: 0 },
  'front-lateral': { theta: Math.PI / 4,    rotY: 0.74 },
  'outer-lateral': { theta: 0,              rotY: Math.PI / 2 },
  'rear-lateral':  { theta: -Math.PI / 4,   rotY: Math.PI - 0.74 },
  rear:            { theta: -Math.PI / 2,    rotY: Math.PI },
};

// vertical placement -> ring index
const VERTICAL = {
  'upper calf': 8,
  'mid calf': 6,
  'lower calf': 4,
};

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 fontStyle(style) {
  switch (style) {
    case 'gothic': return 'bold 90px serif';
    case 'elegant': return '80px serif';
    case 'bold': return 'bold 90px sans-serif';
    case 'technical': return 'bold 72px monospace';
    case 'minimal': return '60px sans-serif';
    default: return 'bold 80px sans-serif'; // clean modern
  }
}

function placementTransform(placement, rings) {
  const ringIndex = VERTICAL[placement] != null ? VERTICAL[placement] : 7; // default mid-upper
  const ring = rings[ringIndex] || rings[Math.floor(rings.length / 2)];
  const ang = ANGULAR[placement] || ANGULAR['outer-lateral'];
  const surface = ringSurfacePoint(ring, ang.theta);
  return { x: surface.x, y: surface.y, z: surface.z, rotY: ang.rotY };
}

function makeTextTexture(scene, text, style, colour) {
  const tex = new DynamicTexture('designTextTex', { width: 512, height: 256 }, scene, false);
  const ctx = tex.getContext();
  ctx.clearRect(0, 0, 512, 256);
  ctx.fillStyle = colour;
  ctx.font = fontStyle(style);
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';
  ctx.fillText(text.slice(0, 40), 256, 128);
  tex.update();
  tex.hasAlpha = true;
  return tex;
}

export function buildDesignPreview(scene, geometry, designConfig = null) {
  const rings = (geometry && geometry.coverStations && geometry.coverStations.length) ? geometry.coverStations : COVER_RINGS;
  const meshes = [];
  const mats = [];
  let textPlane = null;
  let textTex = null;
  let textMat = null;

  function buildText(config) {
    // Dispose previous text
    if (textPlane) { try { textPlane.dispose(); } catch (_) {} textPlane = null; }
    if (textMat) { try { textMat.dispose(); } catch (_) {} textMat = null; }
    if (textTex) { try { textTex.dispose(); } catch (_) {} textTex = null; }

    if (!config || !config.custom_text_enabled || !config.custom_text || !config.custom_text.trim()) return;

    const colour = resolveColour(config.text_colour, '#C0C8D4');
    const sizeKey = config.text_size || 'medium';
    const placement = config.text_placement || 'outer-lateral';
    const text = config.custom_text.trim();
    const charWidth = TEXT_SIZE[sizeKey] || TEXT_SIZE.medium;
    const width = Math.min(charWidth * text.length * 0.7, 2.4);
    const height = charWidth * 1.3;

    try {
      textTex = makeTextTexture(scene, text, config.text_style, colour);
    } catch (_) { textTex = null; }

    textMat = new StandardMaterial('designTextMat', scene);
    textMat.specularColor = new Color3(0.1, 0.1, 0.1);
    textMat.backFaceCulling = true;
    if (textTex) {
      textMat.diffuseTexture = textTex;
      textMat.emissiveTexture = textTex;
      textMat.emissiveColor = Color3.FromHexString(colour).scale(0.7);
      textMat.opacityTexture = textTex;
    } else {
      textMat.diffuseColor = Color3.FromHexString(colour);
      textMat.emissiveColor = Color3.FromHexString(colour).scale(0.5);
    }

    const t = placementTransform(placement, rings);
    textPlane = MeshBuilder.CreatePlane('design-text-plane', { width, height }, scene);
    textPlane.position = new Vector3(
      t.x + Math.sin(t.rotY) * 0.04,
      t.y,
      t.z + Math.cos(t.rotY) * 0.04,
    );
    textPlane.rotation.y = t.rotY;
    if (config.text_orientation === 'vertical') textPlane.rotation.z = Math.PI / 2;
    textPlane.material = textMat;
    textPlane.metadata = { type: 'design', partId: 'custom-text', label: `Text: ${text.slice(0, 20)}` };
    textPlane.isPickable = true;
    meshes.push(textPlane);
    mats.push(textMat);
  }

  if (designConfig) buildText(designConfig);

  return {
    mesh: textPlane,
    label: { id: 'design-status', position: [0, 5.7, 0], text: 'Design concept applied — not manufacturing CAD', kind: 'warning', tone: 'purple' },
    update(next = {}) {
      buildText(next);
    },
    setVisible: (v) => { meshes.forEach((m) => { try { m.setEnabled(v ? 1 : 0); } catch (_) {} }); },
    dispose: () => {
      meshes.forEach((m) => { try { m.dispose(); } catch (_) {} });
      mats.forEach((m) => { try { m.dispose(); } catch (_) {} });
      if (textTex) { try { textTex.dispose(); } catch (_) {} }
    },
  };
}