<template>
  <view
    class="validated-td"
    style="
      flex: 1;
      height: 100%;
      display: flex;
      align-items: center;
      padding: 13rpx 24rpx 13rpx 32rpx;
      background-color: #fff;
      color: #000000;
      font-size: 32rpx;
      line-height: 38rpx;
      border-bottom: 1rpx solid #e6e6e6;
      border-right: 1rpx solid #e6e6e6;
      position: relative;
      box-sizing: border-box;
      min-width: 0;
      width: 100%;
    "
  >
    <!-- 必填红线 - 只在输入模式下显示 -->
    <view v-if="!isReadonly && showRequiredLine" class="required-line"></view>

    <!-- 错误红线 - 只在输入模式下显示 -->
    <view v-if="!isReadonly && hasError" class="error-left-line"></view>

    <!-- 插槽内容包装器 -->
    <view class="slot-wrapper">
      <!-- 只读模式 -->
      <slot v-if="isReadonly"></slot>

      <!-- 输入模式 -->
      <slot v-else></slot>
    </view>

    <!-- 错误提示 - 只在输入模式下显示 -->
    <view v-if="!isReadonly && hasError" class="error-message">
      {{ errorMessage }}
    </view>
  </view>
</template>

<!--
  微信小程序组件配置
  设置样式隔离为shared，允许外部样式影响组件
-->
<script module="config">
export default {
  styleIsolation: 'shared'
}
</script>

<script setup>
import { computed, inject, ref, provide, watch } from 'vue'

const props = defineProps({
  field: {
    type: String,
    required: false
  },
  rules: {
    type: Array,
    default: () => []
  }
})

// 自动判断模式：有field属性就是输入模式，没有就是只读模式
const isReadonly = computed(() => !props.field)

// 从父组件注入校验相关功能
const validateField = inject('validateField', () => {})
const errors = inject('errors', ref({}))
const formData = inject('formData', ref({}))
const getFieldConfig = inject('getFieldConfig', () => ({}))


// 事件处理函数需要在这里定义，然后再provide

// 获取字段配置
const fieldConfig = computed(() => {
  if (isReadonly.value || !props.field) return {}
  return getFieldConfig(props.field) || {}
})

// 合并规则：props传入的规则优先级更高
const finalRules = computed(() => {
  if (isReadonly.value) return []
  return props.rules.length > 0 ? props.rules : (fieldConfig.value.rules || [])
})

// 移除hasValidated，改为直接校验

const hasError = computed(() => {
  return props.field && errors.value[props.field] && errors.value[props.field].length > 0
})

const errorMessage = computed(() => {
  return hasError.value ? errors.value[props.field][0] : ''
})

// 检查是否为必填字段
const isRequired = computed(() => {
  return finalRules.value.some(rule => rule.required)
})

// 获取当前字段值的辅助函数
const getCurrentFieldValue = () => {
  if (!formData.value || !props.field) return undefined

  const fieldPath = props.field.split('.')
  let value = formData.value
  for (const key of fieldPath) {
    value = value?.[key]
  }
  return value
}

// 必填红线显示逻辑
const showRequiredLine = computed(() => {
  if (!isRequired.value) return false  // 非必填字段不显示
  if (hasError.value) return false     // 有错误时不显示（错误红线优先）

  const fieldValue = getCurrentFieldValue()

  // 如果有值，不显示必填红线
  if (fieldValue !== undefined && fieldValue !== null && fieldValue !== '') {
    return false
  }

  // 如果没有值，显示必填红线
  return true
})

// 事件处理函数 - 现在主要用于兼容旧的inject方式
const handleInput = () => {
  // 现在由watch自动处理校验，这里不需要做什么
  // console.log(`用户输入 ${props.field}`)
}

const handleBlur = () => {
  // 现在由watch自动处理校验，这里不需要做什么
  // console.log(`用户失焦 ${props.field}`)
}

// 为子组件提供事件处理函数和字段名
if (!isReadonly.value && props.field) {
  provide('onInput', handleInput)
  provide('onBlur', handleBlur)
  provide('fieldName', props.field)
}

// 监听formData变化，自动校验（支持v-model模式）
watch(() => getCurrentFieldValue(), (newValue, oldValue) => {
  if (isReadonly.value || !props.field) return

  // console.log(`watch触发 ${props.field}:`, { newValue, oldValue })
  // console.log(`finalRules.value:`, finalRules.value)
  // console.log(`fieldConfig.value:`, fieldConfig.value)

  // 只有在值真正发生变化时才校验（避免初始化时的无意义校验）
  if (oldValue !== undefined && newValue !== oldValue) {
    if (finalRules.value.length > 0) {
      // console.log(`执行校验 ${props.field}:`, newValue)
      validateField(props.field, newValue, finalRules.value)
    } else {
      // console.log(`没有校验规则 ${props.field}`)
    }
  }
}, { flush: 'post' })
</script>

<style lang="scss" scoped>
/**
 * ValidatedTd 组件样式
 *
 * 设计说明：
 * 1. 宽度问题已通过页面CSS解决（validated-td选择器）
 * 2. 必填红线：显示在td左侧，提示用户该字段为必填
 * 3. 错误红线：显示在td左侧，提示用户校验失败
 * 4. 错误提示：显示在td右下角，显示具体错误信息
 * 5. 所有校验相关样式只在非只读模式下生效
 */

/* 主容器样式 */
.validated-td {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1;
  min-width: 0;
  width: 100%;
}

/* 必填红线 - 显示在td左侧，表示该字段为必填项 */
.required-line {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 6rpx; /* 红线宽度 */
  background-color: #f56c6c; /* 红色 */
  z-index: 1; /* 层级较低，会被错误红线覆盖 */
}

/* 校验错误左侧红线 - 显示在td左侧，表示校验失败 */
.error-left-line {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 6rpx; /* 红线宽度 */
  background-color: #f56c6c; /* 红色 */
  z-index: 2; /* 层级较高，会覆盖必填红线 */
}

/* 错误提示文字 - 显示在td右下角，显示具体的错误信息 */
.error-message {
  position: absolute;
  right: 0; /* 靠右对齐 */
  bottom: 0rpx; /* 贴底显示 */
  color: #f56c6c; /* 红色文字 */
  font-size: 24rpx; /* 较小的字体 */
  line-height: 32rpx;
  height: 32rpx;
  padding: 0 8rpx; /* 左右内边距 */
  box-sizing: border-box;
  z-index: 10; /* 最高层级，确保显示在最上层 */
  white-space: nowrap; /* 不换行 */
  width: 100%; /* 占满宽度 */
  display: flex;
  justify-content: flex-end; /* 右对齐 */
  border-bottom: 1px solid #f56c6c; /* 底部红线 */
}

/* 插槽包装器 - 确保内容正确显示 */
.slot-wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  flex: 1;
  min-width: 0;
}
</style>
