<script setup>
import { ref } from "vue";
import { onReachBottom } from "@dcloudio/uni-app";
import { searchSpots } from "@/api/search";
import { getTags } from "@/api/tag";
import { extractList } from "@/utils/request";
import SpotCard from "@/components/spot-card/spot-card.vue";

const keyword = ref("");
const hotTags = ref([]);
const results = ref([]);
const searched = ref(false);
const loading = ref(false);
const page = ref(1);
const pageSize = 10;
const hasMore = ref(true);

const fetchHotTags = async () => {
  try {
    const res = await getTags({ sort: "hot" });
    hotTags.value = extractList(res);
  } catch (e) {
    console.error(e);
  }
};

const doSearch = async (reset = true) => {
  const q = keyword.value.trim();
  if (!q) return;
  if (loading.value) return;
  if (!reset && !hasMore.value) return;
  loading.value = true;
  if (reset) {
    page.value = 1;
    hasMore.value = true;
    results.value = [];
  }
  searched.value = true;
  try {
    const res = await searchSpots({
      q,
      page: page.value,
      page_size: pageSize,
    });
    const list = extractList(res);
    if (reset) {
      results.value = list;
    } else {
      results.value.push(...list);
    }
    if (list.length < pageSize) {
      hasMore.value = false;
    } else {
      page.value++;
    }
  } catch (e) {
    console.error(e);
  } finally {
    loading.value = false;
  }
};

const onTagTap = (tag) => {
  keyword.value = tag.name;
  doSearch();
};

const goDetail = (id) => {
  uni.navigateTo({ url: `/pages/spot/detail?id=${id}` });
};

const loadMore = () => {
  doSearch(false);
};

onReachBottom(() => {
  if (searched.value) loadMore();
});

fetchHotTags();
</script>

<template>
  <view class="search-page">
    <view class="search-bar">
      <view class="search-input-wrap">
        <uni-icons type="search" size="16" color="#94a3b8" class="search-icon" />
        <input
          class="search-input"
          v-model="keyword"
          placeholder="搜索取景地"
          confirm-type="search"
          @confirm="doSearch()"
        />
      </view>
      <view class="search-btn" @tap="doSearch()">
        <text class="search-btn-text">搜索</text>
      </view>
    </view>

    <view v-if="!searched" class="pre-search">
      <view v-if="hotTags.length" class="hot-section">
        <text class="hot-title">热门标签</text>
        <view class="hot-tags">
          <view
            v-for="tag in hotTags"
            :key="tag.id"
            class="hot-tag"
            @tap="onTagTap(tag)"
          >
            <text class="hot-tag-text">{{ tag.name }}</text>
          </view>
        </view>
      </view>
      <view class="empty-hint">
        <uni-icons type="search" size="40" color="#94a3b8" class="empty-hint-icon" />
        <text class="empty-hint-text">输入关键词搜索取景地</text>
      </view>
    </view>

    <view v-else class="results">
      <view v-if="results.length > 0" class="result-list">
        <SpotCard
          v-for="item in results"
          :key="item.id"
          :spot="item"
          @click="goDetail(item.id)"
        />
        <view v-if="hasMore" class="load-more" @tap="loadMore">
          <text>{{ loading ? "加载中..." : "加载更多" }}</text>
        </view>
        <view v-else class="no-more">
          <text>没有更多了</text>
        </view>
      </view>

      <view v-else-if="!loading" class="no-result">
        <uni-icons type="info" size="40" color="#94a3b8" class="no-result-icon" />
        <text class="no-result-text">没有找到相关取景地</text>
      </view>

      <view v-if="loading && results.length === 0" class="loading-tip">
        <text>搜索中...</text>
      </view>
    </view>
  </view>
</template>

<style scoped>
.search-page {
  min-height: 100vh;
  background: #f5f6fa;
}

.search-bar {
  display: flex;
  align-items: center;
  padding: 16rpx 24rpx;
  background: #ffffff;
}

.search-input-wrap {
  flex: 1;
  display: flex;
  align-items: center;
  background: #f5f6fa;
  border-radius: 36rpx;
  padding: 0 24rpx;
  height: 72rpx;
}

.search-icon {
  font-size: 28rpx;
  margin-right: 12rpx;
}

.search-input {
  flex: 1;
  font-size: 28rpx;
  color: #1e293b;
}

.search-btn {
  margin-left: 16rpx;
  background: #6366f1;
  border-radius: 36rpx;
  padding: 0 32rpx;
  height: 72rpx;
  display: flex;
  align-items: center;
  justify-content: center;
}

.search-btn-text {
  color: #ffffff;
  font-size: 28rpx;
  font-weight: 500;
}

.pre-search {
  padding: 32rpx;
}

.hot-section {
  margin-bottom: 48rpx;
}

.hot-title {
  font-size: 30rpx;
  font-weight: 700;
  color: #1e293b;
  display: block;
  margin-bottom: 20rpx;
}

.hot-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 16rpx;
}

.hot-tag {
  background: #ffffff;
  padding: 14rpx 28rpx;
  border-radius: 32rpx;
  border: 2rpx solid #e2e8f0;
}

.hot-tag-text {
  font-size: 26rpx;
  color: #475569;
}

.empty-hint {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 80rpx 0;
}

.empty-hint-icon {
  font-size: 80rpx;
  margin-bottom: 20rpx;
}

.empty-hint-text {
  font-size: 28rpx;
  color: #94a3b8;
}

.results {
  padding: 24rpx 32rpx;
}

.result-list {
  padding-bottom: 32rpx;
}

.load-more {
  text-align: center;
  padding: 24rpx 0;
  color: #6366f1;
  font-size: 26rpx;
}

.no-more {
  text-align: center;
  padding: 24rpx 0;
  color: #94a3b8;
  font-size: 26rpx;
}

.no-result {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 120rpx 0;
}

.no-result-icon {
  font-size: 80rpx;
  margin-bottom: 20rpx;
}

.no-result-text {
  font-size: 28rpx;
  color: #94a3b8;
}

.loading-tip {
  text-align: center;
  padding: 60rpx 0;
  color: #94a3b8;
  font-size: 28rpx;
}
</style>
