<script setup lang="tsx">
import { computed, nextTick, ref } from 'vue';
import type { DataTableColumn } from 'naive-ui';
import { NButton, NDivider, NForm, NFormItem, NImage, NInput, NTag } from 'naive-ui';
import {
  fetchDeleteOpinion,
  fetchOpinionList,
  fetchOpinionType,
  fetchReplyOpinion
} from '@/service/api/operation/opinion-feedback';
import { useModal } from '@/components/zt/Modal/hooks/useModal';
import { useTable } from '@/components/zt/Table/hooks/useTable';

/** 解析图片字段：兼容 JSON 数组字符串、逗号分隔 URL、单个 URL */
function parseImgUrls(raw: unknown): string[] {
  if (!raw) return [];
  if (Array.isArray(raw)) return raw.filter(Boolean);
  if (typeof raw === 'string') {
    try {
      const parsed = JSON.parse(raw);
      return Array.isArray(parsed) ? parsed.filter(Boolean) : [parsed];
    } catch {
      return raw
        .split(',')
        .map(s => s.trim())
        .filter(Boolean);
    }
  }
  return [String(raw)];
}

// ========== 回复弹窗状态 ==========
const replyFormRef = ref<InstanceType<typeof NForm> | null>(null);
const replyFormData = ref({ replyContent: '' });
const currentReplyRow = ref<any>(null);

const currentImages = computed(() => parseImgUrls(currentReplyRow.value?.img));

// ========== 表格列定义 ==========
const columns: DataTableColumn<any>[] = [
  {
    title: '序号',
    key: 'index',
    align: 'center',
    width: 64,
    render(_, index) {
      return index + 1;
    }
  },
  {
    title: '反馈类型',
    key: 'opinionType',
    align: 'center',
    width: 100
  },
  {
    title: '反馈描述',
    key: 'feedbackDesc',
    align: 'center',
    ellipsis: { tooltip: true },
    minWidth: 160
  },
  {
    title: '图片',
    key: 'img',
    align: 'center',
    width: 140,
    render: row => {
      const imgs = parseImgUrls(row.img);
      if (!imgs.length) return '--';
      return (
        <div class="flex-center gap-6px">
          {imgs.slice(0, 3).map((url: string) => (
            <NImage
              src={url}
              width={44}
              height={44}
              style="border-radius: 4px; object-fit: cover; cursor: pointer; border: 1px solid #f0f0f0;"
            />
          ))}
          {imgs.length > 3 && <span class="text-12px text-#999">+{imgs.length - 3}</span>}
        </div>
      );
    }
  },
  {
    title: '反馈用户',
    key: 'mobile',
    align: 'center',
    width: 100,
    ellipsis: { tooltip: true }
  },
  {
    title: '联系电话',
    key: 'contact',
    align: 'center',
    width: 130
  },
  {
    title: '回复内容',
    key: 'replyContent',
    align: 'center',
    ellipsis: { tooltip: true },
    minWidth: 140
  },
  {
    title: '回复时间',
    key: 'replyTime',
    align: 'center',
    width: 170
  },
  {
    title: '回复状态',
    key: 'replyStatus',
    align: 'center',
    width: 100,
    render: row => {
      if (row.replyStatus === 1) {
        return <NTag type="success">已回复</NTag>;
      }
      return <NTag type="error">未回复</NTag>;
    }
  },
  {
    title: '创建时间',
    key: 'createTime',
    align: 'center',
    width: 170
  }
];

// ========== 表格 ==========
const [registerTable, { refresh }] = useTable({
  searchFormConfig: {
    schemas: [
      {
        field: 'opinionType',
        label: '反馈类型',
        component: 'ApiSelect',
        componentProps: {
          api: fetchOpinionType,
          labelFeild: 'name',
          valueFeild: 'name'
        }
      },
      {
        field: 'mobile',
        label: '反馈用户',
        component: 'NInput',
        componentProps: {
          placeholder: '请输入反馈用户',
          clearable: true
        }
      },
      {
        field: 'contact',
        label: '联系电话',
        component: 'NInput',
        componentProps: {
          placeholder: '请输入联系电话',
          clearable: true
        }
      },
      {
        field: 'createTime',
        label: '反馈时间',
        component: 'NDatePicker',
        componentProps: {
          type: 'datetimerange',
          defaultTime: ['00:00:00', '23:59:59']
        }
      }
    ],
    inline: false,
    size: 'small',
    labelPlacement: 'left',
    isFull: false
  },
  tableConfig: {
    keyField: 'id',
    title: '意见反馈列表',
    scrollX: 1500,
    showAddButton: false,
    opWdith: 150,
    fieldMapToTime: [['createTime', ['startTime', 'endTime']]]
  }
});

// ========== 回复弹窗 ==========
const [registerReplyModal, { openModal: openReplyModal, closeModal: closeReplyModal, setSubLoading }] = useModal({
  title: '回复',
  width: 600,
  showFooter: true,
  subBtuText: '确定'
});

function handleReply(row: any) {
  currentReplyRow.value = row;
  replyFormData.value = { replyContent: '' };
  nextTick(() => {
    openReplyModal();
  });
}

async function handleReplySubmit() {
  if (!replyFormData.value.replyContent.trim()) {
    window.$message?.error('请输入回复内容');
    return;
  }
  setSubLoading(true);
  const { error } = await fetchReplyOpinion({
    id: currentReplyRow.value.id,
    replyContent: replyFormData.value.replyContent
  });
  setSubLoading(false);
  if (!error) {
    window.$message?.success('回复成功');
    closeReplyModal();
    refresh();
  }
}

function handleDelete(row: any) {
  window.$dialog?.info({
    title: '删除确认',
    content: '确定要删除该反馈吗？',
    positiveText: '确定',
    negativeText: '取消',
    onPositiveClick: async () => {
      const { error } = await fetchDeleteOpinion(row.id);
      if (!error) {
        window.$message?.success('删除成功');
        refresh();
      }
    }
  });
}
</script>

<template>
  <LayoutTable>
    <ZTable :columns="columns" :api="fetchOpinionList" @register="registerTable">
      <template #op="{ row }">
        <template v-if="row.replyStatus === 1">
          <NButton size="small" type="error" ghost @click="handleDelete(row)">删除</NButton>
        </template>
        <template v-else>
          <NButton size="small" type="primary" ghost @click="handleReply(row)">回复</NButton>
          <NButton size="small" type="error" ghost @click="handleDelete(row)">删除</NButton>
        </template>
      </template>
    </ZTable>

    <BasicModal @register="registerReplyModal" @ok="handleReplySubmit">
      <template #default>
        <div v-if="currentReplyRow" class="reply-content">
          <!-- 只读信息展示 -->
          <div class="info-grid">
            <div class="info-item">
              <span class="info-label">反馈类型</span>
              <span class="info-value">{{ currentReplyRow.opinionType }}</span>
            </div>
            <div class="info-item">
              <span class="info-label">反馈描述</span>
              <span class="info-value">{{ currentReplyRow.feedbackDesc }}</span>
            </div>
            <div class="info-item">
              <span class="info-label">图片</span>
              <div class="info-value">
                <template v-if="currentImages.length">
                  <NImage
                    v-for="(url, idx) in currentImages"
                    :key="idx"
                    :src="url"
                    width="72"
                    height="72"
                    class="preview-img"
                  />
                </template>
                <span v-else class="text-#999">暂无图片</span>
              </div>
            </div>
          </div>

          <NDivider />

          <!-- 回复输入 -->
          <NForm ref="replyFormRef" :model="replyFormData" label-placement="top">
            <NFormItem
              label="反馈回复"
              path="replyContent"
              :rule="{
                required: true,
                message: '请输入回复内容',
                trigger: 'blur'
              }"
            >
              <NInput
                v-model:value="replyFormData.replyContent"
                type="textarea"
                placeholder="请输入回复"
                :rows="4"
                :maxlength="500"
                show-count
              />
            </NFormItem>
          </NForm>
        </div>
      </template>
    </BasicModal>
  </LayoutTable>
</template>

<style scoped>
.reply-content {
  padding: 0 4px;
}

.info-grid {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.info-item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  font-size: 14px;
  line-height: 1.6;
}

.info-label {
  flex-shrink: 0;
  min-width: 76px;
  font-weight: 500;
  color: #333;
  text-align: right;
}

.info-value {
  flex: 1;
  color: #666;
  word-break: break-all;
}

.preview-img {
  border-radius: 4px;
  object-fit: cover;
  cursor: pointer;
  border: 1px solid #f0f0f0;
  margin-right: 8px;
  margin-bottom: 8px;
}
</style>
