<script lang="ts" setup>
import type { SensitiveFieldSource } from '#/constants/sensitive-fields';

import { computed, ref } from 'vue';

import { useClipboard } from '@vueuse/core';
import { EyeInvisibleOutlined, EyeOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';

import {
  getSensitiveMaskText,
  getSensitivePlainText,
} from '#/constants/sensitive-fields';

const props = withDefaults(
  defineProps<{
    /** 数据对象 */
    record?: Record<string, unknown> | null;
    /** 字段名 */
    field: string;
    /** 主字段为空时的备选来源 */
    fallback?: SensitiveFieldSource;
    /** 空值占位 */
    emptyText?: string;
    /** 是否显示眼睛切换 */
    showEye?: boolean;
    /** 点击文本是否复制明文 */
    copyable?: boolean;
  }>(),
  {
    record: null,
    emptyText: '—',
    showEye: true,
    copyable: true,
  },
);

const revealed = ref(false);
const { copy } = useClipboard({ legacy: true });

/** 明文值，复制与展示切换时使用 */
const plainText = computed(() =>
  getSensitivePlainText(props.record, props.field, props.fallback),
);

/** 脱敏展示值 */
const maskText = computed(() =>
  getSensitiveMaskText(props.record, props.field, props.fallback),
);

/** 当前界面展示文本 */
const displayText = computed(() => {
  if (!plainText.value) {
    return props.emptyText;
  }
  return revealed.value ? plainText.value : maskText.value;
});

/** 是否有有效值（非空占位） */
const hasValue = computed(() => plainText.value !== '');

/**
 * 点击文本复制明文（脱敏前的原始值）
 */
async function handleCopyText() {
  if (!props.copyable || !hasValue.value) {
    return;
  }
  try {
    await copy(plainText.value);
    message.success('复制成功');
  } catch {
    message.error('复制失败');
  }
}

/**
 * 切换明文 / 脱敏展示
 */
function toggleReveal() {
  if (!hasValue.value) {
    return;
  }
  revealed.value = !revealed.value;
}
</script>

<template>
  <span class="sensitive-text">
    <span
      class="sensitive-text__value"
      :class="{ 'sensitive-text__value--copyable': copyable && hasValue }"
      @click="handleCopyText"
    >
      {{ displayText }}
    </span>
    <EyeOutlined
      v-if="showEye && hasValue && !revealed"
      class="sensitive-text__eye"
      @click.stop="toggleReveal"
    />
    <EyeInvisibleOutlined
      v-else-if="showEye && hasValue && revealed"
      class="sensitive-text__eye"
      @click.stop="toggleReveal"
    />
  </span>
</template>

<style scoped>
.sensitive-text {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  max-width: 100%;
}

.sensitive-text__value {
  word-break: break-all;
}

.sensitive-text__value--copyable {
  cursor: pointer;
}

.sensitive-text__value--copyable:hover {
  color: var(--ant-color-primary, #1677ff);
}

.sensitive-text__eye {
  flex-shrink: 0;
  font-size: 14px;
  color: rgba(0, 0, 0, 0.45);
  cursor: pointer;
  transition: color 0.2s;
}

.sensitive-text__eye :deep(svg) {
  fill: currentColor;
}

.sensitive-text__eye:hover {
  color: var(--ant-color-primary, #1677ff);
}

/* 暗色模式：避免 fallback 黑色导致图标不可见 */
.dark .sensitive-text__eye {
  color: rgba(255, 255, 255, 0.45);
}

.dark .sensitive-text__eye:hover {
  color: var(--ant-color-primary, #4096ff);
}

.dark .sensitive-text__value--copyable:hover {
  color: var(--ant-color-primary, #4096ff);
}
</style>
