<script setup lang="ts">
import { computed, ref, watch, onUnmounted } from 'vue'
import { NInput, NPopover } from 'naive-ui'
import { api } from '@/shared/api/common'

const props = defineProps<{ df: any; record: Record<string, any>; canEdit: boolean; ctx: any }>()

// Label布局:上下结构(vertical) 或 左右结构(horizontal)
const labelLayout = computed(() => props.df.label_layout || 'vertical')

// 密码校验相关状态
const showValidationPopover = ref(false)
const validationMessage = ref('')
let validationTimer: ReturnType<typeof setTimeout> | null = null

// 仅对new_password字段进行前端校验
const shouldValidate = computed(() => props.df.fieldname === 'new_password')

// 监听密码输入变化
watch(() => props.record[props.df.fieldname], (newValue) => {
  if (!shouldValidate.value || !newValue || !props.canEdit) {
    showValidationPopover.value = false
    return
  }

  // 防抖处理：延迟300ms后执行校验
  if (validationTimer) {
    clearTimeout(validationTimer)
  }
  
  validationTimer = setTimeout(() => {
    validatePassword(newValue)
  }, 300)
})

// 前端密码格式校验
function validatePassword(password: string) {
  if (!password || password.length === 0) {
    showValidationPopover.value = false
    return
  }

  const errors: string[] = []
  
  // 最小长度检查（通常8位）
  if (password.length < 8) {
    errors.push(props.ctx.t('Password must be at least 8 characters'))
  }
  
  // 检查是否包含小写字母
  if (!/[a-z]/.test(password)) {
    errors.push(props.ctx.t('Password must contain lowercase letters'))
  }
  
  // 检查是否包含大写字母
  if (!/[A-Z]/.test(password)) {
    errors.push(props.ctx.t('Password must contain uppercase letters'))
  }
  
  // 检查是否包含数字
  if (!/[0-9]/.test(password)) {
    errors.push(props.ctx.t('Password must contain numbers'))
  }
  
  // 检查是否包含特殊字符
  if (!/[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(password)) {
    errors.push(props.ctx.t('Password must contain special characters'))
  }
  
  // 如果有错误，显示提示
  if (errors.length > 0) {
    validationMessage.value = props.ctx.t('Password strength insufficient') + '：' + errors.join('、')
    showValidationPopover.value = true
  } else {
    showValidationPopover.value = false
  }
}

// 清理定时器
const cleanupTimer = () => {
  if (validationTimer) {
    clearTimeout(validationTimer)
    validationTimer = null
  }
}

// 组件卸载时清理
onUnmounted(() => {
  cleanupTimer()
})

// Administrator 解密密码
const isAdministrator = computed(() => {
  const boot = (window as any).jingrow?.boot
  return boot?.user?.name === 'Administrator' || boot?.user?.roles?.includes?.('Administrator')
})

const visible = ref(false)
const revealing = ref(false)

const inputType = computed(() => visible.value ? 'text' : 'password')

function isDummyPassword(val: string | undefined | null): boolean {
  if (!val) return false
  return [...new Set(val)].join('') === '*'
}

const pagetype = computed(() =>
  (props.ctx?.entity && (props.ctx.entity.value ?? props.ctx.entity))
  || (props.record as any)?.pagetype
  || ''
)
const pagename = computed(() =>
  (props.ctx?.id && (props.ctx.id.value ?? props.ctx.id))
  || (props.record as any)?.name
  || ''
)

async function toggleVisible() {
  if (visible.value) {
    visible.value = false
    return
  }
  const currentValue = props.record[props.df.fieldname]
  if (isDummyPassword(currentValue) && pagetype.value && pagename.value) {
    revealing.value = true
    try {
      const res = await api.call('jingrow.client.get_password', {
        pagetype: pagetype.value,
        name: pagename.value,
        fieldname: props.df.fieldname,
      })
      const decrypted = res?.message ?? res
      if (decrypted) {
        props.record[props.df.fieldname] = decrypted
      }
    } catch {
      // 无权限等，仍切换显示
    } finally {
      revealing.value = false
    }
  }
  visible.value = true
}
</script>

<template>
  <div :class="['field-wrapper', `layout-${labelLayout}`]">
    <label class="field-label">
      {{ ctx.t(df.label || df.fieldname) }}
      <span v-if="df.reqd" class="required">*</span>
    </label>
    <n-popover
      v-if="shouldValidate"
      :show="showValidationPopover"
      trigger="manual"
      placement="bottom-start"
      :show-arrow="true"
      style="max-width: 400px"
    >
      <template #trigger>
        <div class="password-input-wrap">
          <n-input 
            v-model:value="record[df.fieldname]" 
            :type="inputType"
            placeholder=""
            :disabled="!canEdit"
            :loading="revealing"
            :status="showValidationPopover ? 'error' : undefined"
          />
          <button 
            v-if="canEdit && isAdministrator"
            type="button" 
            class="password-toggle-btn" 
            @click="toggleVisible"
          >
            <svg v-if="visible" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94"/><path d="M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
            <svg v-else xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
          </button>
        </div>
      </template>
      <div class="password-validation-message">
        {{ validationMessage }}
      </div>
    </n-popover>
    <div v-else class="password-input-wrap">
      <n-input 
        v-model:value="record[df.fieldname]" 
        :type="inputType"
        placeholder=""
        :disabled="!canEdit"
        :loading="revealing"
      />
      <button 
        v-if="canEdit && isAdministrator"
        type="button" 
        class="password-toggle-btn" 
        @click="toggleVisible"
      >
        <svg v-if="visible" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94"/><path d="M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19"/><line x1="1" y1="1" x2="23" y2="23"/></svg>
        <svg v-else xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
      </button>
    </div>
  </div>
</template>

<style scoped>
.field-wrapper :deep(.n-input) {
  flex: 1;
}
.password-input-wrap {
  position: relative;
  flex: 1;
  display: flex;
  align-items: center;
}
.password-input-wrap :deep(.n-input) {
  flex: 1;
  padding-right: 32px;
}
.password-toggle-btn {
  position: absolute;
  right: 8px;
  background: none;
  border: none;
  cursor: pointer;
  color: #999;
  padding: 2px;
  display: flex;
  align-items: center;
  z-index: 1;
}
.password-toggle-btn:hover {
  color: #333;
}
.password-validation-message {
  color: #d03050;
  font-size: 13px;
  line-height: 1.5;
  padding: 4px 0;
  white-space: pre-wrap;
  word-break: break-word;
}
</style>
