<script setup lang="ts">
import { computed, ref } from 'vue'
import type { ResultItem } from './types'

const props = defineProps<{
  items: ResultItem[]
  selectedId: string | null
}>()

const emit = defineEmits<{
  'update:selectedId': [value: string]
  'update:field': [id: string, field: 'instruction' | 'input' | 'output', value: string]
  'restore:item': [id: string]
}>()

const search = ref('')
const invalidOnly = ref(false)
const selectedItem = computed(() => props.items.find((item) => item.id === props.selectedId) ?? props.items[0])
const selectedIndex = computed(() => props.items.findIndex((item) => item.id === selectedItem.value?.id))

const filteredItems = computed(() => props.items.filter((item, index) => {
  const keyword = search.value.trim().toLowerCase()
  const matchesSearch = !keyword
    || item.instruction.toLowerCase().includes(keyword)
    || item.output.toLowerCase().includes(keyword)
    || String(index + 1).includes(keyword)
  return matchesSearch && (!invalidOnly.value || item.status === 'invalid')
}))

function selectRelative(offset: number) {
  if (!props.items.length) return
  const nextIndex = Math.min(Math.max(selectedIndex.value + offset, 0), props.items.length - 1)
  emit('update:selectedId', props.items[nextIndex].id)
}
</script>

<template>
  <section class="result-step">
    <div class="result-workspace">
      <aside class="result-list-pane">
        <div class="pane-header"><strong>生成结果</strong><span>共 {{ items.length }} 条</span></div>
        <div class="result-toolbar">
          <el-input v-model="search" clearable size="small" placeholder="搜索结果">
            <template #prefix><i class="fa fa-search" /></template>
          </el-input>
          <el-checkbox v-model="invalidOnly">仅看错误</el-checkbox>
        </div>
        <div class="result-list">
          <button
            v-for="item in filteredItems"
            :key="item.id"
            type="button"
            class="result-item"
            :class="{ 'is-active': item.id === selectedItem?.id }"
            @click="emit('update:selectedId', item.id)"
          >
            <span class="result-index">#{{ String(items.findIndex((entry) => entry.id === item.id) + 1).padStart(3, '0') }}</span>
            <span class="result-copy">
              <strong>{{ item.instruction || '未填写指令' }}</strong>
              <small>{{ item.output || '未填写输出' }}</small>
            </span>
            <i class="fa" :class="item.status === 'invalid' ? 'fa-exclamation-circle is-error' : 'fa-check-circle is-valid'" />
          </button>
        </div>
      </aside>

      <div v-if="selectedItem" class="result-editor-pane">
        <div class="pane-header">
          <div>
            <strong>结果 #{{ String(selectedIndex + 1).padStart(3, '0') }}</strong>
            <span v-if="selectedItem.status === 'modified'" class="modified-label">已修改</span>
          </div>
          <el-button link @click="emit('restore:item', selectedItem.id)"><i class="fa fa-undo" /> 恢复生成结果</el-button>
        </div>

        <div class="field-editor">
          <label>Instruction <em>必填</em></label>
          <el-input
            :model-value="selectedItem.instruction"
            type="textarea"
            :rows="3"
            @update:model-value="emit('update:field', selectedItem.id, 'instruction', $event)"
          />
        </div>
        <div class="field-editor">
          <label>Input <span>选填</span></label>
          <el-input
            :model-value="selectedItem.input"
            type="textarea"
            :rows="2"
            @update:model-value="emit('update:field', selectedItem.id, 'input', $event)"
          />
        </div>
        <div class="field-editor">
          <label>Output <em>必填</em></label>
          <el-input
            :model-value="selectedItem.output"
            type="textarea"
            :rows="7"
            @update:model-value="emit('update:field', selectedItem.id, 'output', $event)"
          />
        </div>
        <div v-if="selectedItem.error" class="validation-error">
          <i class="fa fa-exclamation-circle" /> {{ selectedItem.error }}
        </div>
        <div v-else class="validation-success">
          <i class="fa fa-check-circle" /> 字段校验通过
        </div>
        <div class="editor-pagination">
          <el-button :disabled="selectedIndex <= 0" @click="selectRelative(-1)">上一条</el-button>
          <span>{{ selectedIndex + 1 }} / {{ items.length }}</span>
          <el-button :disabled="selectedIndex >= items.length - 1" @click="selectRelative(1)">下一条</el-button>
        </div>
      </div>
    </div>
  </section>
</template>

<style scoped lang="scss">
.result-step {
  min-width: 0;
}


.result-workspace {
  display: grid;
  grid-template-columns: minmax(280px, 34fr) minmax(480px, 66fr);
  min-height: clamp(420px, calc(100vh - 500px), 590px);
  overflow: hidden;
  border: 1px solid #e2e5ec;
  border-radius: 9px;
}

.result-list-pane {
  min-width: 0;
  border-right: 1px solid #e5e8ee;
}

.pane-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 52px;
  padding: 0 15px;
  color: #344054;
  background: #fff;
  border-bottom: 1px solid #e8ebf0;
  font-size: 13px;

  > div {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  > span,
  .modified-label {
    color: #8a93a3;
    font-size: 11px;
  }
}

.result-toolbar {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 10px;
  border-bottom: 1px solid #edf0f5;
}

.result-list {
  height: 476px;
  padding: 7px;
  overflow: auto;
}

.result-item {
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr) 18px;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 62px;
  padding: 9px;
  text-align: left;
  background: #fff;
  border: 1px solid transparent;
  border-bottom-color: #edf0f5;
  cursor: pointer;

  &:hover,
  &.is-active {
    background: #f7f6ff;
  }

  &.is-active {
    border-color: #5b50f2;
    border-radius: 6px;
  }
}

.result-index {
  color: #667085;
  font-size: 11px;
}

.result-copy {
  min-width: 0;

  strong,
  small {
    display: block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  strong {
    color: #344054;
    font-size: 12px;
  }

  small {
    margin-top: 5px;
    color: #98a2b3;
    font-size: 10px;
  }
}

.is-valid {
  color: #2ca66a;
}

.is-error {
  color: #d97706;
}

.result-editor-pane {
  min-width: 0;
}

.field-editor {
  padding: 13px 18px 0;

  label {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 7px;
    color: #344054;
    font-size: 12px;
    font-weight: 650;
  }

  em {
    color: #e05252;
    font-size: 10px;
    font-style: normal;
    font-weight: 400;
  }

  span {
    color: #98a2b3;
    font-size: 10px;
    font-weight: 400;
  }
}

.validation-error,
.validation-success {
  margin: 12px 18px 0;
  padding: 9px 11px;
  font-size: 11px;
  border-radius: 6px;
}

.validation-error {
  color: #b45309;
  background: #fff7e8;
}

.validation-success {
  color: #25895c;
  background: #edf9f3;
}

.editor-pagination {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  padding: 12px 18px;

  span {
    color: #8a93a3;
    font-size: 11px;
  }
}

@media (max-width: 900px) {
  .result-workspace {
    grid-template-columns: minmax(0, 1fr);
  }

  .result-list-pane {
    border-right: 0;
    border-bottom: 1px solid #e5e8ee;
  }

  .result-list {
    height: 260px;
  }
}
</style>
