import React, { useState, useEffect, useMemo } from 'react';
import { LabelTemplate, TemplateElement, PaperConfig, VisibilityRule } from '../types';
import {
  extractTemplateVariables,
  extractVariablesFromContent,
  isConditionalVisibility,
  isTemplateVariableInUse,
  removeUnusedTemplateVariable,
  resolveVisibilityRules,
} from '../utils';
import { VisibilityRuleDialog } from './VisibilityRuleDialog';
import { VisibilityRuleSummary } from './VisibilityRuleSummary';
import {
  alignToSelectionBounds,
  alignSelectionToCanvas,
  tileSelectedEvenly,
  type AlignMode,
} from '../elementAlign';
import { CollapsiblePanelSection } from './CollapsiblePanelSection';
import { CommitInput } from './CommitInput';
import {
  Sliders,
  LayoutGrid,
  Type,
  AlignLeft,
  AlignCenter,
  AlignRight,
  Bold,
  Italic,
  Underline,
  Strikethrough,
  HelpCircle,
  Lock,
  Unlock,
  ArrowUp,
  ArrowDown,
  Layers,
  Trash2,
  AlignHorizontalJustifyStart,
  AlignHorizontalJustifyCenter,
  AlignHorizontalJustifyEnd,
  AlignVerticalJustifyStart,
  AlignVerticalJustifyCenter,
  AlignVerticalJustifyEnd,
  AlignHorizontalSpaceBetween,
  AlignVerticalSpaceBetween,
  Link2,
  Plus,
  Ruler,
  RotateCw,
  Barcode,
  QrCode,
  Image as ImageIcon,
  Upload,
} from 'lucide-react';

const PANEL_COLLAPSE_STORAGE_KEY = 'label_designer_panel_collapse_v2';

type PanelCollapseState = {
  content: boolean;
  properties: boolean;
  layers: boolean;
};

function loadPanelCollapseState(): PanelCollapseState {
  try {
    const raw = localStorage.getItem(PANEL_COLLAPSE_STORAGE_KEY);
    if (raw) return JSON.parse(raw) as PanelCollapseState;
  } catch {
    /* ignore */
  }
  return { content: true, properties: false, layers: true };
}

const alignBtnClass =
  'px-2 py-1.5 bg-[#383838] hover:bg-[#444] border border-[#4a4a4a] hover:border-[#31a8ff]/50 text-[10px] text-[#ccc] flex flex-col items-center justify-center gap-0.5 transition cursor-pointer rounded-sm min-h-[52px]';

interface AlignToolButtonProps {
  icon: React.ReactNode;
  label: string;
  title: string;
  onClick: () => void;
}

const AlignToolButton: React.FC<AlignToolButtonProps> = ({ icon, label, title, onClick }) => (
  <button type="button" className={alignBtnClass} onClick={onClick} title={title}>
    {icon}
    <span>{label}</span>
  </button>
);

const PropInput = CommitInput;

interface PropTextareaProps extends Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'onChange'> {
  value: string;
  onCommit: (val: string) => void;
}

const PropTextarea: React.FC<PropTextareaProps> = ({ value, onCommit, ...props }) => {
  const [localVal, setLocalVal] = useState<string>(value);

  useEffect(() => {
    setLocalVal(value);
  }, [value]);

  const handleBlur = () => {
    if (localVal !== value) {
      onCommit(localVal);
    }
  };

  return (
    <textarea
      {...props}
      value={localVal}
      onChange={(e) => setLocalVal(e.target.value)}
      onBlur={handleBlur}
    />
  );
};

interface PropSidebarProps {
  template: LabelTemplate;
  onChangeTemplate: (updated: LabelTemplate) => void;
  selectedElementIds: string[];
  activeTab: 'element' | 'paper';
  onChangeTab: (tab: 'element' | 'paper') => void;
  paper: PaperConfig;
  onSelectElements?: (ids: string[]) => void;
}

export const PropSidebar: React.FC<PropSidebarProps> = ({
  template,
  onChangeTemplate,
  selectedElementIds,
  activeTab,
  onChangeTab,
  paper,
  onSelectElements,
}) => {
  const selectedElementId = selectedElementIds[0] || null;
  const selectedElem = template.elements.find((el) => el.id === selectedElementId);
  const [newVarName, setNewVarName] = useState('');
  const [visibilityRuleDialog, setVisibilityRuleDialog] = useState<
    { mode: 'add' } | { mode: 'edit'; index: number } | null
  >(null);
  const [panelCollapsed, setPanelCollapsed] = useState<PanelCollapseState>(loadPanelCollapseState);

  const togglePanel = (key: keyof PanelCollapseState) => {
    setPanelCollapsed((prev) => {
      const isCollapsed = prev[key];
      const next: PanelCollapseState = isCollapsed
        ? { content: true, properties: true, layers: true, [key]: false }
        : { ...prev, [key]: true };
      try {
        localStorage.setItem(PANEL_COLLAPSE_STORAGE_KEY, JSON.stringify(next));
      } catch {
        /* ignore */
      }
      return next;
    });
  };

  const templateVariables = useMemo(() => extractTemplateVariables(template), [template]);

  const addableVisibilityVariables = useMemo(() => {
    if (!selectedElem || !isConditionalVisibility(selectedElem)) return [];
    const rules = resolveVisibilityRules(selectedElem);
    return templateVariables.filter((v) => !rules.some((r) => r.variable === v));
  }, [selectedElem, templateVariables]);

  const visibilityRuleDialogVariableOptions = useMemo(() => {
    if (!selectedElem || !visibilityRuleDialog) return [];
    const rules = resolveVisibilityRules(selectedElem);
    if (visibilityRuleDialog.mode === 'add') {
      return addableVisibilityVariables;
    }
    const usedByOthers = rules
      .filter((_, i) => i !== visibilityRuleDialog.index)
      .map((r) => r.variable);
    return templateVariables.filter((v) => !usedByOthers.includes(v));
  }, [selectedElem, visibilityRuleDialog, addableVisibilityVariables, templateVariables]);

  const editingVisibilityRule = useMemo(() => {
    if (!selectedElem || visibilityRuleDialog?.mode !== 'edit') return undefined;
    return resolveVisibilityRules(selectedElem)[visibilityRuleDialog.index];
  }, [selectedElem, visibilityRuleDialog]);

  // Compute maximum allowed label dimensions based on paper configurations
  const paperW = paper.orientation === 'portrait' ? paper.width : paper.height;
  const paperH = paper.orientation === 'portrait' ? paper.height : paper.width;

  const maxLabelW = Math.max(10, paperW - paper.marginLeft - paper.marginRight);
  const maxLabelH = Math.max(10, paperH - paper.marginTop - paper.marginBottom);

  const handleElemChange = (updatedElem: TemplateElement) => {
    onChangeTemplate({
      ...template,
      elements: template.elements.map((el) => (el.id === updatedElem.id ? updatedElem : el)),
    });
  };

  const applyVisibilityRules = (next: VisibilityRule[]) => {
    if (!selectedElem) return;
    handleElemChange({
      ...selectedElem,
      visibilityMode: 'conditional',
      visibilityRules: next,
      hideWhenNoData: undefined,
      visibilityVariable: undefined,
      visibilityVariables: undefined,
    });
  };

  const handleConfirmVisibilityRule = (rule: VisibilityRule) => {
    if (!selectedElem || !visibilityRuleDialog) return;
    const rules = resolveVisibilityRules(selectedElem);
    if (visibilityRuleDialog.mode === 'edit') {
      const { index } = visibilityRuleDialog;
      if (rules.some((r, i) => i !== index && r.variable === rule.variable)) return;
      applyVisibilityRules(rules.map((r, i) => (i === index ? rule : r)));
    } else {
      if (rules.some((r) => r.variable === rule.variable)) return;
      applyVisibilityRules([...rules, rule]);
    }
  };

  const applyMultiAlign = (mode: AlignMode) => {
    onChangeTemplate({
      ...template,
      elements: alignToSelectionBounds(template.elements, selectedElementIds, mode),
    });
  };

  const applyTile = (axis: 'horizontal' | 'vertical') => {
    onChangeTemplate({
      ...template,
      elements: tileSelectedEvenly(template.elements, selectedElementIds, axis),
    });
  };

  const applyCanvasAlign = (mode: AlignMode) => {
    onChangeTemplate({
      ...template,
      elements: alignSelectionToCanvas(
        template.elements,
        selectedElementIds,
        template.width,
        template.height,
        mode
      ),
    });
  };

  const renderAlignButtonGrid = (
    onAlign: (mode: AlignMode) => void,
    scope: 'selection' | 'canvas' = 'selection'
  ) => {
    const toCanvas = scope === 'canvas';
    return (
      <div className="grid grid-cols-3 gap-1.5">
        <AlignToolButton
          icon={<AlignHorizontalJustifyStart className="w-3.5 h-3.5" />}
          label="左对齐"
          title={toCanvas ? '整体贴齐画布左边缘' : '选区内左边缘对齐'}
          onClick={() => onAlign('left')}
        />
        <AlignToolButton
          icon={<AlignHorizontalJustifyCenter className="w-3.5 h-3.5" />}
          label="水平居中"
          title={toCanvas ? '整体在画布水平居中' : '选区内水平居中对齐'}
          onClick={() => onAlign('centerH')}
        />
        <AlignToolButton
          icon={<AlignHorizontalJustifyEnd className="w-3.5 h-3.5" />}
          label="右对齐"
          title={toCanvas ? '整体贴齐画布右边缘' : '选区内右边缘对齐'}
          onClick={() => onAlign('right')}
        />
        <AlignToolButton
          icon={<AlignVerticalJustifyStart className="w-3.5 h-3.5" />}
          label="顶对齐"
          title={toCanvas ? '整体贴齐画布顶边' : '选区内顶边对齐'}
          onClick={() => onAlign('top')}
        />
        <AlignToolButton
          icon={<AlignVerticalJustifyCenter className="w-3.5 h-3.5" />}
          label="垂直居中"
          title={toCanvas ? '整体在画布垂直居中' : '选区内垂直居中对齐'}
          onClick={() => onAlign('centerV')}
        />
        <AlignToolButton
          icon={<AlignVerticalJustifyEnd className="w-3.5 h-3.5" />}
          label="底对齐"
          title={toCanvas ? '整体贴齐画布底边' : '选区内底边对齐'}
          onClick={() => onAlign('bottom')}
        />
      </div>
    );
  };

  const insertVariable = (varName: string) => {
    if (!selectedElem) return;
    const token = `{${varName}}`;
    const content = selectedElem.content.includes(token)
      ? selectedElem.content
      : selectedElem.content.trim()
        ? `${selectedElem.content}${selectedElem.content.endsWith(' ') ? '' : ' '}${token}`
        : token;
    handleElemChange({ ...selectedElem, content });
  };

  const handleAddTemplateVariable = () => {
    const name = newVarName.trim();
    if (!name || name === '#INDEX') return;
    const list = new Set<string>(template.variableList ?? extractTemplateVariables(template));
    list.add(name);
    onChangeTemplate({
      ...template,
      variableList: Array.from(list).sort((a, b) => a.localeCompare(b, 'zh-CN')),
    });
    setNewVarName('');
  };

  const handleRemoveTemplateVariable = (varName: string) => {
    if (isTemplateVariableInUse(template, varName)) return;
    onChangeTemplate(removeUnusedTemplateVariable(template, varName));
  };

  const setVariableDefault = (varName: string, value: string) => {
    const defaults = { ...(template.variableDefaults || {}) };
    if (value.trim()) {
      defaults[varName] = value;
    } else {
      delete defaults[varName];
    }
    onChangeTemplate({
      ...template,
      variableDefaults: Object.keys(defaults).length > 0 ? defaults : undefined,
    });
  };

  const renderVariableManagementBlock = () => (
    <div className="space-y-2 pt-2 border-t border-[#3a3a3a]">
      <div className="text-[10px] font-bold text-[#31a8ff]">变量管理</div>
      <p className="text-[10px] text-[#666] leading-relaxed">
        在此添加模板变量并设置设计预览默认值；不会自动写入元素内容，请使用「插入变量到内容」。未被内容或显示条件引用的变量可删除。
      </p>
      <div className="flex gap-1">
        <input
          type="text"
          value={newVarName}
          onChange={(e) => setNewVarName(e.target.value)}
          onKeyDown={(e) => e.key === 'Enter' && handleAddTemplateVariable()}
          placeholder="新变量名"
          className="ps-field text-[10px] flex-1 min-w-0"
        />
        <button
          type="button"
          onClick={handleAddTemplateVariable}
          className="ps-btn shrink-0 text-[10px]"
        >
          <Plus className="w-3 h-3" />
          添加
        </button>
      </div>
      {templateVariables.length === 0 ? (
        <p className="text-[10px] text-[#888]">暂无变量</p>
      ) : (
        <div className="space-y-1">
          {templateVariables.map((v) => {
            const inUse = isTemplateVariableInUse(template, v);
            return (
              <div
                key={v}
                className="grid grid-cols-[72px_minmax(0,1fr)_44px] gap-1 items-center min-w-0"
              >
                <span
                  className="text-[9px] font-mono text-[#31a8ff] truncate"
                  title={v}
                >
                  {`{${v}}`}
                </span>
                <input
                  type="text"
                  value={template.variableDefaults?.[v] ?? ''}
                  onChange={(e) => setVariableDefault(v, e.target.value)}
                  placeholder="预览默认值"
                  className="ps-field font-mono text-[10px] w-full min-w-0"
                />
                <div className="flex items-center justify-center w-[44px] shrink-0">
                  {inUse ? (
                    <span
                      className="p-1 text-[#666] cursor-default"
                      title="已被内容或显示条件引用，不可删除"
                    >
                      <Lock className="w-3.5 h-3.5" />
                    </span>
                  ) : (
                    <button
                      type="button"
                      onClick={() => handleRemoveTemplateVariable(v)}
                      title="删除未使用的变量"
                      className="p-1 rounded text-[#666] hover:text-red-400 hover:bg-[#3a2020] transition-colors"
                    >
                      <Trash2 className="w-3.5 h-3.5" />
                    </button>
                  )}
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );

  // Layer ordering movement
  const moveLayer = (idx: number, direction: 'up' | 'down' | 'top' | 'bottom') => {
    const list = [...template.elements];
    const item = list[idx];
    if (!item) return;

    if (direction === 'up') {
      if (idx >= list.length - 1) return;
      list.splice(idx, 1);
      list.splice(idx + 1, 0, item);
    } else if (direction === 'down') {
      if (idx <= 0) return;
      list.splice(idx, 1);
      list.splice(idx - 1, 0, item);
    } else if (direction === 'top') {
      if (idx >= list.length - 1) return;
      list.splice(idx, 1);
      list.push(item);
    } else if (direction === 'bottom') {
      if (idx <= 0) return;
      list.splice(idx, 1);
      list.unshift(item);
    }

    onChangeTemplate({ ...template, elements: list });
  };

  const toggleLockLayer = (idx: number) => {
    const list = template.elements.map((el, i) => {
      if (i === idx) {
        return { ...el, locked: !el.locked };
      }
      return el;
    });
    onChangeTemplate({ ...template, elements: list });
  };

  const deleteLayer = (id: string) => {
    const el = template.elements.find(x => x.id === id);
    if (el?.locked) return; // Cannot delete locked elements
    onChangeTemplate({
      ...template,
      elements: template.elements.filter((el) => el.id !== id),
    });
    if (onSelectElements && selectedElementIds.includes(id)) {
      onSelectElements([]);
    }
  };

  const renderContentPanelBody = () => {
    if (!selectedElem) {
      return (
        <div className="space-y-3">
          <p className="text-[10px] text-[#777] leading-normal flex items-start gap-1">
            <HelpCircle className="w-3.5 h-3.5 text-[#31a8ff] shrink-0 mt-0.5" />
            <span>选中元素后可编辑内容与显示控制</span>
          </p>
          {renderVariableManagementBlock()}
        </div>
      );
    }

    return (
      <div className="space-y-2 min-w-0 max-w-full overflow-hidden">
        {selectedElem.type === 'image' && (
          <div>
            <label className="ps-field-label">本地图片</label>
            <label className="ps-btn text-[10px] cursor-pointer">
              <Upload className="w-3.5 h-3.5" />
              选择文件
              <input
                type="file"
                accept="image/*"
                className="hidden"
                onChange={(e) => {
                  const file = e.target.files?.[0];
                  if (!file) return;
                  const reader = new FileReader();
                  reader.onload = () =>
                    handleElemChange({ ...selectedElem, content: reader.result as string });
                  reader.readAsDataURL(file);
                  e.target.value = '';
                }}
              />
            </label>
          </div>
        )}
        <PropTextarea
          value={selectedElem.content}
          onCommit={(val) => handleElemChange({ ...selectedElem, content: val })}
          rows={selectedElem.type === 'image' ? 3 : 2}
          className="ps-field resize-none"
          placeholder={
            selectedElem.type === 'image'
              ? '图片 URL 或 data URI，也可使用 {变量名}'
              : '输入文本，使用 {变量名} 引用变量'
          }
        />
        {templateVariables.length > 0 && (
          <div className="space-y-1">
            <div className="text-[9px] text-[#777] font-medium">插入变量到内容</div>
            <div className="flex flex-wrap gap-1">
              {templateVariables.map((v) => (
                <button
                  key={v}
                  type="button"
                  onClick={() => insertVariable(v)}
                  className="ps-btn text-[9px] font-mono"
                >
                  {`{${v}}`}
                </button>
              ))}
            </div>
          </div>
        )}
        {renderVariableManagementBlock()}
        <div className="space-y-2 pt-2 border-t border-[#3a3a3a] min-w-0 max-w-full overflow-hidden">
          <div className="text-[10px] font-bold text-[#31a8ff]">显示控制</div>
          <div>
            <label className="ps-field-label">显示模式</label>
            <select
              value={isConditionalVisibility(selectedElem) ? 'conditional' : 'always'}
              onChange={(e) => {
                const conditional = e.target.value === 'conditional';
                if (!conditional) {
                  handleElemChange({
                    ...selectedElem,
                    visibilityMode: 'always',
                    hideWhenNoData: undefined,
                    visibilityVariable: undefined,
                    visibilityVariables: undefined,
                  });
                  return;
                }
                const migrated = resolveVisibilityRules(selectedElem);
                handleElemChange({
                  ...selectedElem,
                  visibilityMode: 'conditional',
                  visibilityRules: migrated.length > 0 ? migrated : [],
                  hideWhenNoData: undefined,
                  visibilityVariable: undefined,
                  visibilityVariables: undefined,
                });
              }}
              className="ps-field text-[11px]"
            >
              <option value="always">始终显示</option>
              <option value="conditional">按条件显示</option>
            </select>
          </div>
          {isConditionalVisibility(selectedElem) && (() => {
            const rules = resolveVisibilityRules(selectedElem);

            const setRules = (next: VisibilityRule[]) => {
              handleElemChange({
                ...selectedElem,
                visibilityMode: 'conditional',
                visibilityRules: next,
                hideWhenNoData: undefined,
                visibilityVariable: undefined,
                visibilityVariables: undefined,
              });
            };

            const removeRule = (index: number) => {
              setRules(rules.filter((_, i) => i !== index));
            };

            return (
              <div className="space-y-2 min-w-0 max-w-full">
                <p className="text-[10px] text-[#666] leading-relaxed">
                  全部条件满足时才显示。设计预览按变量默认值判断，导出按数据行（或映射默认值）判断。
                </p>
                {rules.length > 0 ? (
                  <div className="space-y-1.5">
                    {rules.map((rule, index) => (
                      <VisibilityRuleSummary
                        key={`${rule.variable}-${index}`}
                        rule={rule}
                        onEdit={() => setVisibilityRuleDialog({ mode: 'edit', index })}
                        onDelete={() => removeRule(index)}
                      />
                    ))}
                  </div>
                ) : (
                  <p className="text-[10px] text-[#888]">尚未添加显示条件</p>
                )}
                <button
                  type="button"
                  onClick={() => setVisibilityRuleDialog({ mode: 'add' })}
                  disabled={addableVisibilityVariables.length === 0}
                  className="ps-btn w-full text-[10px] justify-center disabled:opacity-40"
                  title={
                    addableVisibilityVariables.length === 0
                      ? '请先在变量管理中添加变量，或所有变量已添加条件'
                      : undefined
                  }
                >
                  <Plus className="w-3 h-3" />
                  添加条件
                </button>
              </div>
            );
          })()}
        </div>
      </div>
    );
  };

  return (
    <div className="ps-sidebar-stack">
      <VisibilityRuleDialog
        open={visibilityRuleDialog !== null}
        mode={visibilityRuleDialog?.mode ?? 'add'}
        initialRule={editingVisibilityRule}
        variableOptions={visibilityRuleDialogVariableOptions}
        onClose={() => setVisibilityRuleDialog(null)}
        onConfirm={handleConfirmVisibilityRule}
      />
      <CollapsiblePanelSection
        sectionClassName="content-panel"
        collapsed={panelCollapsed.content}
        onToggle={() => togglePanel('content')}
        icon={<Link2 className="w-3.5 h-3.5 text-[#31a8ff] shrink-0" />}
        title="内容"
        bodyClassName="ps-panel-body p-3 min-h-0"
      >
        {renderContentPanelBody()}
      </CollapsiblePanelSection>

      <CollapsiblePanelSection
        sectionClassName="properties-panel flex flex-col"
        collapsed={panelCollapsed.properties}
        onToggle={() => togglePanel('properties')}
        icon={<Sliders className="w-3.5 h-3.5 text-[#31a8ff] shrink-0" />}
        title="属性"
        headerExtra={
          selectedElem ? (
            <span className="text-[10px] text-[#999] font-normal truncate max-w-[100px]">
              {selectedElem.name}
            </span>
          ) : null
        }
        bodyClassName="ps-panel-body p-3 space-y-4 min-h-0"
      >
        <>
          {/* Label Canvas Dimensions */}
          {!selectedElem && (
            <div className="space-y-4">
              <div className="space-y-3">
                <h4 className="text-[10px] font-bold uppercase tracking-widest mb-1">
                  文档尺寸
                </h4>
                <div className="grid grid-cols-2 gap-3">
                    <div>
                      <label className="ps-field-label">宽度 (mm)</label>
                      <PropInput
                        type="number"
                        min="10"
                        max={maxLabelW}
                        value={template.width}
                        onCommit={(val) => {
                          const wVal = Math.min(maxLabelW, Math.max(10, Number(val) || 10));
                          // Also sanitize elements that might now be out of bounds
                          const sanitizedElements = template.elements.map(el => {
                            const newX = Math.min(wVal - el.width, el.x);
                            const newW = Math.min(wVal - Math.max(0, newX), el.width);
                            return { ...el, x: Math.max(0, newX), width: Math.max(2, newW) };
                          });
                          onChangeTemplate({ ...template, width: wVal, elements: sanitizedElements });
                        }}
                        className="ps-field font-mono"
                      />
                    </div>
                    <div>
                      <label className="ps-field-label">高度 (mm)</label>
                      <PropInput
                        type="number"
                        min="10"
                        max={maxLabelH}
                        value={template.height}
                        onCommit={(val) => {
                          const hVal = Math.min(maxLabelH, Math.max(10, Number(val) || 10));
                          // Also sanitize elements that might now be out of bounds
                          const sanitizedElements = template.elements.map(el => {
                            const newY = Math.min(hVal - el.height, el.y);
                            const newH = Math.min(hVal - Math.max(0, newY), el.height);
                            return {
                              ...el,
                              y: Math.max(0, newY),
                              height: el.type === 'qrcode' ? Math.max(2, newH) : Math.max(2, newH),
                              width: el.type === 'qrcode' ? Math.max(2, newH) : el.width
                            };
                          });
                          onChangeTemplate({ ...template, height: hVal, elements: sanitizedElements });
                        }}
                        className="ps-field font-mono"
                      />
                    </div>
                  </div>
                  <p className="text-[10px] text-[#777] leading-normal flex items-center gap-1 bg-[#1e1e1e] p-2 border border-[#3a3a3a]">
                    <HelpCircle className="w-3.5 h-3.5 text-[#31a8ff] shrink-0" />
                    <span>点击画布元素以编辑属性，或在下方图层面板中选择。</span>
                  </p>
                </div>
              </div>
            )}

            {/* Selected Element Adjust Properties */}
            {selectedElem && (
              <div className="space-y-4">
                {selectedElementIds.length >= 2 && (
                  <div className="bg-[#1e1e1e] border border-[#3a3a3a] p-3 space-y-3">
                    <span className="text-[10px] bg-[#31a8ff] text-white font-bold px-1.5 py-0.5 inline-block">
                      多选 ({selectedElementIds.length})
                    </span>
                    <div className="space-y-1.5">
                      <span className="text-[10px] font-semibold text-[#aaa]">对齐选区</span>
                      <p className="text-[10px] text-[#666] leading-snug">
                        调整各元素在选区内的相对位置
                      </p>
                      {renderAlignButtonGrid((mode) => applyMultiAlign(mode), 'selection')}
                    </div>
                    <div className="space-y-1.5">
                      <span className="text-[10px] font-semibold text-[#aaa]">画布对齐</span>
                      <p className="text-[10px] text-[#666] leading-snug">
                        将选中元素作为整体，相对画布 {template.width}×{template.height} mm 对齐
                      </p>
                      {renderAlignButtonGrid((mode) => applyCanvasAlign(mode), 'canvas')}
                    </div>
                    <div className="space-y-1.5">
                      <span className="text-[10px] font-semibold text-[#aaa]">排列选中</span>
                      <div className="grid grid-cols-2 gap-1.5">
                        <AlignToolButton
                          icon={<AlignHorizontalSpaceBetween className="w-3.5 h-3.5" />}
                          label="水平等距平铺"
                          title="在选区宽度内水平等距排列"
                          onClick={() => applyTile('horizontal')}
                        />
                        <AlignToolButton
                          icon={<AlignVerticalSpaceBetween className="w-3.5 h-3.5" />}
                          label="垂直等距平铺"
                          title="在选区高度内垂直等距排列"
                          onClick={() => applyTile('vertical')}
                        />
                      </div>
                    </div>
                  </div>
                )}

                <div className="space-y-1">
                  <div className="text-[10px] font-bold text-[#31a8ff] uppercase tracking-widest leading-none">
                    图层名称
                  </div>
                  <PropInput
                    type="text"
                    value={selectedElem.name}
                    onCommit={(val) => handleElemChange({ ...selectedElem, name: val || '未命名元素' })}
                    className="ps-field mt-2"
                  />
                </div>

                {/* Alignment Tools */}
                <div className="space-y-1.5">
                  <h5 className="ps-section-title">
                    对齐与分布
                  </h5>
                  <div className="grid grid-cols-3 gap-1.5">
                    <AlignToolButton
                      icon={<AlignHorizontalJustifyStart className="w-3.5 h-3.5" />}
                      label="左对齐"
                      title="靠左对齐 (X=0)"
                      onClick={() => handleElemChange({ ...selectedElem, x: 0 })}
                    />
                    <AlignToolButton
                      icon={<AlignHorizontalJustifyCenter className="w-3.5 h-3.5" />}
                      label="水平居中"
                      title="水平居中对齐"
                      onClick={() => {
                        const newX = Math.round(((template.width - selectedElem.width) / 2) * 10) / 10;
                        handleElemChange({ ...selectedElem, x: Math.max(0, newX) });
                      }}
                    />
                    <AlignToolButton
                      icon={<AlignHorizontalJustifyEnd className="w-3.5 h-3.5" />}
                      label="右对齐"
                      title="靠右对齐"
                      onClick={() => {
                        const newX = Math.round((template.width - selectedElem.width) * 10) / 10;
                        handleElemChange({ ...selectedElem, x: Math.max(0, newX) });
                      }}
                    />
                    <AlignToolButton
                      icon={<AlignVerticalJustifyStart className="w-3.5 h-3.5" />}
                      label="顶对齐"
                      title="靠顶对齐 (Y=0)"
                      onClick={() => handleElemChange({ ...selectedElem, y: 0 })}
                    />
                    <AlignToolButton
                      icon={<AlignVerticalJustifyCenter className="w-3.5 h-3.5" />}
                      label="垂直居中"
                      title="垂直居中对齐"
                      onClick={() => {
                        const newY = Math.round(((template.height - selectedElem.height) / 2) * 10) / 10;
                        handleElemChange({ ...selectedElem, y: Math.max(0, newY) });
                      }}
                    />
                    <AlignToolButton
                      icon={<AlignVerticalJustifyEnd className="w-3.5 h-3.5" />}
                      label="底对齐"
                      title="靠底对齐"
                      onClick={() => {
                        const newY = Math.round((template.height - selectedElem.height) * 10) / 10;
                        handleElemChange({ ...selectedElem, y: Math.max(0, newY) });
                      }}
                    />
                  </div>
                </div>

                {/* Text Settings */}
                {selectedElem.type === 'text' && (
                  <div className="space-y-3 ps-section-divider">
                    <h5 className="ps-section-title">
                      <Type className="w-3.5 h-3.5" />
                      字体排版设置
                    </h5>
                    <div className="grid grid-cols-2 gap-2">
                      <div>
                        <label className="ps-field-label">显示格式</label>
                        <select
                          value={selectedElem.textFormat || 'text'}
                          onChange={(e) =>
                            handleElemChange({
                              ...selectedElem,
                              textFormat: e.target.value as 'text' | 'number' | 'percent' | 'currency',
                              decimalPlaces:
                                e.target.value === 'text'
                                  ? selectedElem.decimalPlaces
                                  : selectedElem.decimalPlaces ?? 2,
                            })
                          }
                          className="ps-field"
                        >
                          <option value="text">文本</option>
                          <option value="number">数值</option>
                          <option value="percent">百分比</option>
                          <option value="currency">货币 (¥)</option>
                        </select>
                      </div>
                      {(selectedElem.textFormat === 'number' ||
                        selectedElem.textFormat === 'percent' ||
                        selectedElem.textFormat === 'currency') && (
                        <>
                          <div>
                            <label className="ps-field-label">小数位数</label>
                            <PropInput
                              type="number"
                              min="0"
                              max="6"
                              value={selectedElem.decimalPlaces ?? 2}
                              onCommit={(val) =>
                                handleElemChange({
                                  ...selectedElem,
                                  decimalPlaces: Math.max(0, Math.min(6, Number(val) || 0)),
                                })
                              }
                              className="ps-field font-mono"
                            />
                          </div>
                          <div className="col-span-2">
                            <label className="ps-field-label">数值显示部分</label>
                            <select
                              value={selectedElem.numberPartDisplay ?? 'full'}
                              onChange={(e) =>
                                handleElemChange({
                                  ...selectedElem,
                                  numberPartDisplay: e.target.value as
                                    | 'full'
                                    | 'integer'
                                    | 'fraction',
                                })
                              }
                              className="ps-field"
                            >
                              <option value="full">完整数值</option>
                              <option value="integer">仅整数部分（如 19.9 → 19）</option>
                              <option value="fraction">仅小数部分（如 19.9 → .9）</option>
                            </select>
                            <p className="text-[9px] text-[#666] mt-1 leading-relaxed">
                              可将价格拆成两个文本元素分别设置字号，如「19」与「.9」
                            </p>
                          </div>
                        </>
                      )}
                    </div>

                    <div className="grid grid-cols-2 gap-2">
                      <div>
                        <label className="ps-field-label">字号 (pt)</label>
                        <PropInput
                          type="number"
                          min="6"
                          max="80"
                          value={selectedElem.fontSize}
                          onCommit={(val) =>
                            handleElemChange({ ...selectedElem, fontSize: Number(val) || 12 })
                          }
                          className="ps-field font-mono"
                        />
                      </div>
                      <div>
                        <label className="ps-field-label">字体库</label>
                        <select
                           value={selectedElem.fontFamily}
                          onChange={(e) =>
                            handleElemChange({
                              ...selectedElem,
                              fontFamily: e.target.value as 'sans' | 'serif' | 'mono',
                            })
                          }
                          className="ps-field"
                        >
                          <option value="sans">黑体 (Sans)</option>
                          <option value="serif">宋体 (Serif)</option>
                          <option value="mono">等宽体 (Mono)</option>
                        </select>
                      </div>
                    </div>

                    {/* Text color */}
                    <div className="border-t border-[#3a3a3a] pt-2.5">
                      <label className="block text-[10px] font-semibold text-[#777] mb-1">文本颜色</label>
                      <div className="flex gap-1 items-center">
                        <input
                          type="color"
                          value={selectedElem.textColor || '#111827'}
                          onChange={(e) => handleElemChange({ ...selectedElem, textColor: e.target.value })}
                          className="color-input shrink-0"
                        />
                        <input
                          type="text"
                          placeholder="#111827"
                          value={selectedElem.textColor || ''}
                          onChange={(e) => handleElemChange({ ...selectedElem, textColor: e.target.value })}
                          className="ps-field font-mono text-[11px] flex-1 min-w-0"
                        />
                      </div>
                    </div>

                    <div className="space-y-2">
                      <label className="ps-field-label mb-0">文本样式</label>
                      <div className="flex flex-wrap items-center gap-2">
                        <button
                          type="button"
                          onClick={() =>
                            handleElemChange({
                              ...selectedElem,
                              fontWeight: selectedElem.fontWeight === 'bold' ? 'normal' : 'bold',
                            })
                          }
                          className={`ps-btn ${selectedElem.fontWeight === 'bold' ? 'active' : ''}`}
                          title="加粗"
                        >
                          <Bold className="w-3.5 h-3.5" />
                        </button>
                        <button
                          type="button"
                          onClick={() =>
                            handleElemChange({
                              ...selectedElem,
                              fontStyle:
                                selectedElem.fontStyle === 'italic' ? 'normal' : 'italic',
                            })
                          }
                          className={`ps-btn ${selectedElem.fontStyle === 'italic' ? 'active' : ''}`}
                          title="斜体"
                        >
                          <Italic className="w-3.5 h-3.5" />
                        </button>
                        <button
                          type="button"
                          onClick={() =>
                            handleElemChange({
                              ...selectedElem,
                              textUnderline: !selectedElem.textUnderline,
                            })
                          }
                          className={`ps-btn ${selectedElem.textUnderline ? 'active' : ''}`}
                          title="下划线"
                        >
                          <Underline className="w-3.5 h-3.5" />
                        </button>
                        <button
                          type="button"
                          onClick={() =>
                            handleElemChange({
                              ...selectedElem,
                              textLineThrough: !selectedElem.textLineThrough,
                            })
                          }
                          className={`ps-btn ${selectedElem.textLineThrough ? 'active' : ''}`}
                          title="删除线"
                        >
                          <Strikethrough className="w-3.5 h-3.5" />
                        </button>
                      </div>
                    </div>

                    <div className="grid grid-cols-3 gap-2">
                      <div>
                        <label className="ps-field-label">水平拉伸</label>
                        <PropInput
                          type="number"
                          min="10"
                          max="500"
                          step="5"
                          value={Math.round((selectedElem.textScaleX ?? 1) * 100)}
                          onCommit={(val) =>
                            handleElemChange({
                              ...selectedElem,
                              textScaleX: Math.max(0.1, Math.min(5, (Number(val) || 100) / 100)),
                            })
                          }
                          className="ps-field font-mono"
                        />
                        <p className="text-[9px] text-[#666] mt-0.5">%</p>
                      </div>
                      <div>
                        <label className="ps-field-label">垂直拉伸</label>
                        <PropInput
                          type="number"
                          min="10"
                          max="500"
                          step="5"
                          value={Math.round((selectedElem.textScaleY ?? 1) * 100)}
                          onCommit={(val) =>
                            handleElemChange({
                              ...selectedElem,
                              textScaleY: Math.max(0.1, Math.min(5, (Number(val) || 100) / 100)),
                            })
                          }
                          className="ps-field font-mono"
                        />
                        <p className="text-[9px] text-[#666] mt-0.5">%</p>
                      </div>
                      <div>
                        <label className="ps-field-label">字间距</label>
                        <PropInput
                          type="number"
                          min="0"
                          max="10"
                          step="0.1"
                          value={selectedElem.letterSpacing ?? 0}
                          onCommit={(val) =>
                            handleElemChange({
                              ...selectedElem,
                              letterSpacing: Math.max(0, Math.min(10, Number(val) || 0)),
                            })
                          }
                          className="ps-field font-mono"
                        />
                        <p className="text-[9px] text-[#666] mt-0.5">mm</p>
                      </div>
                    </div>

                    <div className="space-y-2">
                      <label className="ps-field-label mb-0">排列方向</label>
                      <div className="ps-toggle-group">
                        <button
                          type="button"
                          onClick={() =>
                            handleElemChange({ ...selectedElem, textWritingMode: 'horizontal' })
                          }
                          className={`ps-toggle-btn ${(selectedElem.textWritingMode ?? 'horizontal') === 'horizontal' ? 'active' : ''}`}
                          title="横排"
                        >
                          横排
                        </button>
                        <button
                          type="button"
                          onClick={() =>
                            handleElemChange({ ...selectedElem, textWritingMode: 'vertical' })
                          }
                          className={`ps-toggle-btn ${selectedElem.textWritingMode === 'vertical' ? 'active' : ''}`}
                          title="竖排"
                        >
                          竖排
                        </button>
                      </div>
                    </div>

                    <div className="space-y-2">
                      <label className="ps-field-label mb-0">对齐方式</label>
                      <div className="flex flex-wrap items-center gap-2">
                        <div className="ps-toggle-group">
                          <button
                            type="button"
                            onClick={() => handleElemChange({ ...selectedElem, textAlign: 'left' })}
                            className={`ps-toggle-btn ${selectedElem.textAlign === 'left' ? 'active' : ''}`}
                            title="左对齐"
                          >
                            <AlignLeft className="w-3.5 h-3.5" />
                          </button>
                          <button
                            type="button"
                            onClick={() => handleElemChange({ ...selectedElem, textAlign: 'center' })}
                            className={`ps-toggle-btn ${selectedElem.textAlign === 'center' ? 'active' : ''}`}
                            title="水平居中"
                          >
                            <AlignCenter className="w-3.5 h-3.5" />
                          </button>
                          <button
                            type="button"
                            onClick={() => handleElemChange({ ...selectedElem, textAlign: 'right' })}
                            className={`ps-toggle-btn ${selectedElem.textAlign === 'right' ? 'active' : ''}`}
                            title="右对齐"
                          >
                            <AlignRight className="w-3.5 h-3.5" />
                          </button>
                        </div>
                        <div className="ps-toggle-group">
                          <button
                            type="button"
                            onClick={() => handleElemChange({ ...selectedElem, verticalAlign: 'top' })}
                            className={`ps-toggle-btn ${(selectedElem.verticalAlign ?? 'middle') === 'top' ? 'active' : ''}`}
                            title="顶对齐"
                          >
                            <AlignVerticalJustifyStart className="w-3.5 h-3.5" />
                          </button>
                          <button
                            type="button"
                            onClick={() => handleElemChange({ ...selectedElem, verticalAlign: 'middle' })}
                            className={`ps-toggle-btn ${(selectedElem.verticalAlign ?? 'middle') === 'middle' ? 'active' : ''}`}
                            title="垂直居中"
                          >
                            <AlignVerticalJustifyCenter className="w-3.5 h-3.5" />
                          </button>
                          <button
                            type="button"
                            onClick={() => handleElemChange({ ...selectedElem, verticalAlign: 'bottom' })}
                            className={`ps-toggle-btn ${(selectedElem.verticalAlign ?? 'middle') === 'bottom' ? 'active' : ''}`}
                            title="底对齐"
                          >
                            <AlignVerticalJustifyEnd className="w-3.5 h-3.5" />
                          </button>
                        </div>
                      </div>
                    </div>

                    <label className="flex items-center gap-2 cursor-pointer">
                      <input
                        type="checkbox"
                        checked={selectedElem.wordWrap !== false}
                        onChange={(e) => handleElemChange({ ...selectedElem, wordWrap: e.target.checked })}
                        className="ps-checkbox"
                      />
                      <span className="text-[12px] text-[#ccc]">自动换行</span>
                    </label>
                  </div>
                )}

                {/* Barcode Settings */}
                {selectedElem.type === 'barcode' && (
                  <div className="space-y-3 ps-section-divider">
                    <h5 className="ps-section-title">
                      <Barcode className="w-3.5 h-3.5" />
                      条形码特定格式
                    </h5>
                    <div>
                      <label className="ps-field-label">条码码制</label>
                      <select
                        value={selectedElem.barcodeFormat}
                        onChange={(e) =>
                          handleElemChange({
                            ...selectedElem,
                            barcodeFormat: e.target.value as 'CODE128' | 'CODE39' | 'EAN13' | 'ITF',
                          })
                        }
                        className="ps-field"
                      >
                        <option value="CODE128">CODE 128 (推荐 · 常用)</option>
                        <option value="CODE39">CODE 39 (数字和字符)</option>
                        <option value="EAN13">EAN 13 (纯商品数字 13位)</option>
                        <option value="ITF">ITF (交插双五码)</option>
                      </select>
                    </div>

                    <label className="flex items-center gap-2 cursor-pointer mt-1">
                      <input
                        type="checkbox"
                        checked={selectedElem.showText}
                        onChange={(e) => handleElemChange({ ...selectedElem, showText: e.target.checked })}
                        className="ps-checkbox"
                      />
                      <span className="text-xs font-semibold text-[#ccc]">显示下方文字 (Human Readable)</span>
                    </label>
                  </div>
                )}

                {/* Image Settings */}
                {selectedElem.type === 'image' && (
                  <div className="space-y-3 ps-section-divider">
                    <h5 className="ps-section-title">
                      <ImageIcon className="w-3.5 h-3.5" />
                      图片设置
                    </h5>
                    <div>
                      <label className="ps-field-label">适应方式</label>
                      <select
                        value={selectedElem.imageFit ?? 'contain'}
                        onChange={(e) =>
                          handleElemChange({
                            ...selectedElem,
                            imageFit: e.target.value as 'contain' | 'cover' | 'fill',
                          })
                        }
                        className="ps-field"
                      >
                        <option value="contain">包含 (contain)</option>
                        <option value="cover">覆盖 (cover)</option>
                        <option value="fill">拉伸 (fill)</option>
                      </select>
                    </div>
                  </div>
                )}

                {/* Positions (X, Y) and Sizes (W, H) */}
                <div className="space-y-3">
                  <h5 className="ps-section-title">
                    <Ruler className="w-3.5 h-3.5" />
                    位置与尺寸 (mm)
                  </h5>
                  <div className="grid grid-cols-2 gap-3">
                    <div>
                      <label className="ps-field-label">X 坐标 (左边距)</label>
                      <PropInput
                        type="number"
                        step="0.5"
                        value={selectedElem.x}
                        onCommit={(val) => {
                          handleElemChange({
                            ...selectedElem,
                            x: Math.round((Number(val) || 0) * 10) / 10,
                          });
                        }}
                        className="ps-field font-mono"
                      />
                    </div>
                    <div>
                      <label className="ps-field-label">Y 坐标 (顶边距)</label>
                      <PropInput
                        type="number"
                        step="0.5"
                        value={selectedElem.y}
                        onCommit={(val) => {
                          handleElemChange({
                            ...selectedElem,
                            y: Math.round((Number(val) || 0) * 10) / 10,
                          });
                        }}
                        className="ps-field font-mono"
                      />
                    </div>
                    <div>
                      <label className="ps-field-label">元素宽度</label>
                      <PropInput
                        type="number"
                        step="0.5"
                        min="2"
                        value={selectedElem.width}
                        onCommit={(val) => {
                          const wVal = Math.max(2, Number(val) || 2);
                          const updated = { ...selectedElem, width: wVal };
                          if (selectedElem.type === 'qrcode') {
                            updated.height = wVal;
                          }
                          handleElemChange(updated);
                        }}
                        className="ps-field font-mono"
                      />
                    </div>
                    <div>
                      <label className="ps-field-label">元素高度</label>
                      <PropInput
                        type="number"
                        step="0.5"
                        min="2"
                        value={selectedElem.height}
                        disabled={selectedElem.type === 'qrcode'}
                        onCommit={(val) => {
                          const hVal = Math.max(2, Number(val) || 2);
                          handleElemChange({ ...selectedElem, height: hVal });
                        }}
                        className={`ps-field font-mono ${
                          selectedElem.type === 'qrcode' ? 'opacity-50 select-none' : ''
                        }`}
                      />
                    </div>
                    <div className="col-span-2">
                      <label className="ps-field-label flex items-center gap-1">
                        旋转角度（度）
                      </label>
                      <div className="flex items-center gap-2">
                        <PropInput
                          type="number"
                          step="1"
                          min="-360"
                          max="360"
                          value={selectedElem.rotation ?? 0}
                          onCommit={(val) => {
                            let deg = Number(val) || 0;
                            deg = ((deg % 360) + 360) % 360;
                            handleElemChange({ ...selectedElem, rotation: deg });
                          }}
                          className="ps-field font-mono flex-1"
                        />
                      </div>
                    </div>
                  </div>
                </div>

                {/* Background — all element types */}
                <div className="space-y-2 ps-section-divider">
                  <h5 className="ps-section-title">
                    背景
                  </h5>
                  <div className="flex justify-between items-center mb-1">
                    <span className="text-[10px] text-[#777]">颜色</span>
                    <button
                      type="button"
                      onClick={() =>
                        handleElemChange({
                          ...selectedElem,
                          backgroundColor: 'transparent',
                          backgroundOpacity: 0,
                        })
                      }
                      className="text-[9px] text-[#31a8ff] hover:underline cursor-pointer"
                    >
                      透明
                    </button>
                  </div>
                  <div className="flex gap-1 items-center">
                    <input
                      type="color"
                      value={
                        selectedElem.backgroundColor &&
                        selectedElem.backgroundColor !== 'transparent'
                          ? selectedElem.backgroundColor
                          : '#ffffff'
                      }
                      onChange={(e) =>
                        handleElemChange({
                          ...selectedElem,
                          backgroundColor: e.target.value,
                          backgroundOpacity:
                            selectedElem.backgroundOpacity && selectedElem.backgroundOpacity > 0
                              ? selectedElem.backgroundOpacity
                              : 100,
                        })
                      }
                      className="color-input shrink-0"
                    />
                    <input
                      type="text"
                      placeholder="transparent"
                      value={
                        selectedElem.backgroundColor === 'transparent'
                          ? 'transparent'
                          : selectedElem.backgroundColor || ''
                      }
                      onChange={(e) => {
                        const v = e.target.value.trim();
                        if (v === 'transparent' || v === '') {
                          handleElemChange({
                            ...selectedElem,
                            backgroundColor: 'transparent',
                            backgroundOpacity: 0,
                          });
                        } else {
                          handleElemChange({
                            ...selectedElem,
                            backgroundColor: v,
                            backgroundOpacity: selectedElem.backgroundOpacity ?? 100,
                          });
                        }
                      }}
                      className="ps-field font-mono text-[11px] flex-1 min-w-0"
                    />
                  </div>
                  <div>
                    <div className="flex justify-between items-center mb-1">
                      <span className="text-[10px] text-[#777]">不透明度</span>
                      <span className="text-[10px] text-[#999] font-mono">
                        {selectedElem.backgroundColor === 'transparent'
                          ? 0
                          : selectedElem.backgroundOpacity ?? 100}
                        %
                      </span>
                    </div>
                    <input
                      type="range"
                      min="0"
                      max="100"
                      step="1"
                      value={
                        selectedElem.backgroundColor === 'transparent'
                          ? 0
                          : selectedElem.backgroundOpacity ?? 100
                      }
                      onChange={(e) => {
                        const op = Number(e.target.value);
                        if (op <= 0) {
                          handleElemChange({
                            ...selectedElem,
                            backgroundColor: 'transparent',
                            backgroundOpacity: 0,
                          });
                        } else {
                          handleElemChange({
                            ...selectedElem,
                            backgroundColor:
                              selectedElem.backgroundColor &&
                              selectedElem.backgroundColor !== 'transparent'
                                ? selectedElem.backgroundColor
                                : '#ffffff',
                            backgroundOpacity: op,
                          });
                        }
                      }}
                      className="ps-range"
                    />
                  </div>
                  <div className="border-t border-[#3a3a3a] pt-2.5 space-y-2">
                    <label className="ps-field-label">内边距 (mm)</label>
                    <PropInput
                      type="number"
                      min="0"
                      max="10"
                      step="0.5"
                      value={selectedElem.padding ?? 0}
                      onCommit={(val) =>
                        handleElemChange({
                          ...selectedElem,
                          padding: Math.max(0, Math.min(10, Number(val) || 0)),
                        })
                      }
                      className="ps-field font-mono"
                    />
                    <div>
                      <label className="ps-field-label">各边独立内边距 (mm，留空用统一值)</label>
                      <div className="grid grid-cols-2 gap-1.5">
                        {(
                          [
                            ['paddingTop', '上'],
                            ['paddingRight', '右'],
                            ['paddingBottom', '下'],
                            ['paddingLeft', '左'],
                          ] as const
                        ).map(([key, label]) => (
                          <div key={key} className="flex items-center gap-1">
                            <span className="text-[9px] text-[#777] w-6 shrink-0">{label}</span>
                            <PropInput
                              type="number"
                              min="0"
                              max="10"
                              step="0.5"
                              value={selectedElem[key] ?? ''}
                              onCommit={(val) => {
                                const updated = { ...selectedElem };
                                if (val === '' || val === undefined) {
                                  delete updated[key];
                                } else {
                                  updated[key] = Math.max(0, Math.min(10, Number(val) || 0));
                                }
                                handleElemChange(updated);
                              }}
                              className="ps-field font-mono text-[10px] flex-1 min-w-0"
                              placeholder="—"
                            />
                          </div>
                        ))}
                      </div>
                    </div>
                  </div>
                </div>

                {/* Border & radius */}
                <div className="space-y-2 ps-section-divider">
                  <h5 className="ps-section-title">边框与圆角</h5>

                  <div className="grid grid-cols-2 gap-2">
                    <div>
                      <label className="ps-field-label">边框宽度 (mm)</label>
                      <PropInput
                        type="number"
                        min="0"
                        max="5"
                        step="0.1"
                        value={selectedElem.borderWidth ?? 0}
                        onCommit={(val) =>
                          handleElemChange({
                            ...selectedElem,
                            borderWidth: Math.max(0, Math.min(5, Number(val) || 0)),
                            borderColor: selectedElem.borderColor || '#111827',
                          })
                        }
                        className="ps-field font-mono"
                      />
                    </div>
                    <div>
                      <label className="ps-field-label">圆角半径 (mm)</label>
                      <PropInput
                        type="number"
                        min="0"
                        max="20"
                        step="0.5"
                        value={selectedElem.borderRadius ?? 0}
                        onCommit={(val) =>
                          handleElemChange({
                            ...selectedElem,
                            borderRadius: Math.max(0, Math.min(20, Number(val) || 0)),
                          })
                        }
                        className="ps-field font-mono"
                      />
                    </div>
                  </div>

                  <div>
                    <label className="ps-field-label">边框颜色</label>
                    <div className="flex gap-1 items-center">
                      <input
                        type="color"
                        value={selectedElem.borderColor || '#111827'}
                        onChange={(e) =>
                          handleElemChange({
                            ...selectedElem,
                            borderColor: e.target.value,
                            borderWidth: selectedElem.borderWidth || 0.3,
                          })
                        }
                        className="color-input shrink-0"
                      />
                      <input
                        type="text"
                        value={selectedElem.borderColor || ''}
                        placeholder="#111827"
                        onChange={(e) =>
                          handleElemChange({
                            ...selectedElem,
                            borderColor: e.target.value,
                          })
                        }
                        className="ps-field font-mono text-[11px] flex-1 min-w-0"
                      />
                    </div>
                  </div>

                  <div>
                    <label className="ps-field-label">各边独立边框宽度 (mm，留空用统一值，0 为不显示)</label>
                    <div className="grid grid-cols-2 gap-1.5">
                      {(
                        [
                          ['borderWidthTop', '上'],
                          ['borderWidthRight', '右'],
                          ['borderWidthBottom', '下'],
                          ['borderWidthLeft', '左'],
                        ] as const
                      ).map(([key, label]) => (
                        <div key={key} className="flex items-center gap-1">
                          <span className="text-[9px] text-[#777] w-6 shrink-0">{label}</span>
                          <PropInput
                            type="number"
                            min="0"
                            max="5"
                            step="0.1"
                            value={selectedElem[key] ?? ''}
                            onCommit={(val) => {
                              const updated = { ...selectedElem };
                              if (val === '' || val === undefined) {
                                delete updated[key];
                              } else {
                                updated[key] = Math.max(0, Math.min(5, Number(val) || 0));
                              }
                              handleElemChange(updated);
                            }}
                            className="ps-field font-mono text-[10px] flex-1 min-w-0"
                            placeholder="—"
                          />
                        </div>
                      ))}
                    </div>
                  </div>

                  <div>
                    <label className="ps-field-label">各边独立边框颜色 (留空用统一值)</label>
                    <div className="grid grid-cols-2 gap-1.5">
                      {(
                        [
                          ['borderColorTop', '上'],
                          ['borderColorRight', '右'],
                          ['borderColorBottom', '下'],
                          ['borderColorLeft', '左'],
                        ] as const
                      ).map(([key, label]) => (
                        <div key={key} className="flex items-center gap-1 min-w-0">
                          <span className="text-[9px] text-[#777] w-6 shrink-0">{label}</span>
                          <input
                            type="color"
                            value={
                              selectedElem[key]?.trim() ||
                              selectedElem.borderColor ||
                              '#111827'
                            }
                            onChange={(e) => {
                              const updated = { ...selectedElem };
                              updated[key] = e.target.value;
                              handleElemChange(updated);
                            }}
                            className="color-input shrink-0 scale-90"
                            title={`${label}边边框颜色`}
                          />
                          <PropInput
                            type="text"
                            value={selectedElem[key] ?? ''}
                            onCommit={(val) => {
                              const updated = { ...selectedElem };
                              if (val === '' || val === undefined) {
                                delete updated[key];
                              } else {
                                updated[key] = val;
                              }
                              handleElemChange(updated);
                            }}
                            className="ps-field font-mono text-[10px] flex-1 min-w-0"
                            placeholder="—"
                          />
                        </div>
                      ))}
                    </div>
                  </div>

                  <div>
                    <label className="ps-field-label">各角独立圆角 (mm，留空用统一值)</label>
                    <div className="grid grid-cols-2 gap-1.5">
                      {(
                        [
                          ['borderRadiusTL', '左上'],
                          ['borderRadiusTR', '右上'],
                          ['borderRadiusBL', '左下'],
                          ['borderRadiusBR', '右下'],
                        ] as const
                      ).map(([key, label]) => (
                        <div key={key} className="flex items-center gap-1">
                          <span className="text-[9px] text-[#777] w-6 shrink-0">{label}</span>
                          <PropInput
                            type="number"
                            min="0"
                            max="20"
                            step="0.5"
                            value={selectedElem[key] ?? ''}
                            onCommit={(val) => {
                              const updated = { ...selectedElem };
                              if (val === '' || val === undefined) {
                                delete updated[key];
                              } else {
                                updated[key] = Math.max(0, Math.min(20, Number(val) || 0));
                              }
                              handleElemChange(updated);
                            }}
                            className="ps-field font-mono text-[10px] flex-1 min-w-0"
                            placeholder="—"
                          />
                        </div>
                      ))}
                    </div>
                  </div>
                </div>

              </div>
            )}

          </>
      </CollapsiblePanelSection>

      <CollapsiblePanelSection
        sectionClassName="layers-panel-section"
        collapsed={panelCollapsed.layers}
        onToggle={() => togglePanel('layers')}
        icon={<Layers className="w-3.5 h-3.5 shrink-0 text-[#31a8ff]" />}
        title="图层"
        headerExtra={
          <span className="text-[10px] text-[#666] font-mono">{template.elements.length}</span>
        }
        bodyClassName="ps-panel-body min-h-0"
      >
          {template.elements.length === 0 ? (
            <div className="text-[11px] text-[#666] text-center py-6">暂无图层</div>
          ) : (
            [...template.elements].reverse().map((elem, revIdx) => {
              const actualIdx = template.elements.length - 1 - revIdx;
              const isSelected = selectedElementIds.includes(elem.id);
              const isLocked = !!elem.locked;

              return (
                <div
                  key={elem.id}
                  onClick={(e) => {
                    if (!onSelectElements) return;
                    const isMulti = e.shiftKey || e.ctrlKey || e.metaKey;
                    if (isMulti) {
                      if (selectedElementIds.includes(elem.id)) {
                        onSelectElements(selectedElementIds.filter((id) => id !== elem.id));
                      } else {
                        onSelectElements([...selectedElementIds, elem.id]);
                      }
                    } else {
                      onSelectElements([elem.id]);
                    }
                  }}
                  className={`ps-layer-item group ${isSelected ? 'selected' : ''}`}
                >
                  <div className="flex items-center gap-2 min-w-0 flex-1">
                    <span className="shrink-0 w-3.5 flex items-center justify-center">
                      {elem.type === 'text' && <Type className="w-3 h-3 text-[#666]" />}
                      {elem.type === 'barcode' && <Barcode className="w-3 h-3 text-[#666]" />}
                      {elem.type === 'qrcode' && <QrCode className="w-3 h-3 text-[#666]" />}
                      {elem.type === 'image' && <ImageIcon className="w-3 h-3 text-[#666]" />}
                    </span>
                    <span className="truncate" title={elem.name}>
                      {elem.name}
                    </span>
                  </div>

                  <div className="flex items-center gap-0.5 shrink-0 opacity-0 group-hover:opacity-100 transition-opacity">
                    <button
                      type="button"
                      onClick={(e) => { e.stopPropagation(); moveLayer(actualIdx, 'up'); }}
                      disabled={actualIdx === template.elements.length - 1}
                      title="上移"
                      className="p-0.5 hover:bg-[#555] disabled:opacity-20 cursor-pointer text-[#aaa]"
                    >
                      <ArrowUp className="w-3 h-3" />
                    </button>
                    <button
                      type="button"
                      onClick={(e) => { e.stopPropagation(); moveLayer(actualIdx, 'down'); }}
                      disabled={actualIdx === 0}
                      title="下移"
                      className="p-0.5 hover:bg-[#555] disabled:opacity-20 cursor-pointer text-[#aaa]"
                    >
                      <ArrowDown className="w-3 h-3" />
                    </button>
                    <button
                      type="button"
                      onClick={(e) => { e.stopPropagation(); toggleLockLayer(actualIdx); }}
                      title={isLocked ? '解锁' : '锁定'}
                      className={`p-0.5 cursor-pointer ${isLocked ? 'text-amber-400' : 'text-[#666] hover:text-[#ccc]'}`}
                    >
                      {isLocked ? <Lock className="w-3 h-3" /> : <Unlock className="w-3 h-3" />}
                    </button>
                    <button
                      type="button"
                      onClick={(e) => { e.stopPropagation(); deleteLayer(elem.id); }}
                      disabled={isLocked}
                      title="删除"
                      className="p-0.5 hover:text-red-400 text-[#666] disabled:opacity-20 cursor-pointer"
                    >
                      <Trash2 className="w-3 h-3" />
                    </button>
                  </div>
                </div>
              );
            })
          )}
      </CollapsiblePanelSection>
    </div>
  );
};
