const PROMPT_TEMPLATE_VARIABLES = [
  { name: "current_time", sample: "2026年06月11日 15时" },
  { name: "user_id", sample: "tenant-demo" },
  { name: "thread_id", sample: "thread_demo" },
  { name: "run_id", sample: "run_demo" },
  { name: "agent_id", sample: "agent_demo" },
  { name: "agent_name", sample: "Agent Demo" },
  { name: "skill_list", sample: "1. document-summary\n2. deep-research" },
  { name: "mcp_list", sample: "1. mcp_web_search" },
  { name: "attachments", sample: "1. input/example.pdf (application/pdf, 102400 bytes)" },
  { name: "meeting_id", sample: "meeting_demo", condition: true },
];

function isPromptVariableName(name) {
  return /^[A-Za-z_][A-Za-z0-9_]*$/.test(String(name || "").trim());
}

function uniquePromptVariables(items) {
  const seen = new Set();
  const out = [];
  for (const raw of items || []) {
    const name = String(raw || "").trim();
    if (!isPromptVariableName(name) || seen.has(name)) continue;
    seen.add(name);
    out.push(name);
  }
  return out;
}

function scanPromptVariables(template) {
  const re = /\{\{\s*([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g;
  const seen = new Set();
  const out = [];
  let m;
  while ((m = re.exec(template || ""))) {
    if (seen.has(m[1])) continue;
    seen.add(m[1]);
    out.push(m[1]);
  }
  return out;
}

function mergePromptVariables(template, extraVariables = []) {
  return uniquePromptVariables([
    ...scanPromptVariables(template || ""),
    ...(extraVariables || []),
  ]);
}

function previewPromptTemplate(template, variables) {
  let rendered = String(template || "");
  rendered = rendered.replace(/\{%\s*if\s+([A-Za-z_][A-Za-z0-9_]*)\s*%\}([\s\S]*?)\{%\s*endif\s*%\}/g, (_, key, body) => (
    variables[key] ? body : ""
  ));
  rendered = rendered.replace(/\{\{\s*([A-Za-z_][A-Za-z0-9_]*)\s*\}\}/g, (_, key) => {
    const value = variables[key];
    if (value == null) return "";
    if (typeof value === "object") return JSON.stringify(value);
    return String(value);
  });
  return rendered;
}

function samplePromptVariables(agent) {
  const out = {};
  for (const item of PROMPT_TEMPLATE_VARIABLES) out[item.name] = item.sample;
  for (const name of agent?.promptVariables || []) {
    if (out[name] === undefined) out[name] = `sample_${name}`;
  }
  out.agent_id = agent?.id || out.agent_id;
  out.agent_name = agent?.name || out.agent_name;
  return out;
}

function PromptTemplateEditor({
  value,
  onChange,
  agent,
  className = "textarea-lg",
  rows,
  style,
  placeholder,
}) {
  const textareaRef = React.useRef(null);
  const [selectedVariable, setSelectedVariable] = React.useState("current_time");
  const detectedVariables = React.useMemo(() => scanPromptVariables(value || ""), [value]);
  const savedPromptVariables = React.useMemo(
    () => uniquePromptVariables(agent?.promptVariables || []),
    [JSON.stringify(agent?.promptVariables || [])]
  );
  const variableChoices = React.useMemo(() => uniquePromptVariables([
    ...PROMPT_TEMPLATE_VARIABLES.map((item) => item.name),
    ...savedPromptVariables,
    ...detectedVariables,
  ]), [JSON.stringify(savedPromptVariables), JSON.stringify(detectedVariables)]);
  const sampleValues = React.useMemo(
    () => samplePromptVariables(agent),
    [agent?.id, agent?.name, JSON.stringify(agent?.promptVariables || [])]
  );
  const preview = React.useMemo(
    () => previewPromptTemplate(value || "", sampleValues),
    [value, sampleValues]
  );

  const update = (next) => onChange(next, mergePromptVariables(next));

  const insertText = (text, selectStartOffset = text.length, selectEndOffset = text.length) => {
    const textarea = textareaRef.current;
    const current = String(value || "");
    const start = textarea ? textarea.selectionStart : current.length;
    const end = textarea ? textarea.selectionEnd : current.length;
    const next = current.slice(0, start) + text + current.slice(end);
    update(next);
    requestAnimationFrame(() => {
      if (!textareaRef.current) return;
      textareaRef.current.focus();
      const cursorStart = start + selectStartOffset;
      const cursorEnd = start + selectEndOffset;
      textareaRef.current.setSelectionRange(cursorStart, cursorEnd);
    });
  };

  const insertVariable = (name) => insertText(`{{ ${name} }}`);

  const insertCondition = (name) => {
    const textarea = textareaRef.current;
    const current = String(value || "");
    const start = textarea ? textarea.selectionStart : current.length;
    const end = textarea ? textarea.selectionEnd : current.length;
    const selected = current.slice(start, end) || "content";
    const before = `{% if ${name} %}\n`;
    const after = `\n{% endif %}`;
    insertText(before + selected + after, before.length, before.length + selected.length);
  };
  const selectedName = variableChoices.includes(selectedVariable)
    ? selectedVariable
    : (variableChoices[0] || PROMPT_TEMPLATE_VARIABLES[0].name);
  const selectedMeta = PROMPT_TEMPLATE_VARIABLES.find((item) => item.name === selectedName)
    || { name: selectedName };

  return (
    <div className="prompt-template-editor">
      <textarea
        ref={textareaRef}
        className={className}
        rows={rows}
        style={style}
        value={value || ""}
        onChange={(e) => update(e.target.value)}
        placeholder={placeholder}
      />
      <div className="prompt-vars">
        <div className="prompt-vars-head">
          <span>Choose variable</span>
          <span className="desc">Use built-ins or variables already present in the prompt.</span>
        </div>
        <div className="prompt-var-chips">
          {variableChoices.map((name) => (
            <button
              key={name}
              type="button"
              className={"prompt-var-chip builtin" + (name === selectedName ? " selected" : "")}
              onClick={() => setSelectedVariable(name)}
              title={`Select ${name}`}
            >
              {name}
            </button>
          ))}
        </div>
        <div className="prompt-insert-panel">
          <div className="prompt-insert-title">
            <span>{selectedMeta.name}</span>
            <code>{`{{ ${selectedMeta.name} }}`}</code>
          </div>
          <div className="prompt-insert-actions">
            <button
              type="button"
              className="prompt-action-btn"
              onClick={() => insertVariable(selectedMeta.name)}
            >
              Insert value
            </button>
            <button
              type="button"
              className="prompt-action-btn condition"
              onClick={() => insertCondition(selectedMeta.name)}
            >
              Insert condition
            </button>
          </div>
          <div className="prompt-insert-help">
            <span><b>Insert value</b> writes the runtime value here.</span>
            <span><b>Insert condition</b> wraps text so it only appears when this value exists.</span>
          </div>
        </div>
        <div className="prompt-vars-row">
          <span className="prompt-vars-label">Detected</span>
          {detectedVariables.length ? detectedVariables.map((name) => (
            <span key={name} className="prompt-var-chip">
              {"{{ " + name + " }}"}
            </span>
          )) : <span className="prompt-var-empty">none</span>}
        </div>
        <details className="prompt-preview">
          <summary>Preview</summary>
          <pre>{preview || "(empty prompt)"}</pre>
        </details>
      </div>
    </div>
  );
}

window.PROMPT_TEMPLATE_VARIABLES = PROMPT_TEMPLATE_VARIABLES;
window.scanPromptVariables = scanPromptVariables;
window.previewPromptTemplate = previewPromptTemplate;
window.PromptTemplateEditor = PromptTemplateEditor;
