<script lang="ts" setup>
/**
 * 按 payload_schema 动态渲染消息内容表单（场景与定时任务共用）
 * 支持 TemplateCard / NewsList / LinkList / GalleryPickLink(acceptTypes) 等
 * v-model 绑定整份 payload 对象
 */
import { computed } from 'vue';

import {
  Input,
  InputNumber,
  RadioGroup,
  Select,
  Textarea,
} from 'ant-design-vue';

import UploadImage from '#/components/form/components/upload-image.vue';
import UploadOssFile from '#/components/form/components/upload-oss-file.vue';
import ButtonList from '#/views/system/oa-scene/components/payload-lists/button-list.vue';
import LinkList from '#/views/system/oa-scene/components/payload-lists/link-list.vue';
import NewsList from '#/views/system/oa-scene/components/payload-lists/news-list.vue';
import PostEditor from '#/views/system/oa-scene/components/payload-lists/post-editor.vue';
import TemplateCardForm from '#/views/system/oa-scene/components/template-card-form.vue';

export interface PayloadFieldSchema {
  name: string;
  label: string;
  component: string;
  required?: boolean;
  props?: Record<string, any>;
}

const props = defineProps<{
  /** payload_schema 解析后的字段列表 */
  schema: PayloadFieldSchema[];
  /** 当前消息 payload */
  modelValue: Record<string, any>;
}>();

const emit = defineEmits<{
  (e: 'update:modelValue', v: Record<string, any>): void;
}>();

const payload = computed({
  get() {
    return props.modelValue && typeof props.modelValue === 'object'
      ? props.modelValue
      : {};
  },
  set(v: Record<string, any>) {
    emit('update:modelValue', v || {});
  },
});

function getValue(fieldName: string): any {
  return payload.value?.[fieldName];
}

function setValue(fieldName: string, value: any) {
  payload.value = { ...payload.value, [fieldName]: value };
}

/**
 * 解析字段 acceptTypes
 * 兼容两套约定：场景种子常用 0=图片；xk_file_type 常用 1=图片
 */
function fieldAcceptTypes(field: PayloadFieldSchema): number[] {
  const raw = field.props?.acceptTypes;
  if (Array.isArray(raw) && raw.length > 0) {
    return raw.map(Number).filter((n) => !Number.isNaN(n));
  }
  return [0, 1];
}

function isImageMediaField(field: PayloadFieldSchema) {
  const types = fieldAcceptTypes(field);
  // 仅图片类型走图片上传器
  return types.every((t) => t === 0 || t === 1);
}

function imageUrlsOf(fieldName: string): string[] {
  const url = getValue(fieldName);
  return url ? [String(url)] : [];
}

function setImageUrls(fieldName: string, urls: string[]) {
  setValue(fieldName, urls[0] || '');
}

function fileInputAccept(field: PayloadFieldSchema) {
  const types = fieldAcceptTypes(field);
  if (types.includes(3) || types.includes(2)) {
    return 'audio/*,.amr,.mp3,.wav';
  }
  return '.pdf,.doc,.docx,.zip,.rar,.txt,application/pdf,*/*';
}
</script>

<template>
  <div class="payload-schema-form">
    <template v-for="field in schema" :key="field.name">
      <div
        v-if="field.component === 'TemplateCardEditor'"
        class="payload-row"
      >
        <label class="payload-label">{{ field.label }}</label>
        <TemplateCardForm
          :model-value="getValue('template_card') || {}"
          @update:model-value="(val) => setValue('template_card', val)"
        />
      </div>

      <div v-else-if="field.component === 'NewsList'" class="payload-row">
        <label class="payload-label">
          {{ field.label }}
          <span v-if="field.required" class="required">*</span>
        </label>
        <NewsList
          :model-value="getValue(field.name) || []"
          :max-count="field.props?.maxCount || 8"
          @update:model-value="(val) => setValue(field.name, val)"
        />
      </div>

      <div v-else-if="field.component === 'ButtonList'" class="payload-row">
        <label class="payload-label">
          {{ field.label }}
          <span v-if="field.required" class="required">*</span>
        </label>
        <ButtonList
          :model-value="getValue(field.name) || []"
          :max-count="field.props?.maxCount || 6"
          @update:model-value="(val) => setValue(field.name, val)"
        />
      </div>

      <div v-else-if="field.component === 'LinkList'" class="payload-row">
        <label class="payload-label">
          {{ field.label }}
          <span v-if="field.required" class="required">*</span>
        </label>
        <LinkList
          :model-value="getValue(field.name) || []"
          :max-count="field.props?.maxCount || 10"
          @update:model-value="(val) => setValue(field.name, val)"
        />
      </div>

      <div v-else-if="field.component === 'PostEditor'" class="payload-row">
        <label class="payload-label">
          {{ field.label }}
          <span v-if="field.required" class="required">*</span>
        </label>
        <PostEditor
          :model-value="getValue(field.name) || {}"
          @update:model-value="(val) => setValue(field.name, val)"
        />
      </div>

      <div
        v-else-if="field.component === 'GalleryPickLink'"
        class="payload-row"
      >
        <label class="payload-label">
          {{ field.label }}
          <span v-if="field.required" class="required">*</span>
        </label>
        <UploadImage
          v-if="isImageMediaField(field)"
          :model-value="imageUrlsOf(field.name)"
          :multiple="false"
          :max-count="1"
          :accept-types="fieldAcceptTypes(field)"
          @update:model-value="(urls) => setImageUrls(field.name, urls)"
        />
        <UploadOssFile
          v-else
          :model-value="getValue(field.name) || ''"
          :max-count="1"
          :accept-types="fieldAcceptTypes(field)"
          :accept="fileInputAccept(field)"
          @update:model-value="(url) => setValue(field.name, url || '')"
        />
      </div>

      <div v-else-if="field.component === 'Textarea'" class="payload-row">
        <label class="payload-label">
          {{ field.label }}
          <span v-if="field.required" class="required">*</span>
        </label>
        <Textarea
          :value="getValue(field.name)"
          :rows="field.props?.rows || 3"
          :placeholder="field.props?.placeholder"
          @update:value="(val) => setValue(field.name, val)"
        />
      </div>

      <div v-else-if="field.component === 'RadioGroup'" class="payload-row">
        <label class="payload-label">
          {{ field.label }}
          <span v-if="field.required" class="required">*</span>
        </label>
        <RadioGroup
          :value="getValue(field.name)"
          :options="field.props?.options"
          @update:value="(val) => setValue(field.name, val)"
        />
      </div>

      <div v-else-if="field.component === 'Select'" class="payload-row">
        <label class="payload-label">
          {{ field.label }}
          <span v-if="field.required" class="required">*</span>
        </label>
        <Select
          :value="getValue(field.name)"
          :options="field.props?.options"
          :placeholder="field.props?.placeholder"
          style="width: 100%"
          @update:value="(val) => setValue(field.name, val)"
        />
      </div>

      <div v-else-if="field.component === 'InputNumber'" class="payload-row">
        <label class="payload-label">
          {{ field.label }}
          <span v-if="field.required" class="required">*</span>
        </label>
        <InputNumber
          :value="getValue(field.name)"
          :placeholder="field.props?.placeholder"
          style="width: 100%"
          @update:value="(val) => setValue(field.name, val)"
        />
      </div>

      <div v-else class="payload-row">
        <label class="payload-label">
          {{ field.label }}
          <span v-if="field.required" class="required">*</span>
        </label>
        <Input
          :value="getValue(field.name)"
          :placeholder="field.props?.placeholder"
          @update:value="(val) => setValue(field.name, val)"
        />
      </div>
    </template>
    <div v-if="!schema?.length" class="empty-hint">该消息类型无需配置内容</div>
  </div>
</template>

<style scoped>
.payload-schema-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.payload-row {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.payload-label {
  font-size: 13px;
  color: rgba(0, 0, 0, 0.85);
}
.required {
  color: #ff4d4f;
  margin-left: 2px;
}
.empty-hint {
  font-size: 13px;
  color: rgba(0, 0, 0, 0.45);
}
</style>
