// phys8-helpers.js — тематические хелперы для Физики 8 (тепловые, электромагнитные, оптические).
// Дополняет phys.js (тот не трогаем — он общий для Phys 10/11).
// Экспорт в window.P8Helpers = { thermal, em, optics, svg }

(function () {
  'use strict';

  // === SVG-утилиты ===
  const SVGNS = 'http://www.w3.org/2000/svg';

  function svgEl(tag, attrs) {
    const e = document.createElementNS(SVGNS, tag);
    if (attrs) for (const k in attrs) {
      if (k === 'text') e.textContent = attrs[k];
      else e.setAttribute(k, attrs[k]);
    }
    return e;
  }

  function createSvg(width, height, viewBox) {
    const svg = svgEl('svg', {
      xmlns: SVGNS,
      viewBox: viewBox || `0 0 ${width} ${height}`,
      width,
      height,
      preserveAspectRatio: 'xMidYMid meet'
    });
    return svg;
  }

  // === SVG-defs хелперы (градиенты, шаблоны) ===
  function linearGradient(id, stops, opts = {}) {
    const grad = svgEl('linearGradient', {
      id,
      x1: opts.x1 || '0%',
      y1: opts.y1 || '0%',
      x2: opts.x2 || '100%',
      y2: opts.y2 || '0%'
    });
    stops.forEach(([offset, color, opacity = 1]) => {
      grad.appendChild(svgEl('stop', {
        offset: typeof offset === 'number' ? `${offset * 100}%` : offset,
        'stop-color': color,
        'stop-opacity': opacity
      }));
    });
    return grad;
  }

  function radialGradient(id, stops, opts = {}) {
    const grad = svgEl('radialGradient', {
      id,
      cx: opts.cx || '50%',
      cy: opts.cy || '50%',
      r:  opts.r  || '50%'
    });
    stops.forEach(([offset, color, opacity = 1]) => {
      grad.appendChild(svgEl('stop', {
        offset: typeof offset === 'number' ? `${offset * 100}%` : offset,
        'stop-color': color,
        'stop-opacity': opacity
      }));
    });
    return grad;
  }

  // === Стрелка с градиентом и glow ===
  function gradientArrow(svg, x1, y1, x2, y2, opts = {}) {
    const id = opts.id || `arr-${Math.random().toString(36).slice(2, 8)}`;
    const colorFrom = opts.colorFrom || '#fbbf24';
    const colorTo = opts.colorTo || '#dc2626';
    const width = opts.width || 4;
    const headSize = opts.headSize || 14;

    // defs
    let defs = svg.querySelector('defs');
    if (!defs) { defs = svgEl('defs'); svg.appendChild(defs); }
    defs.appendChild(linearGradient(id, [[0, colorFrom, 1], [1, colorTo, 1]], {
      x1: '0%', y1: '0%',
      x2: `${(x2 - x1) > 0 ? 100 : -100}%`,
      y2: `${(y2 - y1) > 0 ? 100 : -100}%`
    }));

    const dx = x2 - x1, dy = y2 - y1;
    const len = Math.hypot(dx, dy);
    if (len < 1e-6) return null;
    const ux = dx / len, uy = dy / len;
    const px = -uy, py = ux;
    const bx = x2 - ux * headSize, by = y2 - uy * headSize;
    const w = headSize * 0.55;
    const lx = bx + px * w, ly = by + py * w;
    const rx = bx - px * w, ry = by - py * w;

    const g = svgEl('g', { filter: opts.glow ? `drop-shadow(0 0 4px ${colorTo})` : '' });
    g.appendChild(svgEl('line', {
      x1, y1, x2: bx, y2: by,
      stroke: `url(#${id})`,
      'stroke-width': width,
      'stroke-linecap': 'round'
    }));
    g.appendChild(svgEl('polygon', {
      points: `${x2},${y2} ${lx},${ly} ${rx},${ry}`,
      fill: colorTo
    }));
    return g;
  }

  // === Текст с подложкой (легче читать на анимированном фоне) ===
  function labeledText(x, y, text, opts = {}) {
    const g = svgEl('g');
    const t = svgEl('text', {
      x, y,
      'font-family': "'JetBrains Mono', monospace",
      'font-size': opts.size || 12,
      'font-weight': opts.weight || 700,
      fill: opts.color || '#0f172a',
      'text-anchor': opts.anchor || 'middle',
      'dominant-baseline': 'middle',
      text
    });
    g.appendChild(t);
    return g;
  }

  // ─────────────────────────────────────────────────────────────────────────
  // === ТЕРМАЛЬНЫЕ хелперы ===
  // ─────────────────────────────────────────────────────────────────────────

  const thermal = {
    // Температурный цвет: 0 (холодный, синий) → 1 (горячий, красный/жёлтый)
    tempColor(t) {
      const k = Math.max(0, Math.min(1, t));
      // Палитра: cool#2563eb → mid#a78bfa → warm#fb923c → hot#facc15
      const stops = [
        [0,    [37, 99, 235]],
        [0.33, [167, 139, 250]],
        [0.66, [251, 146, 60]],
        [1,    [250, 204, 21]]
      ];
      let from = stops[0], to = stops[stops.length - 1];
      for (let i = 0; i < stops.length - 1; i++) {
        if (k >= stops[i][0] && k <= stops[i + 1][0]) { from = stops[i]; to = stops[i + 1]; break; }
      }
      const lt = (k - from[0]) / (to[0] - from[0]);
      const r = Math.round(from[1][0] + (to[1][0] - from[1][0]) * lt);
      const g = Math.round(from[1][1] + (to[1][1] - from[1][1]) * lt);
      const b = Math.round(from[1][2] + (to[1][2] - from[1][2]) * lt);
      return `rgb(${r},${g},${b})`;
    },

    // Heat-flow стрелка: волнистая, градиентом
    heatFlowArrow(svg, x1, y1, x2, y2, intensity = 1) {
      return gradientArrow(svg, x1, y1, x2, y2, {
        colorFrom: '#fde047',
        colorTo: '#dc2626',
        width: 3 + intensity * 2,
        headSize: 12 + intensity * 4,
        glow: true
      });
    },

    // Молекула (с лёгким glow при горячем состоянии)
    molecule(x, y, r, temp = 0.5) {
      const c = thermal.tempColor(temp);
      const g = svgEl('g');
      g.appendChild(svgEl('circle', {
        cx: x, cy: y, r: r * 1.6,
        fill: c, opacity: 0.18 + temp * 0.30
      }));
      g.appendChild(svgEl('circle', {
        cx: x, cy: y, r,
        fill: c,
        stroke: '#0f172a', 'stroke-width': 0.8, opacity: 0.92
      }));
      return g;
    },

    // Термометр (вертикальный, fill уровнем temp 0-1)
    thermometerSVG(x, y, height = 100, temp = 0.5) {
      const g = svgEl('g', { transform: `translate(${x},${y})` });
      const bw = 10, bh = height, bulbR = 14;
      // Tube
      g.appendChild(svgEl('rect', {
        x: -bw / 2, y: 0, width: bw, height: bh,
        rx: bw / 2, fill: '#f3f4f6', stroke: '#475569', 'stroke-width': 1.5
      }));
      // Fill
      const fillH = bh * temp;
      g.appendChild(svgEl('rect', {
        x: -bw / 2 + 2, y: bh - fillH, width: bw - 4, height: fillH,
        rx: 3, fill: thermal.tempColor(temp)
      }));
      // Bulb
      g.appendChild(svgEl('circle', {
        cx: 0, cy: bh + bulbR - 3, r: bulbR,
        fill: thermal.tempColor(temp),
        stroke: '#475569', 'stroke-width': 1.5
      }));
      // Glow
      g.appendChild(svgEl('circle', {
        cx: 0, cy: bh + bulbR - 3, r: bulbR + 6,
        fill: thermal.tempColor(temp), opacity: 0.20 + temp * 0.30
      }));
      return g;
    },

    // Конвекционная ячейка — круговое движение частиц (для §4)
    // Используется в виджете с canvas, генерирует начальное состояние частиц
    convectionCellParticles(cx, cy, rx, ry, count = 20) {
      const arr = [];
      for (let i = 0; i < count; i++) {
        const t = i / count;
        const angle = t * 2 * Math.PI;
        arr.push({
          x: cx + rx * Math.cos(angle),
          y: cy + ry * Math.sin(angle),
          angle,
          speed: 0.5 + Math.random() * 0.3,
          r: 3 + Math.random() * 1.5,
          phase: Math.random() * 2 * Math.PI
        });
      }
      return arr;
    }
  };

  // ─────────────────────────────────────────────────────────────────────────
  // === ЭЛЕКТРОМАГНИТНЫЕ хелперы ===
  // ─────────────────────────────────────────────────────────────────────────

  const em = {
    // Заряд: круг с +/-
    chargeSVG(x, y, sign, r = 14, label) {
      const color = sign > 0 ? '#dc2626' : '#2563eb';
      const fill = sign > 0 ? '#fecaca' : '#bfdbfe';
      const g = svgEl('g', { transform: `translate(${x},${y})` });
      g.appendChild(svgEl('circle', {
        cx: 0, cy: 0, r: r + 4,
        fill: color, opacity: 0.15
      }));
      g.appendChild(svgEl('circle', {
        cx: 0, cy: 0, r,
        fill, stroke: color, 'stroke-width': 2
      }));
      const ls = r * 0.5;
      if (sign > 0) {
        g.appendChild(svgEl('line', { x1: -ls, y1: 0, x2: ls, y2: 0, stroke: color, 'stroke-width': 2.5 }));
        g.appendChild(svgEl('line', { x1: 0, y1: -ls, x2: 0, y2: ls, stroke: color, 'stroke-width': 2.5 }));
      } else {
        g.appendChild(svgEl('line', { x1: -ls, y1: 0, x2: ls, y2: 0, stroke: color, 'stroke-width': 2.5 }));
      }
      if (label) {
        g.appendChild(svgEl('text', {
          x: r + 6, y: 4,
          'font-family': "'JetBrains Mono', monospace",
          'font-size': 11, 'font-weight': 700,
          fill: color, text: label
        }));
      }
      return g;
    },

    // Компонент цепи (battery, resistor, lamp, ammeter, voltmeter, switch)
    // pos: { x, y }, orient: 'h' | 'v', label
    circuitComponent(type, x, y, orient = 'h', label) {
      const g = svgEl('g', { transform: `translate(${x},${y})` });
      const len = 60;
      if (type === 'battery') {
        // 2 параллельные полоски: длинная (+), короткая (-)
        g.appendChild(svgEl('line', { x1: -len/2, y1: 0, x2: -8, y2: 0, stroke: '#0f172a', 'stroke-width': 2 }));
        g.appendChild(svgEl('line', { x1: 8, y1: 0, x2: len/2, y2: 0, stroke: '#0f172a', 'stroke-width': 2 }));
        g.appendChild(svgEl('line', { x1: -8, y1: -12, x2: -8, y2: 12, stroke: '#0f172a', 'stroke-width': 3.5 }));
        g.appendChild(svgEl('line', { x1: 8, y1: -7, x2: 8, y2: 7, stroke: '#0f172a', 'stroke-width': 2 }));
      } else if (type === 'resistor') {
        // Зигзаг
        g.appendChild(svgEl('line', { x1: -len/2, y1: 0, x2: -22, y2: 0, stroke: '#0f172a', 'stroke-width': 2 }));
        g.appendChild(svgEl('polyline', {
          points: '-22,0 -16,-10 -8,10 0,-10 8,10 16,-10 22,0',
          fill: 'none', stroke: '#d97706', 'stroke-width': 2.5
        }));
        g.appendChild(svgEl('line', { x1: 22, y1: 0, x2: len/2, y2: 0, stroke: '#0f172a', 'stroke-width': 2 }));
      } else if (type === 'lamp') {
        g.appendChild(svgEl('line', { x1: -len/2, y1: 0, x2: -14, y2: 0, stroke: '#0f172a', 'stroke-width': 2 }));
        g.appendChild(svgEl('circle', { cx: 0, cy: 0, r: 14, fill: '#fef3c7', stroke: '#0f172a', 'stroke-width': 2 }));
        g.appendChild(svgEl('line', { x1: -10, y1: -10, x2: 10, y2: 10, stroke: '#0f172a', 'stroke-width': 1.5 }));
        g.appendChild(svgEl('line', { x1: -10, y1: 10, x2: 10, y2: -10, stroke: '#0f172a', 'stroke-width': 1.5 }));
        g.appendChild(svgEl('line', { x1: 14, y1: 0, x2: len/2, y2: 0, stroke: '#0f172a', 'stroke-width': 2 }));
      } else if (type === 'ammeter' || type === 'voltmeter') {
        g.appendChild(svgEl('line', { x1: -len/2, y1: 0, x2: -14, y2: 0, stroke: '#0f172a', 'stroke-width': 2 }));
        g.appendChild(svgEl('circle', { cx: 0, cy: 0, r: 14, fill: '#fff', stroke: '#0f172a', 'stroke-width': 2 }));
        g.appendChild(svgEl('text', {
          x: 0, y: 0,
          'font-family': "'JetBrains Mono', monospace",
          'font-size': 13, 'font-weight': 800,
          fill: type === 'ammeter' ? '#dc2626' : '#2563eb',
          'text-anchor': 'middle', 'dominant-baseline': 'middle',
          text: type === 'ammeter' ? 'A' : 'V'
        }));
        g.appendChild(svgEl('line', { x1: 14, y1: 0, x2: len/2, y2: 0, stroke: '#0f172a', 'stroke-width': 2 }));
      } else if (type === 'switch') {
        g.appendChild(svgEl('line', { x1: -len/2, y1: 0, x2: -12, y2: 0, stroke: '#0f172a', 'stroke-width': 2 }));
        g.appendChild(svgEl('circle', { cx: -12, cy: 0, r: 2.5, fill: '#0f172a' }));
        g.appendChild(svgEl('line', { x1: -12, y1: 0, x2: 8, y2: -10, stroke: '#0f172a', 'stroke-width': 2 }));
        g.appendChild(svgEl('circle', { cx: 12, cy: 0, r: 2.5, fill: '#0f172a' }));
        g.appendChild(svgEl('line', { x1: 12, y1: 0, x2: len/2, y2: 0, stroke: '#0f172a', 'stroke-width': 2 }));
      }
      if (label) {
        g.appendChild(svgEl('text', {
          x: 0, y: -22,
          'font-family': "'JetBrains Mono', monospace",
          'font-size': 11, 'font-weight': 700,
          fill: '#0f172a', 'text-anchor': 'middle',
          text: label
        }));
      }
      if (orient === 'v') g.setAttribute('transform', `translate(${x},${y}) rotate(90)`);
      return g;
    },

    // Силовая линия от точечного заряда (одиночная)
    fieldLineFrom(cx, cy, angle, length, sign, color) {
      color = color || (sign > 0 ? '#dc2626' : '#2563eb');
      const r1 = 18, r2 = length;
      const x1 = cx + r1 * Math.cos(angle), y1 = cy + r1 * Math.sin(angle);
      const x2 = cx + r2 * Math.cos(angle), y2 = cy + r2 * Math.sin(angle);
      return gradientArrow(null, sign > 0 ? x1 : x2, sign > 0 ? y1 : y2, sign > 0 ? x2 : x1, sign > 0 ? y2 : y1, {
        colorFrom: color, colorTo: color, width: 1.4, headSize: 7
      });
    }
  };

  // ─────────────────────────────────────────────────────────────────────────
  // === ОПТИКА хелперы ===
  // ─────────────────────────────────────────────────────────────────────────

  const optics = {
    // Луч света (стрелка с цветом)
    rayLine(x1, y1, x2, y2, opts = {}) {
      const color = opts.color || '#facc15';
      const width = opts.width || 2.5;
      const dashed = opts.dashed || false;
      const arrow = opts.arrow !== false;
      const g = svgEl('g', { filter: opts.glow ? `drop-shadow(0 0 3px ${color})` : '' });
      g.appendChild(svgEl('line', {
        x1, y1, x2, y2,
        stroke: color, 'stroke-width': width,
        'stroke-linecap': 'round',
        'stroke-dasharray': dashed ? '6 5' : ''
      }));
      if (arrow) {
        const dx = x2 - x1, dy = y2 - y1;
        const len = Math.hypot(dx, dy);
        if (len > 1) {
          const ux = dx / len, uy = dy / len;
          const hs = 9;
          const px = -uy, py = ux;
          const bx = x2 - ux * hs, by = y2 - uy * hs;
          const lx = bx + px * hs * 0.45, ly = by + py * hs * 0.45;
          const rx = bx - px * hs * 0.45, ry = by - py * hs * 0.45;
          g.appendChild(svgEl('polygon', {
            points: `${x2},${y2} ${lx},${ly} ${rx},${ry}`, fill: color
          }));
        }
      }
      return g;
    },

    // Тонкая линза (двояковыпуклая или двояковогнутая)
    lensSVG(cx, cy, height, type = 'converging') {
      const g = svgEl('g', { transform: `translate(${cx},${cy})` });
      const h = height / 2;
      const w = type === 'converging' ? 10 : -10;
      // Эллипс или линза
      const path = `M 0 ${-h}
                    C ${w} ${-h * 0.5}, ${w} ${h * 0.5}, 0 ${h}
                    C ${-w} ${h * 0.5}, ${-w} ${-h * 0.5}, 0 ${-h} Z`;
      g.appendChild(svgEl('path', {
        d: path,
        fill: 'rgba(125, 211, 252, .35)',
        stroke: '#0284c7', 'stroke-width': 2
      }));
      // Стрелки на концах (вид линзы)
      const tip = type === 'converging' ? 6 : -6;
      g.appendChild(svgEl('polygon', {
        points: `${-tip},${-h} 0,${-h - 8} ${tip},${-h}`,
        fill: '#0284c7'
      }));
      g.appendChild(svgEl('polygon', {
        points: `${-tip},${h} 0,${h + 8} ${tip},${h}`,
        fill: '#0284c7'
      }));
      return g;
    },

    // Плоское зеркало (вертикальная штриховка)
    mirrorPlane(x1, y1, x2, y2) {
      const g = svgEl('g');
      g.appendChild(svgEl('line', {
        x1, y1, x2, y2,
        stroke: '#0f172a', 'stroke-width': 3
      }));
      // Hatch штриховка
      const dx = x2 - x1, dy = y2 - y1;
      const len = Math.hypot(dx, dy);
      const ux = dx / len, uy = dy / len;
      const px = uy, py = -ux;
      const step = 8;
      const segs = Math.floor(len / step);
      for (let i = 0; i < segs; i++) {
        const t = i / segs;
        const bx = x1 + dx * t, by = y1 + dy * t;
        g.appendChild(svgEl('line', {
          x1: bx, y1: by,
          x2: bx + px * 8, y2: by + py * 8,
          stroke: '#475569', 'stroke-width': 1.5
        }));
      }
      return g;
    }
  };

  // === Export ===
  window.P8Helpers = {
    svg: { el: svgEl, create: createSvg, linearGradient, radialGradient, gradientArrow, labeledText },
    thermal,
    em,
    optics
  };
})();
