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

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 DEFAULT_ACCENTS = [
  { id: 'ridge', theta: Math.PI / 4, radius: 0.04, color: '#A56BFF' },
  { id: 'green-line', theta: Math.PI * 0.72, radius: 0.022, color: '#22D37D' },
];

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 finishSpecular(finish) {
  if (finish === 'gloss concept') return new Color3(0.6, 0.6, 0.6);
  if (finish === 'satin') return new Color3(0.25, 0.25, 0.25);
  return new Color3(0.05, 0.05, 0.05); // matte
}

export function buildConceptualCover(scene, geometry, designConfig = null) {
  const mainColour = resolveColour(designConfig && designConfig.main_colour, '#2E2150');
  const accentColour = resolveColour(designConfig && designConfig.accent_colour, '#A56BFF');

  const mat = new StandardMaterial('coverMat', scene);
  mat.diffuseColor = Color3.FromHexString(mainColour);
  mat.emissiveColor = Color3.FromHexString(mainColour).scale(0.35);
  mat.specularColor = finishSpecular(designConfig && designConfig.finish);
  mat.alpha = 0.78;
  mat.transparencyMode = 2;
  mat.backFaceCulling = false;
  mat.sideOrientation = Mesh.DOUBLESIDE;

  const rings = (geometry && geometry.coverStations && geometry.coverStations.length) ? geometry.coverStations : COVER_RINGS;

  let shell;
  try {
    shell = createAnatomicalSectionMesh(scene, 'cover-shell', rings, { closeBottom: true });
  } catch (_) {
    shell = MeshBuilder.CreateCylinder('cover-shell', { diameterTop: 1.5, diameterBottom: 0.8, height: 3.8, tessellation: 30 }, scene);
  }
  shell.material = mat;
  shell.metadata = { type: 'cover', partId: 'cover-shell', label: 'Conceptual Cover' };

  const meshes = [shell];
  const accentMats = [];

  // Pattern-style accent bands — derived from design config, fall back to defaults
  const accents = buildAccentBands(designConfig, accentColour, rings);
  accents.forEach((a) => {
    try {
      const path = rings.map((r) => ringSurfacePoint(r, a.theta));
      const tube = MeshBuilder.CreateTube(`cover-${a.id}`, { path, radius: a.radius, tessellation: 8, cap: Mesh.CAP_ALL }, scene);
      const tm = new StandardMaterial(`cover-${a.id}-mat`, scene);
      tm.emissiveColor = Color3.FromHexString(a.color);
      tm.diffuseColor = Color3.FromHexString(a.color);
      tm.specularColor = new Color3(0, 0, 0);
      tube.material = tm;
      tube.isPickable = false;
      meshes.push(tube);
      accentMats.push({ mat: tm, id: a.id });
    } catch (_) { /* accent optional */ }
  });

  return {
    mesh: shell,
    meshes,
    label: { id: 'cover-warn', position: [0, 6.1, 0], text: 'Conceptual cover preview — not manufacturing geometry', kind: 'warning', tone: 'amber' },
    setOpacity: (a) => { mat.alpha = a; },
    update(next = {}) {
      if (next.main_colour) {
        const mc = resolveColour(next.main_colour, mainColour);
        mat.diffuseColor = Color3.FromHexString(mc);
        mat.emissiveColor = Color3.FromHexString(mc).scale(0.35);
      }
      if (next.finish) mat.specularColor = finishSpecular(next.finish);
      if (next.accent_colour) {
        const ac = resolveColour(next.accent_colour, accentColour);
        accentMats.forEach((am) => {
          am.mat.emissiveColor = Color3.FromHexString(ac);
          am.mat.diffuseColor = Color3.FromHexString(ac);
        });
      }
    },
    setVisible: (v) => meshes.forEach((m) => { try { m.setEnabled(v ? 1 : 0); } catch (_) {} }),
    dispose: () => {
      meshes.forEach((m) => { try { m.dispose(); } catch (_) {} });
      try { mat.dispose(); } catch (_) {}
      accentMats.forEach((am) => { try { am.mat.dispose(); } catch (_) {} });
    },
  };
}

function buildAccentBands(config, accentColour, rings) {
  if (!config || !config.pattern_style || config.pattern_style === 'none') {
    return DEFAULT_ACCENTS.map((a) => ({ ...a, color: accentColour }));
  }
  const style = config.pattern_style;
  const density = (config.accent_density === 'aggressive' ? 3 : config.accent_density === 'subtle' ? 1 : 2);
  const accents = [];
  if (style === 'ribbed') {
    for (let i = 0; i < 3 + density; i++) {
      accents.push({ id: `rib-${i}`, theta: Math.PI / 4 + i * 0.12, radius: 0.025, color: accentColour });
    }
  } else if (style === 'panelled' || style === 'segmented shell') {
    [0, Math.PI / 3, (Math.PI * 2) / 3, Math.PI, (Math.PI * 4) / 3, (Math.PI * 5) / 3].forEach((theta, i) => {
      accents.push({ id: `panel-${i}`, theta, radius: 0.02, color: accentColour });
    });
  } else if (style === 'vent-accent') {
    accents.push({ id: 'vent-top', theta: Math.PI * 0.3, radius: 0.03, color: accentColour });
    accents.push({ id: 'vent-bot', theta: Math.PI * 0.8, radius: 0.03, color: accentColour });
  } else if (style === 'skeletal') {
    [Math.PI / 6, Math.PI / 2, (Math.PI * 5) / 6].forEach((theta, i) => {
      accents.push({ id: `skel-${i}`, theta, radius: 0.035, color: accentColour });
    });
  } else if (style === 'geometric') {
    [0, Math.PI / 2, Math.PI, (3 * Math.PI) / 2].forEach((theta, i) => {
      accents.push({ id: `geo-${i}`, theta, radius: 0.028, color: accentColour });
    });
  } else if (style === 'organic flowing') {
    [Math.PI * 0.15, Math.PI * 0.45, Math.PI * 0.75].forEach((theta, i) => {
      accents.push({ id: `org-${i}`, theta, radius: 0.022, color: accentColour });
    });
  } else {
    return DEFAULT_ACCENTS.map((a) => ({ ...a, color: accentColour }));
  }
  return accents;
}