import { layout } from './stores/layout.svelte.js';
import { isEpcType, isInductionType, EPC_LEFT_BOX, EPC_RIGHT_BOX, EPC_LINE_WIDTH, EPC_DEFAULT_WAYPOINTS, EPC_ICON_FILE, INDUCTION_HEAD_W, INDUCTION_ARROW, INDUCTION_STRIP_TOP_FRAC, INDUCTION_STRIP_BOTTOM_FRAC } from './symbols.js';
import { deserializeSymbol } from './serialization.js';
import type { PlacedSymbol } from './types.js';

function downloadBlob(blob: Blob, filename: string) {
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();
  URL.revokeObjectURL(url);
}

async function buildEpcSvgElements(sym: PlacedSymbol): Promise<string> {
  const waypoints = sym.epcWaypoints || EPC_DEFAULT_WAYPOINTS;
  const ox = sym.x;
  const oy = sym.y;
  const parts: string[] = [];

  // Polyline
  if (waypoints.length >= 2) {
    const points = waypoints.map(wp => `${ox + wp.x},${oy + wp.y}`).join(' ');
    parts.push(`    <polyline points="${points}" fill="none" stroke="#000000" stroke-width="${EPC_LINE_WIDTH}" />`);
  }

  if (waypoints.length >= 2) {
    // Left icon — embed actual SVG, oriented along first segment
    const lb = EPC_LEFT_BOX;
    const p0x = ox + waypoints[0].x, p0y = oy + waypoints[0].y;
    const p1x = ox + waypoints[1].x, p1y = oy + waypoints[1].y;
    const lAngle = Math.atan2(p1y - p0y, p1x - p0x) * 180 / Math.PI;

    try {
      const svgText = await (await fetch(EPC_ICON_FILE)).text();
      const doc = new DOMParser().parseFromString(svgText, 'image/svg+xml');
      const svgEl = doc.documentElement;
      const vb = svgEl.getAttribute('viewBox');
      const [vbX, vbY, vbW, vbH] = vb ? vb.split(/[\s,]+/).map(Number) : [0, 0, lb.w, lb.h];
      const sx = lb.w / vbW;
      const sy = lb.h / vbH;
      const transform = `translate(${p0x},${p0y}) rotate(${lAngle.toFixed(2)}) translate(${-lb.w},${-lb.h / 2}) scale(${sx.toFixed(6)},${sy.toFixed(6)}) translate(${-vbX},${-vbY})`;
      parts.push(`    <g transform="${transform}">`);
      parts.push(`      ${svgEl.innerHTML}`);
      parts.push(`    </g>`);
    } catch {
      // Fallback: plain rect
      parts.push(`    <rect x="${-lb.w}" y="${-lb.h / 2}" width="${lb.w}" height="${lb.h}" fill="#aaaaaa" stroke="#000000" stroke-width="0.3" transform="translate(${p0x},${p0y}) rotate(${lAngle.toFixed(2)})" />`);
    }

    // Right box — oriented along last segment, left-center at wp[last]
    const last = waypoints[waypoints.length - 1];
    const prev = waypoints[waypoints.length - 2];
    const plx = ox + last.x, ply = oy + last.y;
    const ppx = ox + prev.x, ppy = oy + prev.y;
    const rAngle = Math.atan2(ply - ppy, plx - ppx) * 180 / Math.PI;
    const rb = EPC_RIGHT_BOX;
    parts.push(`    <rect x="0" y="${-rb.h / 2}" width="${rb.w}" height="${rb.h}" fill="#aaaaaa" stroke="#000000" stroke-width="0.3" transform="translate(${plx},${ply}) rotate(${rAngle.toFixed(2)})" />`);
  }

  return parts.join('\n');
}

export async function exportSVG() {
  const lines: string[] = [
    '<?xml version="1.0" encoding="UTF-8" standalone="no"?>',
    `<svg width="${layout.canvasW}" height="${layout.canvasH}" viewBox="0 0 ${layout.canvasW} ${layout.canvasH}" version="1.1"`,
    '  xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"',
    '  xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape">',
    `  <rect width="${layout.canvasW}" height="${layout.canvasH}" fill="#ffffff" />`,
  ];

  for (const sym of layout.symbols) {
    const rot = sym.rotation || 0;
    const cx = sym.x + sym.w / 2;
    const cy = sym.y + sym.h / 2;
    const rotAttr = rot ? ` transform="rotate(${rot},${cx},${cy})"` : '';
    const label = sym.label || sym.name;
    const idAttr = ` id="${label}" inkscape:label="${label}"`;

    if (isEpcType(sym.symbolId)) {
      lines.push(`  <g${idAttr}${rotAttr}>`);
      lines.push(await buildEpcSvgElements(sym as PlacedSymbol));
      lines.push('  </g>');
    } else if (isInductionType(sym.symbolId)) {
      const hw = INDUCTION_HEAD_W;
      const stripTopY = sym.y + sym.h * INDUCTION_STRIP_TOP_FRAC;
      const stripBottomY = sym.y + sym.h * INDUCTION_STRIP_BOTTOM_FRAC;
      const pts = INDUCTION_ARROW.map(([xf, yf]) => [sym.x + xf * hw, sym.y + yf * sym.h] as const);
      const d = `M ${sym.x + sym.w},${stripTopY} L ${pts[0][0]},${stripTopY} ${pts.map(([px, py]) => `L ${px},${py}`).join(' ')} L ${pts[5][0]},${stripBottomY} L ${sym.x + sym.w},${stripBottomY} Z`;
      lines.push(`  <g${idAttr}>`);
      lines.push(`    <path d="${d}" fill="#000000"${rotAttr} />`);
      lines.push('  </g>');
    } else {
      try {
        const svgText = await (await fetch(sym.file)).text();
        const doc = new DOMParser().parseFromString(svgText, 'image/svg+xml');
        const svgEl = doc.documentElement;
        // Skip if DOMParser returned an error (e.g., 404 or invalid SVG)
        if (svgEl.querySelector('parsererror')) {
          console.error('SVG parse error for:', sym.file);
          continue;
        }
        const vb = svgEl.getAttribute('viewBox');
        const [vbX, vbY, vbW, vbH] = vb
          ? vb.split(/[\s,]+/).map(Number)
          : [0, 0, sym.w, sym.h];
        const sx = sym.w / vbW;
        const sy = sym.h / vbH;

        let transform = `translate(${sym.x},${sym.y}) scale(${sx.toFixed(6)},${sy.toFixed(6)}) translate(${-vbX},${-vbY})`;
        if (rot) {
          transform = `rotate(${rot},${cx},${cy}) ${transform}`;
        }

        lines.push(`  <g${idAttr} transform="${transform}">`);
        lines.push(`    ${svgEl.innerHTML}`);
        lines.push('  </g>');
      } catch (err) {
        console.error('Failed to embed symbol:', sym.name, err);
      }
    }
  }

  lines.push('</svg>');
  downloadBlob(new Blob([lines.join('\n')], { type: 'image/svg+xml' }), 'test_view.svg');
}

export function loadLayoutJSON(file: File): Promise<void> {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (ev) => {
      try {
        const data = JSON.parse(ev.target!.result as string);
        layout.pushUndo();
        if (data.gridSize) layout.gridSize = data.gridSize;
        if (data.minSpacing) layout.minSpacing = data.minSpacing;
        layout.symbols = [];
        layout.nextId = 1;
        for (const s of data.symbols) {
          layout.symbols.push(deserializeSymbol(s, layout.nextId++));
        }
        layout.markDirty();
        layout.saveMcmState();
        resolve();
      } catch (err) {
        reject(err);
      }
    };
    reader.readAsText(file);
  });
}
