<script setup lang="ts">
import type { PropType } from 'vue';

import { ref } from 'vue';
import ElXMarkdown from 'vue-element-plus-x/es/XMarkdown/index.js';

import { $t } from '@easyflow/locales';

import { Document } from '@element-plus/icons-vue';
import { ElButton, ElEmpty, ElIcon, ElTag } from 'element-plus';

import {
  markdownRenderProps,
  resolveMarkdownContent,
} from '#/views/ai/documentCollection/markdown-content';

type RetrievalMode = 'HYBRID' | 'KEYWORD' | 'VECTOR';
type HitSource = 'BOTH' | 'KEYWORD' | 'VECTOR';

interface PreviewItem {
  sorting: number | string;
  content: string;
  renderMarkdown?: string;
  sourceFileName?: string;
  score?: number | string;
  hitSource?: HitSource;
}

const props = defineProps({
  hideScore: {
    type: Boolean,
    default: false,
  },
  data: {
    type: Array as () => PreviewItem[],
    default: () => [],
  },
  total: {
    type: Number,
    default: 0,
  },
  loading: {
    type: Boolean,
    default: false,
  },
  confirmImport: {
    type: Boolean,
    default: false,
  },
  disabledConfirm: {
    type: Boolean,
    default: false,
  },
  onCancel: {
    type: Function as PropType<() => void>,
    default: () => undefined,
  },
  onConfirm: {
    type: Function as PropType<() => void>,
    default: () => undefined,
  },
  isSearching: {
    type: Boolean,
    default: false,
  },
  retrievalMode: {
    type: String as () => RetrievalMode,
    default: 'HYBRID',
  },
});

const loadingStatus = ref(false);

const resolveHitSourceLabel = (hitSource?: HitSource) => {
  if (hitSource === 'VECTOR') {
    return $t('documentCollection.hitSources.vector');
  }
  if (hitSource === 'KEYWORD') {
    return $t('documentCollection.hitSources.keyword');
  }
  if (hitSource === 'BOTH') {
    return $t('documentCollection.hitSources.both');
  }
  return '';
};

const resolveDisplayHitSource = (
  hitSource: HitSource | undefined,
  retrievalMode: RetrievalMode,
) => {
  if (hitSource) {
    return hitSource;
  }
  if (retrievalMode === 'VECTOR') {
    return 'VECTOR' as HitSource;
  }
  if (retrievalMode === 'KEYWORD') {
    return 'KEYWORD' as HitSource;
  }
  return undefined;
};

const resolveHitSourceType = (hitSource?: HitSource) => {
  if (hitSource === 'VECTOR') {
    return 'success';
  }
  if (hitSource === 'KEYWORD') {
    return 'warning';
  }
  return 'info';
};

const resolvePreviewMarkdown = (item: PreviewItem) =>
  resolveMarkdownContent(item.renderMarkdown || item.content);

const resolveScoreLine = (item: PreviewItem) => {
  const pieces: string[] = [];
  if (
    !props.hideScore &&
    item.score !== undefined &&
    item.score !== null &&
    `${item.score}` !== ''
  ) {
    pieces.push(`${$t('documentCollection.similarityScore')}: ${item.score}`);
  }
  if (item.sourceFileName) {
    pieces.push(`来源: ${item.sourceFileName}`);
  }
  return pieces.join(' · ');
};

const handleCancel = () => {
  props.onCancel?.();
};

const handleConfirm = () => {
  props.onConfirm?.();
};

defineExpose({
  loadingContent: (state: boolean) => {
    loadingStatus.value = state;
  },
});
</script>

<template>
  <div class="preview-container" v-loading="loadingStatus">
    <div class="preview-header">
      <h3>
        <ElIcon class="header-icon" size="20">
          <Document />
        </ElIcon>
        {{
          isSearching
            ? $t('documentCollection.searchResults')
            : $t('documentCollection.documentPreview')
        }}
      </h3>
      <span class="preview-stats" v-if="props.data.length > 0">
        {{ $t('documentCollection.total') }}
        {{ total > 0 ? total : data.length }}
        {{ $t('documentCollection.segments') }}
      </span>
    </div>

    <div class="preview-content">
      <div v-if="data.length > 0" class="preview-list">
        <div v-for="(item, index) in data" :key="index" class="preview-item">
          <div class="preview-item__header">
            <div class="preview-item__meta">
              <div class="segment-badge">
                {{ item.sorting ?? index + 1 }}
              </div>
              <div v-if="resolveScoreLine(item)" class="score-text">
                {{ resolveScoreLine(item) }}
              </div>
            </div>
            <div
              v-if="resolveDisplayHitSource(item.hitSource, retrievalMode)"
              class="hit-source-row"
            >
              <ElTag
                size="small"
                effect="plain"
                :type="
                  resolveHitSourceType(
                    resolveDisplayHitSource(item.hitSource, retrievalMode),
                  )
                "
              >
                {{
                  resolveHitSourceLabel(
                    resolveDisplayHitSource(item.hitSource, retrievalMode),
                  )
                }}
              </ElTag>
            </div>
          </div>
          <div
            v-if="resolvePreviewMarkdown(item)"
            class="content-desc content-desc--markdown"
          >
            <ElXMarkdown
              :markdown="resolvePreviewMarkdown(item)"
              :allow-html="markdownRenderProps.allowHtml"
              :sanitize="markdownRenderProps.sanitize"
            />
          </div>
          <div v-else class="content-desc">
            {{ item.content }}
          </div>
        </div>
      </div>
      <ElEmpty
        v-else
        :description="
          isSearching
            ? $t('documentCollection.searchResults')
            : $t('documentCollection.documentPreview')
        "
      />
    </div>

    <div class="preview-actions" v-if="confirmImport">
      <div class="action-buttons">
        <ElButton
          :style="{ minWidth: '100px', height: '36px' }"
          @click="handleCancel"
        >
          {{ $t('documentCollection.actions.cancelImport') }}
        </ElButton>
        <ElButton
          type="primary"
          :style="{ minWidth: '100px', height: '36px' }"
          :loading="disabledConfirm"
          @click="handleConfirm"
        >
          {{ $t('documentCollection.actions.confirmImport') }}
        </ElButton>
      </div>
    </div>
  </div>
</template>

<style scoped>
.preview-container {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  min-height: 0;
  background-color: var(--el-bg-color);
  border: 1px solid rgb(15 23 42 / 6%);
  border-radius: 20px;

  .preview-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 16px 20px;
    border-bottom: 1px solid var(--el-border-color);

    h3 {
      display: flex;
      gap: 8px;
      align-items: center;
      margin: 0;
      font-size: 16px;
      font-weight: 500;
      color: var(--el-text-color-primary);

      .header-icon {
        color: var(--el-color-primary);
      }
    }

    .preview-stats {
      font-size: 14px;
      color: var(--el-text-color-secondary);
    }
  }

  .preview-content {
    flex: 1;
    padding: 18px 20px;
    overflow: hidden auto;

    .preview-list {
      display: flex;
      flex-direction: column;
      gap: 18px;

      .segment-badge {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 24px;
        height: 24px;
        font-size: 12px;
        font-weight: 500;
        color: var(--el-color-primary);
        background-color: var(--el-color-primary-light-9);
        border-radius: 50%;
      }

      .content-desc {
        width: 100%;
        padding: 14px 16px;
        font-size: 14px;
        line-height: 1.6;
        word-break: break-word;
        background: rgb(248 250 252 / 90%);
        border-radius: 14px;
      }

      .content-desc--markdown :deep(.markdown-body) {
        font-size: inherit;
        line-height: inherit;
        color: inherit;
        background: transparent;
      }

      .content-desc--markdown :deep(.markdown-body > :first-child) {
        margin-top: 0;
      }

      .content-desc--markdown :deep(.markdown-body > :last-child) {
        margin-bottom: 0;
      }

      .score-text {
        font-size: 13px;
        font-weight: 500;
        color: var(--el-text-color-secondary);
      }

      .preview-item {
        display: grid;
        gap: 10px;
      }

      .preview-item__header {
        display: flex;
        gap: 12px;
        align-items: center;
        justify-content: space-between;
      }

      .preview-item__meta {
        display: flex;
        gap: 12px;
        align-items: center;
        min-width: 0;
      }

      .hit-source-row {
        display: flex;
        flex: none;
      }
    }
  }

  .preview-actions {
    padding: 16px 20px;
    background-color: var(--el-bg-color-page);
    border-top: 1px solid var(--el-border-color);

    .action-buttons {
      display: flex;
      gap: 12px;
      justify-content: flex-end;
    }
  }
}

/* 适配 Element Plus 加载状态样式 */
.el-list--loading .el-list-loading {
  padding: 40px 0;
}
</style>
