<script setup lang="ts">
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
import {
  createDemandFeedback,
  fetchDemandFeedback,
} from '../api/videoDiscovery'
import type {
  DemandFeedbackItem,
  DemandFeedbackTarget,
  FeedbackAction,
  FeedbackSummary,
} from '../types/videoDiscovery'

const props = defineProps<{
  open: boolean
  target: DemandFeedbackTarget | null
}>()

const emit = defineEmits<{
  close: []
  submitted: [summary: FeedbackSummary]
}>()

const ACTIONS: Array<{ value: FeedbackAction; label: string }> = [
  { value: 'support', label: '认可' },
  { value: 'oppose', label: '不认可' },
  { value: 'correct', label: '纠错' },
  { value: 'supplement', label: '补充' },
]

const REASONS: Record<string, Array<{ value: string; label: string }>> = {
  demand: [
    { value: 'not_a_demand', label: '需求不成立' },
    { value: 'wrong_grade', label: '等级不合适' },
    { value: 'wrong_category', label: '分类不准确' },
    { value: 'unclear_wording', label: '需求表述不清' },
    { value: 'wrong_reason', label: '判断原因不准确' },
    { value: 'missing_demand', label: '缺少需求' },
    { value: 'other', label: '其他' },
  ],
  video: [
    { value: 'irrelevant', label: '与需求不相关' },
    { value: 'weak_relevance', label: '相关性弱' },
    { value: 'unavailable', label: '视频失效' },
    { value: 'duplicate', label: '视频重复' },
    { value: 'wrong_info', label: '标题或信息错误' },
    { value: 'missing_video', label: '缺少相关视频' },
    { value: 'other', label: '其他' },
  ],
  hit_content: [
    { value: 'not_hit', label: '内容未命中' },
    { value: 'wrong_point_type', label: '点位类型错误' },
    { value: 'inaccurate_wording', label: '表述不准确' },
    { value: 'wrong_reason', label: '命中原因不准确' },
    { value: 'duplicate', label: '内容重复' },
    { value: 'missing_content', label: '缺少命中内容' },
    { value: 'other', label: '其他' },
  ],
}

const action = ref<FeedbackAction | null>(null)
const reasonCode = ref('')
const content = ref('')
const submitting = ref(false)
const submitError = ref<string | null>(null)
const history = ref<DemandFeedbackItem[]>([])
const historyTotal = ref(0)
const historyLoading = ref(false)
const historyError = ref<string | null>(null)

const targetLabel = computed(() => {
  if (props.target?.target_type === 'demand') return '需求'
  if (props.target?.target_type === 'video') return '视频'
  return '命中内容'
})

const reasonOptions = computed(() => REASONS[props.target?.target_type ?? 'demand'])
const dirty = computed(() => Boolean(action.value || reasonCode.value || content.value.trim()))
const canSubmit = computed(() => {
  if (!action.value || !props.target || submitting.value) return false
  if (action.value === 'oppose' && !reasonCode.value) return false
  if (
    (action.value === 'correct' || action.value === 'supplement')
    && !content.value.trim()
  ) return false
  return true
})

watch(
  [() => props.open, () => props.target],
  ([open]) => {
    if (!open || !props.target) return
    action.value = null
    reasonCode.value = ''
    content.value = ''
    submitError.value = null
    void loadHistory()
  },
)

watch(action, (value) => {
  if (value === 'support') reasonCode.value = ''
})

async function loadHistory() {
  if (!props.target) return
  historyLoading.value = true
  historyError.value = null
  try {
    const response = await fetchDemandFeedback(props.target)
    history.value = response.items ?? []
    historyTotal.value = response.total ?? 0
  } catch (error) {
    historyError.value = error instanceof Error ? error.message : String(error)
  } finally {
    historyLoading.value = false
  }
}

function requestId(): string {
  if (typeof crypto.randomUUID === 'function') return crypto.randomUUID()
  return `${Date.now()}-${Math.random().toString(16).slice(2)}`
}

async function submit() {
  if (!canSubmit.value || !props.target || !action.value) return
  submitting.value = true
  submitError.value = null
  try {
    const response = await createDemandFeedback({
      client_request_id: requestId(),
      target_type: props.target.target_type,
      demand_grade_id: props.target.demand_grade_id,
      video_id: props.target.video_id,
      demand_video_expansion_id: props.target.demand_video_expansion_id,
      feedback_action: action.value,
      reason_code: reasonCode.value || undefined,
      content: content.value.trim() || undefined,
    })
    emit('submitted', response.feedback_summary)
    emit('close')
  } catch (error) {
    submitError.value = error instanceof Error ? error.message : String(error)
  } finally {
    submitting.value = false
  }
}

function close() {
  if (submitting.value) return
  if (dirty.value && !window.confirm('反馈尚未提交，确定关闭吗？')) return
  emit('close')
}

function onKeydown(event: KeyboardEvent) {
  if (event.key === 'Escape' && props.open) close()
}

function actionLabel(value: FeedbackAction): string {
  return ACTIONS.find((item) => item.value === value)?.label ?? value
}

function reasonLabel(value: string | null): string {
  if (!value) return ''
  return reasonOptions.value.find((item) => item.value === value)?.label ?? value
}

function formatTime(value: string | null): string {
  if (!value) return '—'
  const date = new Date(value)
  if (Number.isNaN(date.getTime())) return value
  return new Intl.DateTimeFormat('zh-CN', {
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
  }).format(date)
}

onMounted(() => window.addEventListener('keydown', onKeydown))
onBeforeUnmount(() => window.removeEventListener('keydown', onKeydown))
</script>

<template>
  <Teleport to="body">
    <Transition name="feedback-fade">
      <div v-if="open && target" class="feedback-overlay" @click.self="close">
        <aside class="feedback-drawer" role="dialog" aria-modal="true" :aria-label="`${targetLabel}反馈`">
          <header class="drawer-head">
            <div>
              <span>反馈 · {{ targetLabel }}</span>
              <h2>{{ target.title }}</h2>
            </div>
            <button type="button" aria-label="关闭反馈" @click="close">×</button>
          </header>

          <div class="drawer-body">
            <section class="target-context" aria-label="反馈对象">
              <div v-for="item in target.context" :key="item.label">
                <span>{{ item.label }}</span>
                <strong>{{ item.value }}</strong>
              </div>
            </section>

            <section class="form-section">
              <div class="section-title">
                <strong>你的判断</strong>
                <span>必填</span>
              </div>
              <div class="action-options">
                <button
                  v-for="item in ACTIONS"
                  :key="item.value"
                  type="button"
                  :class="{ active: action === item.value }"
                  @click="action = item.value"
                >
                  {{ item.label }}
                </button>
              </div>
            </section>

            <section v-if="action && action !== 'support'" class="form-section">
              <div class="section-title">
                <strong>问题原因</strong>
                <span>{{ action === 'oppose' ? '必填' : '选填' }}</span>
              </div>
              <div class="reason-options">
                <button
                  v-for="item in reasonOptions"
                  :key="item.value"
                  type="button"
                  :class="{ active: reasonCode === item.value }"
                  @click="reasonCode = reasonCode === item.value ? '' : item.value"
                >
                  {{ item.label }}
                </button>
              </div>
            </section>

            <section class="form-section">
              <div class="section-title">
                <strong>补充说明</strong>
                <span>{{ action === 'correct' || action === 'supplement' ? '必填' : '选填' }}</span>
              </div>
              <textarea
                v-model="content"
                maxlength="1000"
                rows="4"
                placeholder="请说明判断依据或建议的正确内容"
              />
              <div class="text-count">{{ content.length }} / 1000</div>
            </section>

            <p v-if="submitError" class="feedback-error">{{ submitError }}</p>

            <section class="history-section">
              <div class="section-title">
                <strong>反馈记录</strong>
                <span>{{ historyTotal }} 条</span>
              </div>
              <div v-if="historyLoading" class="history-state">正在加载反馈记录…</div>
              <div v-else-if="historyError" class="history-state error">{{ historyError }}</div>
              <div v-else-if="history.length" class="history-list">
                <article v-for="item in history" :key="item.id">
                  <header>
                    <strong>
                      {{ item.feedback_user.display_name }}
                      <small>@{{ item.feedback_user.username }}</small>
                    </strong>
                    <time>{{ formatTime(item.created_at) }}</time>
                  </header>
                  <div class="history-tags">
                    <span>{{ actionLabel(item.feedback_action) }}</span>
                    <span v-if="item.reason_code">{{ reasonLabel(item.reason_code) }}</span>
                  </div>
                  <p v-if="item.content">{{ item.content }}</p>
                </article>
              </div>
              <div v-else class="history-state">暂无反馈记录</div>
            </section>
          </div>

          <footer class="drawer-actions">
            <button type="button" class="cancel" @click="close">取消</button>
            <button type="button" class="submit" :disabled="!canSubmit" @click="submit">
              {{ submitting ? '提交中…' : '提交反馈' }}
            </button>
          </footer>
        </aside>
      </div>
    </Transition>
  </Teleport>
</template>

<style scoped>
.feedback-overlay {
  position: fixed;
  z-index: 1000;
  inset: 0;
  display: flex;
  justify-content: flex-end;
  background: rgba(18, 28, 22, 0.34);
  backdrop-filter: blur(2px);
}

.feedback-drawer {
  width: min(470px, 100vw);
  height: 100%;
  display: flex;
  flex-direction: column;
  background: #fff;
  color: #17211b;
  box-shadow: -18px 0 48px rgba(18, 38, 25, 0.16);
}

.drawer-head {
  min-height: 82px;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 18px 20px 15px;
  border-bottom: 1px solid #e5eae6;
}

.drawer-head span {
  color: #397354;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: 0.12em;
}

.drawer-head h2 {
  margin: 5px 0 0;
  font-family: Georgia, 'Songti SC', serif;
  font-size: 18px;
  line-height: 1.35;
}

.drawer-head button {
  width: 30px;
  height: 30px;
  flex: 0 0 auto;
  border: 1px solid #dce3dd;
  border-radius: 8px;
  background: #f8faf8;
  color: #68736b;
  font-size: 19px;
  cursor: pointer;
}

.drawer-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 16px 20px 24px;
}

.target-context {
  display: grid;
  gap: 7px;
  padding: 12px 13px;
  border: 1px solid #dce6de;
  border-radius: 10px;
  background: #f4f8f5;
}

.target-context div {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: 8px;
}

.target-context span {
  color: #829087;
  font-size: 10px;
}

.target-context strong {
  overflow-wrap: anywhere;
  color: #334239;
  font-size: 11px;
  line-height: 1.45;
}

.form-section,
.history-section {
  margin-top: 18px;
}

.section-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 9px;
}

.section-title strong {
  font-size: 12px;
}

.section-title span {
  color: #8a958d;
  font-size: 9px;
}

.action-options {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 7px;
}

.action-options button,
.reason-options button {
  border: 1px solid #d8dfd9;
  border-radius: 8px;
  background: #fff;
  color: #58645c;
  font-size: 11px;
  cursor: pointer;
}

.action-options button {
  height: 36px;
  font-weight: 700;
}

.reason-options {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}

.reason-options button {
  min-height: 30px;
  padding: 5px 9px;
}

.action-options button:hover,
.reason-options button:hover,
.action-options button.active,
.reason-options button.active {
  border-color: #3d7656;
  background: #e9f2ec;
  color: #275b40;
}

textarea {
  width: 100%;
  box-sizing: border-box;
  resize: vertical;
  padding: 10px 11px;
  border: 1px solid #d8dfd9;
  border-radius: 9px;
  outline: none;
  color: #26332a;
  font: inherit;
  font-size: 12px;
  line-height: 1.55;
}

textarea:focus {
  border-color: #6b957c;
  box-shadow: 0 0 0 3px rgba(53, 110, 78, 0.1);
}

.text-count {
  margin-top: 4px;
  color: #98a19a;
  font-size: 9px;
  text-align: right;
}

.feedback-error {
  margin: 12px 0 0;
  padding: 9px 10px;
  border-radius: 8px;
  background: #fff0ec;
  color: #a8462c;
  font-size: 11px;
}

.history-section {
  padding-top: 17px;
  border-top: 1px solid #e8ece9;
}

.history-list {
  display: grid;
  gap: 8px;
}

.history-list article {
  padding: 10px 11px;
  border: 1px solid #e1e6e2;
  border-radius: 9px;
  background: #fbfcfb;
}

.history-list header {
  display: flex;
  justify-content: space-between;
  gap: 8px;
}

.history-list header strong {
  font-size: 11px;
}

.history-list header small {
  margin-left: 5px;
  color: #8b958e;
  font-size: 9px;
  font-weight: 500;
}

.history-list time {
  color: #919a93;
  font-size: 9px;
}

.history-tags {
  display: flex;
  gap: 5px;
  margin-top: 7px;
}

.history-tags span {
  padding: 2px 6px;
  border-radius: 999px;
  background: #e7efe9;
  color: #39604a;
  font-size: 9px;
  font-weight: 700;
}

.history-list p {
  margin: 7px 0 0;
  color: #5f6b63;
  font-size: 11px;
  line-height: 1.5;
  white-space: pre-wrap;
}

.history-state {
  padding: 12px;
  border-radius: 8px;
  background: #f7f9f7;
  color: #89928b;
  font-size: 10px;
  text-align: center;
}

.history-state.error {
  color: #a8462c;
}

.drawer-actions {
  display: flex;
  justify-content: flex-end;
  gap: 9px;
  padding: 13px 20px;
  border-top: 1px solid #e3e8e4;
  background: #fbfcfb;
}

.drawer-actions button {
  height: 36px;
  padding: 0 16px;
  border-radius: 8px;
  font-size: 11px;
  font-weight: 800;
  cursor: pointer;
}

.drawer-actions .cancel {
  border: 1px solid #d4dcd6;
  background: #fff;
  color: #68736b;
}

.drawer-actions .submit {
  border: 1px solid #315f47;
  background: #315f47;
  color: #fff;
}

.drawer-actions .submit:disabled {
  border-color: #cdd5cf;
  background: #cdd5cf;
  cursor: not-allowed;
}

.feedback-fade-enter-active,
.feedback-fade-leave-active {
  transition: opacity 0.18s ease;
}

.feedback-fade-enter-active .feedback-drawer,
.feedback-fade-leave-active .feedback-drawer {
  transition: transform 0.18s ease;
}

.feedback-fade-enter-from,
.feedback-fade-leave-to {
  opacity: 0;
}

.feedback-fade-enter-from .feedback-drawer,
.feedback-fade-leave-to .feedback-drawer {
  transform: translateX(24px);
}

@media (max-width: 640px) {
  .feedback-drawer {
    width: 100%;
  }
}
</style>
