<!--
  功能：提供单个配送合同 PDF 附件的选择、拖拽、预览和移除控件。
  版本：v1.0.0
-->
<template>
  <div
    class="contract-file-control"
    :class="{ 'contract-file-disabled': disabled }"
    :tabindex="disabled ? -1 : 0"
    role="button"
    :aria-disabled="disabled"
    aria-label="选择合同附件 PDF"
    @click="openPicker"
    @keydown.enter.prevent="openPicker"
    @keydown.space.prevent="openPicker"
    @dragover.prevent
    @drop.prevent="selectDroppedFile"
  >
    <input
      ref="fileInput"
      class="contract-file-input"
      type="file"
      accept=".pdf,application/pdf"
      :disabled="disabled"
      @change="selectPickedFile"
    />
    <div class="contract-file-main">
      <icon-upload />
      <div>
        <strong>{{ title }}</strong>
        <div class="contract-file-hint">点击选择或拖拽 PDF，最大 10 MiB</div>
        <div v-if="attachment.requiresReupload" class="contract-file-warning">
          旧附件地址不可用，请重新上传
        </div>
      </div>
    </div>
    <a-space @click.stop @keydown.stop>
      <a-button
        v-if="attachment.available && !attachment.selectedFile && !attachment.removed"
        size="small"
        @click="emit('preview')"
      >
        <template #icon><icon-eye /></template>预览
      </a-button>
      <a-button
        v-if="attachment.selectedFile"
        size="small"
        @click="emit('clear-selection')"
      >
        取消选择
      </a-button>
      <a-button
        v-else-if="attachment.hasExisting && !attachment.removed"
        size="small"
        status="danger"
        @click="emit('remove')"
      >
        <template #icon><icon-delete /></template>移除
      </a-button>
    </a-space>
  </div>
</template>

<script setup lang="ts">
import { IconDelete, IconEye, IconUpload } from '@arco-design/web-vue/es/icon';
import { computed, ref } from 'vue';

export type ContractAttachmentFieldState = {
  selectedFile?: File;
  hasExisting: boolean;
  available: boolean;
  requiresReupload: boolean;
  removed: boolean;
};

const props = defineProps<{
  attachment: ContractAttachmentFieldState;
  disabled?: boolean;
}>();

const emit = defineEmits<{
  select: [file: File];
  remove: [];
  'clear-selection': [];
  preview: [];
}>();

const fileInput = ref<HTMLInputElement>();
const title = computed(() => {
  if (props.attachment.selectedFile) return props.attachment.selectedFile.name;
  if (props.attachment.removed) return '未选择合同附件';
  if (props.attachment.hasExisting) return '合同附件.pdf';
  return '选择合同附件';
});

/** 打开组件内唯一的原生文件选择器。 */
function openPicker() {
  if (!props.disabled) fileInput.value?.click();
}

/** 读取点击选择的单个文件，并允许再次选择同名文件。 */
function selectPickedFile(event: Event) {
  const input = event.target as HTMLInputElement;
  const file = input.files?.[0];
  if (file) emit('select', file);
  input.value = '';
}

/** 接收拖拽到控件上的第一个文件。 */
function selectDroppedFile(event: DragEvent) {
  if (props.disabled) return;
  const file = event.dataTransfer?.files?.[0];
  if (file) emit('select', file);
}
</script>

<style scoped lang="less">
.contract-file-control {
  display: flex;
  gap: 16px;
  align-items: center;
  justify-content: space-between;
  min-height: 88px;
  padding: 16px;
  cursor: pointer;
  border: 1px dashed var(--color-border-3);
  border-radius: 6px;
  outline: none;
  transition: border-color 0.2s, background 0.2s, box-shadow 0.2s;
}
.contract-file-control:hover,
.contract-file-control:focus-visible {
  background: var(--color-fill-1);
  border-color: rgb(var(--primary-6));
}
.contract-file-control:focus-visible {
  box-shadow: 0 0 0 2px rgba(var(--primary-6), 0.2);
}
.contract-file-disabled {
  cursor: not-allowed;
  opacity: 0.65;
}
.contract-file-input {
  display: none;
}
.contract-file-main {
  display: flex;
  gap: 12px;
  align-items: center;
  min-width: 0;
}
.contract-file-main strong {
  display: block;
  overflow: hidden;
  color: var(--color-text-1);
  text-overflow: ellipsis;
  white-space: nowrap;
}
.contract-file-hint {
  margin-top: 4px;
  color: var(--color-text-3);
  font-size: 12px;
}
.contract-file-warning {
  margin-top: 4px;
  color: rgb(var(--warning-6));
  font-size: 12px;
}
</style>
