<script setup lang="ts">
/**
 * OA 场景 - 飞书 post 富文本编辑器（简化版）
 *
 * 用于 feishu 平台 post 消息类型编辑。
 * 后端期望结构（FeishuChannel::buildPayload case 'post'）：
 *   {
 *     zh_cn: {
 *       title: string,
 *       content: [[ {tag:'text', text}, {tag:'a', href, text}, ... ]]
 *     }
 *   }
 *
 * 简化方案：每段一个 Textarea（一行节点），段内用 markdown 风格表达链接：
 *   - `[文字](url)` → { tag:'a', href:url, text:文字 }
 *   - 其余文字     → { tag:'text', text:文字 }
 *
 * 不支持复杂富文本（图片/at/表情等节点），用户选项 all-four 表示"要能用"即可。
 */
import { computed } from 'vue';

import { Button, Input, Textarea } from 'ant-design-vue';

interface PostNode {
  tag: 'text' | 'a';
  text: string;
  href?: string;
}

interface FeishuPost {
  zh_cn?: {
    title?: string;
    content?: PostNode[][];
  };
}

const props = withDefaults(
  defineProps<{
    /** 双向绑定的 post 数据（含 zh_cn 包裹） */
    modelValue?: FeishuPost;
  }>(),
  {
    modelValue: () => ({}),
  },
);

const emit = defineEmits<{
  'update:modelValue': [value: FeishuPost];
}>();

/** 标题（双向） */
const title = computed<string>({
  get: () => props.modelValue?.zh_cn?.title || '',
  set: (val) => emitValue(val, paragraphs.value),
});

/** 段落（双向；每段是原始字符串，提交时解析为 PostNode[]） */
const paragraphs = computed<string[]>({
  get: () => props.modelValue?.zh_cn?.content?.map(stringifyNodes) ?? [],
  set: (val) => emitValue(title.value, val),
});

function emitValue(newTitle: string, newParagraphs: string[]) {
  emit('update:modelValue', {
    zh_cn: {
      title: newTitle,
      content: newParagraphs.map(parseParagraph).filter((p) => p.length > 0),
    },
  });
}

/**
 * 把一段文本解析为飞书 post 节点数组
 * 支持 markdown 风格链接：[text](url)
 */
function parseParagraph(text: string): PostNode[] {
  if (!text) return [];
  const nodes: PostNode[] = [];
  // 链接正则：[文字](url)，url 必须以 http(s):// 开头
  const regex = /\[([^\]]+)\]\((https?:\/\/[^\s)]+)\)/g;
  let lastIndex = 0;
  let match: RegExpExecArray | null;
  while ((match = regex.exec(text)) !== null) {
    if (match.index > lastIndex) {
      nodes.push({ tag: 'text', text: text.slice(lastIndex, match.index) });
    }
    nodes.push({ tag: 'a', text: match[1]!, href: match[2]! });
    lastIndex = regex.lastIndex;
  }
  if (lastIndex < text.length) {
    nodes.push({ tag: 'text', text: text.slice(lastIndex) });
  }
  return nodes;
}

/** 反向：把节点数组还原为可编辑的字符串（[文字](url)） */
function stringifyNodes(nodes: PostNode[] | undefined): string {
  if (!Array.isArray(nodes) || nodes.length === 0) return '';
  return nodes
    .map((n) => {
      if (n.tag === 'a' && n.href) {
        return `[${n.text}](${n.href})`;
      }
      return n.text || '';
    })
    .join('');
}

function updateParagraph(index: number, value: string) {
  const next = [...paragraphs.value];
  next[index] = value;
  paragraphs.value = next;
}

function addParagraph() {
  paragraphs.value = [...paragraphs.value, ''];
}

function removeParagraph(index: number) {
  paragraphs.value = paragraphs.value.filter((_, i) => i !== index);
}
</script>

<template>
  <div class="post-editor">
    <div class="form-row">
      <label class="row-label">标题</label>
      <Input
        :value="title"
        placeholder="富文本标题（可选）"
        size="small"
        allow-clear
        @update:value="(v: string) => (title = v)"
      />
    </div>

    <div class="paragraphs">
      <div
        v-for="(p, idx) in paragraphs"
        :key="idx"
        class="paragraph-row"
      >
        <div class="paragraph-head">
          <span class="paragraph-index">段落 {{ idx + 1 }}</span>
          <Button
            type="link"
            size="small"
            danger
            class="paragraph-del"
            @click="removeParagraph(idx)"
          >
            删除
          </Button>
        </div>
        <Textarea
          :value="p"
          :rows="2"
          size="small"
          placeholder="支持 [文字](https://链接) 语法"
          @update:value="(v: string) => updateParagraph(idx, v)"
        />
      </div>
    </div>

    <Button type="dashed" size="small" block @click="addParagraph">
      + 添加段落
    </Button>

    <div class="hint">
      提示：链接语法 <code>[文字](https://...)</code>，其他文字原样作为文本节点
    </div>
  </div>
</template>

<style scoped lang="scss">
.post-editor {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
}

.form-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.row-label {
  font-size: 11px;
  color: var(--ant-color-text-secondary, #4e5969);
}

.paragraphs {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.paragraph-row {
  padding: 4px 6px;
  border: 1px solid var(--ant-color-border-secondary, #e5e6eb);
  border-radius: 4px;
}

.paragraph-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 2px;
}

.paragraph-index {
  font-size: 11px;
  font-weight: 600;
  color: var(--ant-color-text-secondary, #4e5969);
}

.paragraph-del {
  padding: 0 4px;
  height: auto;
  font-size: 12px;
}

.hint {
  font-size: 11px;
  color: var(--ant-color-text-tertiary, #86909c);

  code {
    padding: 1px 4px;
    border-radius: 2px;
    font-family: 'JetBrains Mono', monospace;
  }
}
</style>
