import { customElement, noShadowDOM } from "solid-element";
import {
  Show,
  For,
  createResource,
  createMemo,
  createSignal,
  onCleanup,
} from "solid-js";
import { resolvePath } from "./utils/path";
import { traceImage, type TracedLayer } from "./utils/image-tracer";
import { generate3MF, type ExtrusionSettings } from "./utils/3mf-generator";
import MdTokenViewer from "./md-token-viewer";

export interface TokenProps {
  size?: number; // 模型整体尺寸 (mm), 默认 50
  defaultThickness?: number; // 默认图层厚度 (mm), 默认 2
}

interface LayerSettings {
  id: string;
  name: string;
  enabled: boolean;
  thickness: number;
  color: string;
}

customElement("md-token", { size: 50, defaultThickness: 2 }, (props, { element }) => {
  noShadowDOM();

  const [showEditor, setShowEditor] = createSignal(false);
  const [layers, setLayers] = createSignal<LayerSettings[]>([]);
  const [modelUrl, setModelUrl] = createSignal<string | null>(null);
  const [isGenerating, setIsGenerating] = createSignal(false);
  const [error, setError] = createSignal<string | null>(null);

  // 从 element 的 textContent 获取图片路径
  const rawSrc = element?.textContent?.trim() || "";

  // 隐藏原始文本内容
  if (element) {
    element.textContent = "";
  }

  // 从父节点 article 的 data-src 获取当前 markdown 文件完整路径
  const articleEl = element?.closest("article[data-src]");
  const articlePath = articleEl?.getAttribute("data-src") || "";

  // 解析相对路径
  const resolvedSrc = resolvePath(articlePath, rawSrc);

  // 加载图片
  const loadImage = (src: string): Promise<HTMLImageElement> => {
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.onload = () => resolve(img);
      img.onerror = reject;
      img.src = src;
    });
  };

  const [image] = createResource(resolvedSrc, loadImage);

  // 图像加载完成后进行矢量追踪
  const [traceResult] = createResource(
    () => image(),
    async (img) => {
      if (!img) return null;
      try {
        const traced = await traceImage(img);
        return traced;
      } catch (e) {
        setError(e instanceof Error ? e.message : "矢量追踪失败");
        return null;
      }
    }
  );

  // 初始化图层设置
  createMemo(() => {
    const result = traceResult();
    if (result && result.layers.length > 0) {
      const layerSettings: LayerSettings[] = result.layers.map((layer, index) => ({
        id: layer.id,
        name: layer.name || `图层 ${index + 1}`,
        enabled: true,
        thickness: props.defaultThickness || 2,
        color: `#${layer.color.getHexString()}` || `hsl(${(index * 60) % 360}, 70%, 50%)`,
      }));
      setLayers(layerSettings);
    }
  });

  // 生成 3MF 模型
  const generateModel = async () => {
    if (!image()) return;

    setIsGenerating(true);
    setError(null);

    try {
      const enabledLayers = layers().filter((l) => l.enabled);
      if (enabledLayers.length === 0) {
        setError("请至少选择一个图层");
        setIsGenerating(false);
        return;
      }

      const settings: ExtrusionSettings = {
        size: props.size || 50,
        layers: enabledLayers.map((l) => ({
          id: l.id,
          thickness: l.thickness,
        })),
      };

      const modelBlob = await generate3MF(image()!, traceResult()!, settings);
      const url = URL.createObjectURL(modelBlob);
      setModelUrl(url);
    } catch (e) {
      setError(e instanceof Error ? e.message : "生成模型失败");
    } finally {
      setIsGenerating(false);
    }
  };

  // 更新图层厚度
  const updateLayerThickness = (layerId: string, thickness: number) => {
    setLayers((prev) =>
      prev.map((l) => (l.id === layerId ? { ...l, thickness } : l))
    );
  };

  // 切换图层启用状态
  const toggleLayer = (layerId: string) => {
    setLayers((prev) =>
      prev.map((l) => (l.id === layerId ? { ...l, enabled: !l.enabled } : l))
    );
  };

  // 下载 3MF 文件
  const downloadModel = () => {
    const url = modelUrl();
    if (!url) return;

    const a = document.createElement("a");
    a.href = url;
    a.download = `token-${Date.now()}.3mf`;
    a.click();
  };

  // 清理 URL
  onCleanup(() => {
    const url = modelUrl();
    if (url) {
      URL.revokeObjectURL(url);
    }
  });

  const visible = createMemo(() => !image.loading && !!image());

  return (
    <div class="md-token-component my-4">
      <Show when={visible()}>
        <div class="flex flex-col gap-4">
          {/* 预览区域 */}
          <div class="flex flex-wrap gap-4 items-start">
            {/* 原始图片预览 */}
            <div class="flex-1 min-w-[200px]">
              <h4 class="text-sm font-semibold mb-2 text-gray-700">原始图片</h4>
              <div class="relative border rounded-lg overflow-hidden bg-gray-50">
                <img
                  src={resolvedSrc}
                  alt="Token source"
                  class="max-w-full h-auto max-h-[300px] object-contain"
                />
              </div>
            </div>

            {/* 3D 模型预览 */}
            <Show when={modelUrl()}>
              <div class="flex-1 min-w-[200px]">
                <h4 class="text-sm font-semibold mb-2 text-gray-700">
                  3D 模型预览
                </h4>
                <MdTokenViewer url={modelUrl()}/>
              </div>
            </Show>
          </div>

          {/* 错误信息 */}
          <Show when={error()}>
            <div class="bg-red-50 border border-red-200 text-red-700 px-4 py-2 rounded">
              ⚠️ {error()}
            </div>
          </Show>

          {/* 控制面板 */}
          <div class="border rounded-lg p-4 bg-white shadow-sm">
            <div class="flex items-center justify-between mb-4">
              <h3 class="text-lg font-semibold text-gray-800">
                🎯 Token 设置
              </h3>
              <button
                onClick={() => setShowEditor(!showEditor())}
                class="text-sm text-blue-600 hover:text-blue-800"
              >
                {showEditor() ? "隐藏设置" : "显示设置"}
              </button>
            </div>

            <Show when={showEditor()}>
              <div class="space-y-4">
                {/* 整体尺寸设置 */}
                <div class="flex items-center gap-4">
                  <label class="text-sm font-medium text-gray-700 min-w-[100px]">
                    模型尺寸 (mm)
                  </label>
                  <input
                    type="range"
                    min="10"
                    max="100"
                    step="1"
                    value={props.size || 50}
                    class="flex-1"
                    onChange={(e) => {
                      const newSize = parseInt(e.target.value);
                      element?.setAttribute("size", newSize.toString());
                    }}
                  />
                  <span class="text-sm text-gray-600 w-12 text-right">
                    {props.size || 50}mm
                  </span>
                </div>

                {/* 图层列表 */}
                <div>
                  <h4 class="text-sm font-medium text-gray-700 mb-2">
                    图层设置
                  </h4>
                  <div class="space-y-2 max-h-[300px] overflow-y-auto">
                    <For each={layers()}>
                      {(layer) => (
                        <div class="flex items-center gap-3 p-2 border rounded hover:bg-gray-50">
                          <input
                            type="checkbox"
                            checked={layer.enabled}
                            onChange={() => toggleLayer(layer.id)}
                            class="w-4 h-4"
                          />
                          <div
                            class="w-4 h-4 rounded"
                            style={{ "background-color": layer.color }}
                          />
                          <span class="flex-1 text-sm text-gray-700">
                            {layer.name}
                          </span>
                          <label class="text-xs text-gray-500">厚度:</label>
                          <input
                            type="number"
                            min="0.5"
                            max="10"
                            step="0.5"
                            value={layer.thickness}
                            class="w-16 px-2 py-1 border rounded text-sm"
                            onChange={(e) =>
                              updateLayerThickness(
                                layer.id,
                                parseFloat(e.target.value) || 2
                              )
                            }
                          />
                          <span class="text-xs text-gray-500">mm</span>
                        </div>
                      )}
                    </For>
                  </div>
                </div>

                {/* 生成按钮 */}
                <div class="flex gap-2 pt-2">
                  <button
                    onClick={generateModel}
                    disabled={isGenerating()}
                    class="flex-1 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-400 text-white px-4 py-2 rounded font-medium transition-colors"
                  >
                    {isGenerating() ? "生成中..." : "🔄 生成 3D 模型"}
                  </button>
                  <Show when={modelUrl()}>
                    <button
                      onClick={downloadModel}
                      class="bg-green-600 hover:bg-green-700 text-white px-4 py-2 rounded font-medium transition-colors"
                    >
                      📥 下载 3MF
                    </button>
                  </Show>
                </div>
              </div>
            </Show>
          </div>
        </div>
      </Show>

      {/* 加载状态 */}
      <Show when={image.loading}>
        <div class="text-center py-8 text-gray-500">
          <div class="animate-spin inline-block w-6 h-6 border-2 border-current border-t-transparent rounded-full mr-2" />
          加载图片中...
        </div>
      </Show>
    </div>
  );
});
